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.
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 will get values like 4 ins 31.51 secs.
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 and optimize
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
- * Allow alternative formatting for output
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
@@ -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 << pluralize(years, 'yr')
38
- result << pluralize(months, 'mo')
39
- result << pluralize(days, 'day')
40
- result << pluralize(hours, 'hr')
41
- result << pluralize(minutes, 'min')
42
- result << pluralize(seconds, 'sec')
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
- # A poor man's pluralizer
53
- def pluralize(number, word)
54
- return '' if number == 0
55
- res = "#{number} #{word}"
56
- res << 's' unless number == 1
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
- '1 min 20 secs' => 60 + 20,
58
- '1 min 20.51 secs' => 60 + 20.51,
59
- '3 mins 20.51 secs' => 3 * 60 + 20.51,
60
- '4 hrs 1 min 1 sec' => 4 * 3600 + 60 + 1,
61
- '3 mins 4 secs' => 3 * 60 + 4,
62
- '2 hrs 20 mins' => 2 * 3600 + 20 * 60,
63
- '1 mo 1 day' => 1 * 30 * 24 * 3600 + 24 * 3600,
64
- '6 mos 1 day' => 6 * 30 * 24 * 3600 + 24 * 3600,
65
- '6 mos 2 days' => 6 * 30 * 24 * 3600 + 2 * 24 * 3600,
66
- '2 hrs 30 mins' => 2.5 * 3600
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
- it "should properly output a duration of #{v}" do
72
- ChronicDuration.output(v).should == k
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.1
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-14 00:00:00 -08:00
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