hpoydar-chronic_duration 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|