hpoydar-chronic_duration 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/{LICENSE → MIT-LICENSE} +0 -0
- data/README.rdoc +11 -4
- data/lib/chronic_duration.rb +47 -17
- data/spec/chronic_duration_spec.rb +46 -14
- metadata +3 -3
data/{LICENSE → MIT-LICENSE}
RENAMED
File without changes
|
data/README.rdoc
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
A simple Ruby natural language parser for elapsed time. (For example, 4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in seconds. Will return an integer unless you get tricky and need a float. (4 minutes and 13.47 seconds, for example.)
|
4
4
|
|
5
|
-
The reverse can also be accomplished with the output method. So pass in seconds and you
|
5
|
+
The reverse can also be accomplished with the output method. So pass in seconds and you can get strings like 4 mins 31.51 secs (default format), 4h 3m 30s, or 4:01:29.
|
6
6
|
|
7
7
|
== Installation
|
8
8
|
|
@@ -17,6 +17,12 @@ The reverse can also be accomplished with the output method. So pass in seconds
|
|
17
17
|
=> 270
|
18
18
|
>> ChronicDuration.output(270)
|
19
19
|
=> 4 mins 30 secs
|
20
|
+
>> ChronicDuration.output(270, :short)
|
21
|
+
=> 4m 30s
|
22
|
+
>> ChronicDuration.output(270, :long)
|
23
|
+
=> 4 minutes 30 seconds
|
24
|
+
>> ChronicDuration.output(270, :chrono)
|
25
|
+
=> 4:30
|
20
26
|
|
21
27
|
Nil is returned if the string can't be parsed
|
22
28
|
|
@@ -35,7 +41,8 @@ Examples of parse-able strings:
|
|
35
41
|
|
36
42
|
== TODO
|
37
43
|
|
38
|
-
* Benchmark
|
39
|
-
* Context specific matching (E.g., for '4m30s', assume 'm' is minutes)
|
44
|
+
* Benchmark, optimize
|
45
|
+
* Context specific matching (E.g., for '4m30s', assume 'm' is minutes not months)
|
40
46
|
* Smartly parse vacation-like durations (E.g., '4 days and 3 nights')
|
41
|
-
*
|
47
|
+
* :chrono output option should probably change to something like 4 days 4:00:12 instead of 4:04:00:12
|
48
|
+
* Correct rdoc whine on gem install
|
data/lib/chronic_duration.rb
CHANGED
@@ -7,10 +7,12 @@ module ChronicDuration
|
|
7
7
|
end
|
8
8
|
|
9
9
|
# Refactor, DRY up, make recursive
|
10
|
-
def output(seconds)
|
10
|
+
def output(seconds, opts = {})
|
11
|
+
|
12
|
+
opts[:format] ||= :default
|
11
13
|
|
12
14
|
years = months = days = hours = minutes = 0
|
13
|
-
|
15
|
+
|
14
16
|
if seconds >= 60
|
15
17
|
minutes = (seconds / 60).to_i
|
16
18
|
seconds = seconds % 60
|
@@ -32,28 +34,56 @@ module ChronicDuration
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
joiner = ' '
|
38
|
+
process = nil
|
39
|
+
|
40
|
+
case opts[:format]
|
41
|
+
when :short
|
42
|
+
dividers = {
|
43
|
+
:years => 'y', :months => 'm', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
|
44
|
+
when :default
|
45
|
+
dividers = {
|
46
|
+
:years => ' yr', :months => ' mo', :days => ' day', :hours => ' hr', :minutes => ' min', :seconds => ' sec',
|
47
|
+
:pluralize => true }
|
48
|
+
when :long
|
49
|
+
dividers = {
|
50
|
+
:years => ' year', :months => ' month', :days => ' day', :hours => ' hour', :minutes => ' minute', :seconds => ' second',
|
51
|
+
:pluralize => true }
|
52
|
+
when :chrono
|
53
|
+
dividers = {
|
54
|
+
:years => ':', :months => ':', :days => ':', :hours => ':', :minutes => ':', :seconds => ':', :keep_zero => true }
|
55
|
+
process = lambda do |str|
|
56
|
+
# Pad zeros
|
57
|
+
# Get rid of lead off times if they are zero
|
58
|
+
# Get rid of lead off zero
|
59
|
+
# Get rid of trailing :
|
60
|
+
str.gsub(/\b\d\b/) { |d| ("%02d" % d) }.gsub(/^(00:)+/, '').gsub(/^0/, '').gsub(/:$/, '')
|
61
|
+
end
|
62
|
+
joiner = ''
|
63
|
+
end
|
64
|
+
|
35
65
|
result = []
|
66
|
+
[:years, :months, :days, :hours, :minutes, :seconds].each do |t|
|
67
|
+
result << humanize_time_unit( eval(t.to_s), dividers[t], dividers[:pluralize], dividers[:keep_zero] )
|
68
|
+
end
|
36
69
|
|
37
|
-
result
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
result = result.join(' ').squeeze(' ').strip
|
45
|
-
return nil if result.length == 0
|
70
|
+
result = result.join(joiner).squeeze(' ').strip
|
71
|
+
|
72
|
+
if process
|
73
|
+
result = process.call(result)
|
74
|
+
end
|
75
|
+
|
76
|
+
result.length == 0 ? nil : result
|
46
77
|
|
47
|
-
result
|
48
78
|
end
|
49
79
|
|
50
80
|
private
|
51
81
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
res << 's'
|
82
|
+
def humanize_time_unit(number, unit, pluralize, keep_zero)
|
83
|
+
return '' if number == 0 && !keep_zero
|
84
|
+
res = "#{number}#{unit}"
|
85
|
+
# A poor man's pluralizer
|
86
|
+
res << 's' if !(number == 1) && pluralize
|
57
87
|
res
|
58
88
|
end
|
59
89
|
|
@@ -52,24 +52,56 @@ describe ChronicDuration, '.output' do
|
|
52
52
|
ChronicDuration.parse('gobblygoo').should be_nil
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
55
|
@exemplars = {
|
57
|
-
|
58
|
-
|
59
|
-
'
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
56
|
+
(60 + 20) =>
|
57
|
+
{
|
58
|
+
:short => '1m 20s',
|
59
|
+
:default => '1 min 20 secs',
|
60
|
+
:long => '1 minute 20 seconds',
|
61
|
+
:chrono => '1:20'
|
62
|
+
},
|
63
|
+
(60 + 20.51) =>
|
64
|
+
{
|
65
|
+
:short => '1m 20.51s',
|
66
|
+
:default => '1 min 20.51 secs',
|
67
|
+
:long => '1 minute 20.51 seconds',
|
68
|
+
:chrono => '1:20.51'
|
69
|
+
},
|
70
|
+
(4 * 3600 + 60 + 1) =>
|
71
|
+
{
|
72
|
+
:short => '4h 1m 1s',
|
73
|
+
:default => '4 hrs 1 min 1 sec',
|
74
|
+
:long => '4 hours 1 minute 1 second',
|
75
|
+
:chrono => '4:01:01'
|
76
|
+
},
|
77
|
+
(2 * 3600 + 20 * 60) =>
|
78
|
+
{
|
79
|
+
:short => '2h 20m',
|
80
|
+
:default => '2 hrs 20 mins',
|
81
|
+
:long => '2 hours 20 minutes',
|
82
|
+
:chrono => '2:20'
|
83
|
+
},
|
84
|
+
(2 * 3600 + 20 * 60) =>
|
85
|
+
{
|
86
|
+
:short => '2h 20m',
|
87
|
+
:default => '2 hrs 20 mins',
|
88
|
+
:long => '2 hours 20 minutes',
|
89
|
+
:chrono => '2:20:00'
|
90
|
+
},
|
91
|
+
(6 * 30 * 24 * 3600 + 24 * 3600) =>
|
92
|
+
{
|
93
|
+
:short => '6m 1d',
|
94
|
+
:default => '6 mos 1 day',
|
95
|
+
:long => '6 months 1 day',
|
96
|
+
:chrono => '6:01:00:00:00' # Yuck. FIXME
|
97
|
+
}
|
67
98
|
}
|
68
99
|
|
69
|
-
|
70
100
|
@exemplars.each do |k, v|
|
71
|
-
|
72
|
-
|
101
|
+
v.each do |key, val|
|
102
|
+
it "should properly output a duration of #{k} seconds as #{val} using the #{key.to_s} format option" do
|
103
|
+
ChronicDuration.output(k, :format => key).should == val
|
104
|
+
end
|
73
105
|
end
|
74
106
|
end
|
75
107
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hpoydar-chronic_duration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henry Poydar
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-16 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,7 +23,7 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- lib/chronic_duration.rb
|
26
|
-
- LICENSE
|
26
|
+
- MIT-LICENSE
|
27
27
|
- Rakefile
|
28
28
|
- README.rdoc
|
29
29
|
has_rdoc: true
|