hpoydar-chronic_duration 0.6.0 → 0.6.1
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.
- metadata +6 -12
- data/MIT-LICENSE +0 -22
- data/README.rdoc +0 -52
- data/Rakefile +0 -17
- data/lib/chronic_duration.rb +0 -198
- data/lib/numerizer.rb +0 -97
- data/spec/chronic_duration_spec.rb +0 -150
- data/spec/spec_helper.rb +0 -4
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.6.
|
4
|
+
version: 0.6.1
|
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-02-
|
12
|
+
date: 2009-02-17 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -21,12 +21,8 @@ extensions: []
|
|
21
21
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
|
-
files:
|
25
|
-
|
26
|
-
- lib/numerizer.rb
|
27
|
-
- MIT-LICENSE
|
28
|
-
- Rakefile
|
29
|
-
- README.rdoc
|
24
|
+
files: []
|
25
|
+
|
30
26
|
has_rdoc: true
|
31
27
|
homepage: http://github.com/hpoydar/chronic_duration
|
32
28
|
post_install_message:
|
@@ -56,7 +52,5 @@ rubygems_version: 1.2.0
|
|
56
52
|
signing_key:
|
57
53
|
specification_version: 2
|
58
54
|
summary: A Ruby natural language parser for elapsed time
|
59
|
-
test_files:
|
60
|
-
|
61
|
-
- spec/spec_helper.rb
|
62
|
-
- Rakefile
|
55
|
+
test_files: []
|
56
|
+
|
data/MIT-LICENSE
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) Henry Poydar
|
2
|
-
|
3
|
-
Permission is hereby granted, free of charge, to any person
|
4
|
-
obtaining a copy of this software and associated documentation
|
5
|
-
files (the "Software"), to deal in the Software without
|
6
|
-
restriction, including without limitation the rights to use,
|
7
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
-
copies of the Software, and to permit persons to whom the
|
9
|
-
Software is furnished to do so, subject to the following
|
10
|
-
conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be
|
13
|
-
included in all copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
= Chronic Duration
|
2
|
-
|
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
|
-
|
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
|
-
|
7
|
-
== Installation
|
8
|
-
|
9
|
-
$ sudo gem sources -a http://gems.github.com
|
10
|
-
$ sudo gem install hpoydar-chronic_duration
|
11
|
-
|
12
|
-
== Usage
|
13
|
-
|
14
|
-
>> require 'chronic_duration'
|
15
|
-
=> true
|
16
|
-
>> ChronicDuration.parse('4 minutes and 30 seconds')
|
17
|
-
=> 270
|
18
|
-
>> ChronicDuration.output(270)
|
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
|
26
|
-
|
27
|
-
Nil is returned if the string can't be parsed
|
28
|
-
|
29
|
-
Examples of parse-able strings:
|
30
|
-
|
31
|
-
* '12.4 secs'
|
32
|
-
* '1:20'
|
33
|
-
* '1:20.51'
|
34
|
-
* '4:01:01'
|
35
|
-
* '3 mins 4 sec'
|
36
|
-
* '2 hrs 20 min'
|
37
|
-
* '2h20min'
|
38
|
-
* '6 mos 1 day'
|
39
|
-
* '47 yrs 6 mos and 4d'
|
40
|
-
* 'two hours and twenty minutes'
|
41
|
-
|
42
|
-
== Contributors
|
43
|
-
|
44
|
-
jduff
|
45
|
-
|
46
|
-
== TODO
|
47
|
-
|
48
|
-
* Benchmark, optimize
|
49
|
-
* Context specific matching (E.g., for '4m30s', assume 'm' is minutes not months)
|
50
|
-
* Smartly parse vacation-like durations (E.g., '4 days and 3 nights')
|
51
|
-
* :chrono output option should probably change to something like 4 days 4:00:12 instead of 4:04:00:12
|
52
|
-
* Correct rdoc whine on gem install
|
data/Rakefile
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
require 'rake/rdoctask'
|
2
|
-
require 'spec/rake/spectask'
|
3
|
-
|
4
|
-
task :default => :spec
|
5
|
-
|
6
|
-
desc 'Run specs'
|
7
|
-
Spec::Rake::SpecTask.new('spec') do |task|
|
8
|
-
task.spec_files = FileList['spec/**/*_spec.rb']
|
9
|
-
end
|
10
|
-
|
11
|
-
Rake::RDocTask.new do |task|
|
12
|
-
task.rdoc_dir = 'doc'
|
13
|
-
task.title = 'chronic_duration'
|
14
|
-
task.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
15
|
-
task.rdoc_files.include 'README'
|
16
|
-
task.rdoc_files.include 'lib/**/*.rb'
|
17
|
-
end
|
data/lib/chronic_duration.rb
DELETED
@@ -1,198 +0,0 @@
|
|
1
|
-
require 'numerizer'
|
2
|
-
module ChronicDuration
|
3
|
-
extend self
|
4
|
-
|
5
|
-
def parse(string)
|
6
|
-
result = calculate_from_words(cleanup(string))
|
7
|
-
result == 0 ? nil : result
|
8
|
-
end
|
9
|
-
|
10
|
-
# Refactor, DRY up, make recursive
|
11
|
-
def output(seconds, opts = {})
|
12
|
-
|
13
|
-
opts[:format] ||= :default
|
14
|
-
|
15
|
-
years = months = days = hours = minutes = 0
|
16
|
-
|
17
|
-
if seconds >= 60
|
18
|
-
minutes = (seconds / 60).to_i
|
19
|
-
seconds = seconds % 60
|
20
|
-
if minutes >= 60
|
21
|
-
hours = (minutes / 60).to_i
|
22
|
-
minutes = (minutes % 60).to_i
|
23
|
-
if hours >= 24
|
24
|
-
days = (hours / 24).to_i
|
25
|
-
hours = (hours % 24).to_i
|
26
|
-
if days >= 30
|
27
|
-
months = (days / 30).to_i
|
28
|
-
days = (days % 30).to_i
|
29
|
-
if months >= 12
|
30
|
-
years = (months / 12).to_i
|
31
|
-
months = (months % 12).to_i
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
joiner = ' '
|
39
|
-
process = nil
|
40
|
-
|
41
|
-
case opts[:format]
|
42
|
-
when :short
|
43
|
-
dividers = {
|
44
|
-
:years => 'y', :months => 'm', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
|
45
|
-
when :default
|
46
|
-
dividers = {
|
47
|
-
:years => ' yr', :months => ' mo', :days => ' day', :hours => ' hr', :minutes => ' min', :seconds => ' sec',
|
48
|
-
:pluralize => true }
|
49
|
-
when :long
|
50
|
-
dividers = {
|
51
|
-
:years => ' year', :months => ' month', :days => ' day', :hours => ' hour', :minutes => ' minute', :seconds => ' second',
|
52
|
-
:pluralize => true }
|
53
|
-
when :chrono
|
54
|
-
dividers = {
|
55
|
-
:years => ':', :months => ':', :days => ':', :hours => ':', :minutes => ':', :seconds => ':', :keep_zero => true }
|
56
|
-
process = lambda do |str|
|
57
|
-
# Pad zeros
|
58
|
-
# Get rid of lead off times if they are zero
|
59
|
-
# Get rid of lead off zero
|
60
|
-
# Get rid of trailing :
|
61
|
-
str.gsub(/\b\d\b/) { |d| ("%02d" % d) }.gsub(/^(00:)+/, '').gsub(/^0/, '').gsub(/:$/, '')
|
62
|
-
end
|
63
|
-
joiner = ''
|
64
|
-
end
|
65
|
-
|
66
|
-
result = []
|
67
|
-
[:years, :months, :days, :hours, :minutes, :seconds].each do |t|
|
68
|
-
result << humanize_time_unit( eval(t.to_s), dividers[t], dividers[:pluralize], dividers[:keep_zero] )
|
69
|
-
end
|
70
|
-
|
71
|
-
result = result.join(joiner).squeeze(' ').strip
|
72
|
-
|
73
|
-
if process
|
74
|
-
result = process.call(result)
|
75
|
-
end
|
76
|
-
|
77
|
-
result.length == 0 ? nil : result
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
private
|
82
|
-
|
83
|
-
def humanize_time_unit(number, unit, pluralize, keep_zero)
|
84
|
-
return '' if number == 0 && !keep_zero
|
85
|
-
res = "#{number}#{unit}"
|
86
|
-
# A poor man's pluralizer
|
87
|
-
res << 's' if !(number == 1) && pluralize
|
88
|
-
res
|
89
|
-
end
|
90
|
-
|
91
|
-
def calculate_from_words(string)
|
92
|
-
val = 0
|
93
|
-
words = string.split(' ')
|
94
|
-
words.each_with_index do |v, k|
|
95
|
-
if v =~ float_matcher
|
96
|
-
val += (convert_to_number(v) * duration_units_seconds_multiplier(words[k + 1] || 'seconds'))
|
97
|
-
end
|
98
|
-
end
|
99
|
-
val
|
100
|
-
end
|
101
|
-
|
102
|
-
def cleanup(string)
|
103
|
-
res = filter_by_type(Numerizer.numerize(string))
|
104
|
-
res = res.gsub(float_matcher) {|n| " #{n} "}.squeeze(' ').strip
|
105
|
-
res = filter_through_white_list(res)
|
106
|
-
end
|
107
|
-
|
108
|
-
def convert_to_number(string)
|
109
|
-
string.to_f % 1 > 0 ? string.to_f : string.to_i
|
110
|
-
end
|
111
|
-
|
112
|
-
def duration_units_list
|
113
|
-
%w(seconds minutes hours days weeks months years)
|
114
|
-
end
|
115
|
-
def duration_units_seconds_multiplier(unit)
|
116
|
-
return 0 unless duration_units_list.include?(unit)
|
117
|
-
case unit
|
118
|
-
when 'years'; 31557600 # accounts for leap years
|
119
|
-
when 'months'; 3600 * 24 * 30
|
120
|
-
when 'weeks'; 3600 * 24 * 7
|
121
|
-
when 'days'; 3600 * 24
|
122
|
-
when 'hours'; 3600
|
123
|
-
when 'minutes'; 60
|
124
|
-
when 'seconds'; 1
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def error_message
|
129
|
-
'Sorry, that duration could not be parsed'
|
130
|
-
end
|
131
|
-
|
132
|
-
# Parse 3:41:59 and return 3 hours 41 minutes 59 seconds
|
133
|
-
def filter_by_type(string)
|
134
|
-
if string.gsub(' ', '') =~ /#{float_matcher}(:#{float_matcher})+/
|
135
|
-
res = []
|
136
|
-
string.gsub(' ', '').split(':').reverse.each_with_index do |v,k|
|
137
|
-
return unless duration_units_list[k]
|
138
|
-
res << "#{v} #{duration_units_list[k]}"
|
139
|
-
end
|
140
|
-
res = res.reverse.join(' ')
|
141
|
-
else
|
142
|
-
res = string
|
143
|
-
end
|
144
|
-
res
|
145
|
-
end
|
146
|
-
|
147
|
-
def float_matcher
|
148
|
-
/[0-9]*\.?[0-9]+/
|
149
|
-
end
|
150
|
-
|
151
|
-
# Get rid of unknown words and map found
|
152
|
-
# words to defined time units
|
153
|
-
def filter_through_white_list(string)
|
154
|
-
res = []
|
155
|
-
string.split(' ').each do |word|
|
156
|
-
if word =~ float_matcher
|
157
|
-
res << word.strip
|
158
|
-
next
|
159
|
-
end
|
160
|
-
res << mappings[word.strip] if mappings.has_key?(word.strip)
|
161
|
-
end
|
162
|
-
res.join(' ')
|
163
|
-
end
|
164
|
-
|
165
|
-
def mappings
|
166
|
-
{
|
167
|
-
'seconds' => 'seconds',
|
168
|
-
'second' => 'seconds',
|
169
|
-
'secs' => 'seconds',
|
170
|
-
'sec' => 'seconds',
|
171
|
-
's' => 'seconds',
|
172
|
-
'minutes' => 'minutes',
|
173
|
-
'minute' => 'minutes',
|
174
|
-
'mins' => 'minutes',
|
175
|
-
'min' => 'minutes',
|
176
|
-
'm' => 'minutes',
|
177
|
-
'hours' => 'hours',
|
178
|
-
'hour' => 'hours',
|
179
|
-
'hrs' => 'hours',
|
180
|
-
'hr' => 'hours',
|
181
|
-
'h' => 'hours',
|
182
|
-
'days' => 'days',
|
183
|
-
'day' => 'days',
|
184
|
-
'dy' => 'days',
|
185
|
-
'd' => 'days',
|
186
|
-
'months' => 'months',
|
187
|
-
'mos' => 'months',
|
188
|
-
'years' => 'years',
|
189
|
-
'yrs' => 'years',
|
190
|
-
'y' => 'years'
|
191
|
-
}
|
192
|
-
end
|
193
|
-
|
194
|
-
def white_list
|
195
|
-
self.mappings.map {|k, v| k}
|
196
|
-
end
|
197
|
-
|
198
|
-
end
|
data/lib/numerizer.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
|
3
|
-
class Numerizer
|
4
|
-
|
5
|
-
DIRECT_NUMS = [
|
6
|
-
['eleven', '11'],
|
7
|
-
['twelve', '12'],
|
8
|
-
['thirteen', '13'],
|
9
|
-
['fourteen', '14'],
|
10
|
-
['fifteen', '15'],
|
11
|
-
['sixteen', '16'],
|
12
|
-
['seventeen', '17'],
|
13
|
-
['eighteen', '18'],
|
14
|
-
['nineteen', '19'],
|
15
|
-
['ninteen', '19'], # Common mis-spelling
|
16
|
-
['zero', '0'],
|
17
|
-
['one', '1'],
|
18
|
-
['two', '2'],
|
19
|
-
['three', '3'],
|
20
|
-
['four(\W|$)', '4\1'], # The weird regex is so that it matches four but not fourty
|
21
|
-
['five', '5'],
|
22
|
-
['six(\W|$)', '6\1'],
|
23
|
-
['seven(\W|$)', '7\1'],
|
24
|
-
['eight(\W|$)', '8\1'],
|
25
|
-
['nine(\W|$)', '9\1'],
|
26
|
-
['ten', '10'],
|
27
|
-
['\ba[\b^$]', '1'] # doesn't make sense for an 'a' at the end to be a 1
|
28
|
-
]
|
29
|
-
|
30
|
-
TEN_PREFIXES = [ ['twenty', 20],
|
31
|
-
['thirty', 30],
|
32
|
-
['fourty', 40],
|
33
|
-
['fifty', 50],
|
34
|
-
['sixty', 60],
|
35
|
-
['seventy', 70],
|
36
|
-
['eighty', 80],
|
37
|
-
['ninety', 90]
|
38
|
-
]
|
39
|
-
|
40
|
-
BIG_PREFIXES = [ ['hundred', 100],
|
41
|
-
['thousand', 1000],
|
42
|
-
['million', 1_000_000],
|
43
|
-
['billion', 1_000_000_000],
|
44
|
-
['trillion', 1_000_000_000_000],
|
45
|
-
]
|
46
|
-
|
47
|
-
def self.numerize(string)
|
48
|
-
string = string.dup
|
49
|
-
|
50
|
-
# preprocess
|
51
|
-
string.gsub!(/ +|([^\d])-([^\d])/, '\1 \2') # will mutilate hyphenated-words but shouldn't matter for date extraction
|
52
|
-
string.gsub!(/a half/, 'haAlf') # take the 'a' out so it doesn't turn into a 1, save the half for the end
|
53
|
-
|
54
|
-
# easy/direct replacements
|
55
|
-
|
56
|
-
DIRECT_NUMS.each do |dn|
|
57
|
-
string.gsub!(/#{dn[0]}/i, '<num>' + dn[1])
|
58
|
-
end
|
59
|
-
|
60
|
-
# ten, twenty, etc.
|
61
|
-
|
62
|
-
TEN_PREFIXES.each do |tp|
|
63
|
-
string.gsub!(/(?:#{tp[0]}) *<num>(\d(?=[^\d]|$))*/i) { '<num>' + (tp[1] + $1.to_i).to_s }
|
64
|
-
end
|
65
|
-
|
66
|
-
TEN_PREFIXES.each do |tp|
|
67
|
-
string.gsub!(/#{tp[0]}/i) { '<num>' + tp[1].to_s }
|
68
|
-
end
|
69
|
-
|
70
|
-
# hundreds, thousands, millions, etc.
|
71
|
-
|
72
|
-
BIG_PREFIXES.each do |bp|
|
73
|
-
string.gsub!(/(?:<num>)?(\d*) *#{bp[0]}/i) { '<num>' + (bp[1] * $1.to_i).to_s}
|
74
|
-
andition(string)
|
75
|
-
end
|
76
|
-
|
77
|
-
# fractional addition
|
78
|
-
# I'm not combining this with the previous block as using float addition complicates the strings
|
79
|
-
# (with extraneous .0's and such )
|
80
|
-
string.gsub!(/(\d+)(?: | and |-)*haAlf/i) { ($1.to_f + 0.5).to_s }
|
81
|
-
|
82
|
-
string.gsub(/<num>/, '')
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
def self.andition(string)
|
88
|
-
sc = StringScanner.new(string)
|
89
|
-
while(sc.scan_until(/<num>(\d+)( | and )<num>(\d+)(?=[^\w]|$)/i))
|
90
|
-
if sc[2] =~ /and/ || sc[1].size > sc[3].size
|
91
|
-
string[(sc.pos - sc.matched_size)..(sc.pos-1)] = '<num>' + (sc[1].to_i + sc[3].to_i).to_s
|
92
|
-
sc.reset
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
@@ -1,150 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
-
|
3
|
-
describe ChronicDuration, 'gem' do
|
4
|
-
|
5
|
-
it "should build" do
|
6
|
-
spec = eval(File.read("#{File.dirname(__FILE__)}/../chronic_duration.gemspec"))
|
7
|
-
FileUtils.rm_f(File.dirname(__FILE__) + "/../chronic_duration-#{spec.version}.gem")
|
8
|
-
system "cd #{File.dirname(__FILE__)}/.. && gem build chronic_duration.gemspec -q --no-verbose"
|
9
|
-
File.exists?(File.dirname(__FILE__) + "/../chronic_duration-#{spec.version}.gem").should be_true
|
10
|
-
FileUtils.rm_f(File.dirname(__FILE__) + "/../chronic_duration-#{spec.version}.gem")
|
11
|
-
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
describe ChronicDuration, '.parse' do
|
16
|
-
|
17
|
-
@exemplars = {
|
18
|
-
'1:20' => 60 + 20,
|
19
|
-
'1:20.51' => 60 + 20.51,
|
20
|
-
'4:01:01' => 4 * 3600 + 60 + 1,
|
21
|
-
'3 mins 4 sec' => 3 * 60 + 4,
|
22
|
-
'three mins four sec' => 3 * 60 + 4,
|
23
|
-
'2 hrs 20 min' => 2 * 3600 + 20 * 60,
|
24
|
-
'2h20min' => 2 * 3600 + 20 * 60,
|
25
|
-
'6 mos 1 day' => 6 * 30 * 24 * 3600 + 24 * 3600,
|
26
|
-
'2.5 hrs' => 2.5 * 3600,
|
27
|
-
'47 yrs 6 mos and 4.5d' => 47 * 31557600 + 6 * 30 * 24 * 3600 + 4.5 * 24 * 3600,
|
28
|
-
'two hours and twenty minutes' => 2 * 3600 + 20 * 60
|
29
|
-
}
|
30
|
-
|
31
|
-
it "should return nil if the string can't be parsed" do
|
32
|
-
ChronicDuration.parse('gobblygoo').should be_nil
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should return a float if seconds are in decimals" do
|
36
|
-
ChronicDuration.parse('12 mins 3.141 seconds').is_a?(Float).should be_true
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should return an integer unless the seconds are in decimals" do
|
40
|
-
ChronicDuration.parse('12 mins 3 seconds').is_a?(Integer).should be_true
|
41
|
-
end
|
42
|
-
|
43
|
-
@exemplars.each do |k, v|
|
44
|
-
it "should properly parse a duration like #{k}" do
|
45
|
-
ChronicDuration.parse(k).should == v
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
describe ChronicDuration, '.output' do
|
52
|
-
|
53
|
-
it "should return nil if the input can't be parsed" do
|
54
|
-
ChronicDuration.parse('gobblygoo').should be_nil
|
55
|
-
end
|
56
|
-
|
57
|
-
@exemplars = {
|
58
|
-
(60 + 20) =>
|
59
|
-
{
|
60
|
-
:short => '1m 20s',
|
61
|
-
:default => '1 min 20 secs',
|
62
|
-
:long => '1 minute 20 seconds',
|
63
|
-
:chrono => '1:20'
|
64
|
-
},
|
65
|
-
(60 + 20.51) =>
|
66
|
-
{
|
67
|
-
:short => '1m 20.51s',
|
68
|
-
:default => '1 min 20.51 secs',
|
69
|
-
:long => '1 minute 20.51 seconds',
|
70
|
-
:chrono => '1:20.51'
|
71
|
-
},
|
72
|
-
(4 * 3600 + 60 + 1) =>
|
73
|
-
{
|
74
|
-
:short => '4h 1m 1s',
|
75
|
-
:default => '4 hrs 1 min 1 sec',
|
76
|
-
:long => '4 hours 1 minute 1 second',
|
77
|
-
:chrono => '4:01:01'
|
78
|
-
},
|
79
|
-
(2 * 3600 + 20 * 60) =>
|
80
|
-
{
|
81
|
-
:short => '2h 20m',
|
82
|
-
:default => '2 hrs 20 mins',
|
83
|
-
:long => '2 hours 20 minutes',
|
84
|
-
:chrono => '2:20'
|
85
|
-
},
|
86
|
-
(2 * 3600 + 20 * 60) =>
|
87
|
-
{
|
88
|
-
:short => '2h 20m',
|
89
|
-
:default => '2 hrs 20 mins',
|
90
|
-
:long => '2 hours 20 minutes',
|
91
|
-
:chrono => '2:20:00'
|
92
|
-
},
|
93
|
-
(6 * 30 * 24 * 3600 + 24 * 3600) =>
|
94
|
-
{
|
95
|
-
:short => '6m 1d',
|
96
|
-
:default => '6 mos 1 day',
|
97
|
-
:long => '6 months 1 day',
|
98
|
-
:chrono => '6:01:00:00:00' # Yuck. FIXME
|
99
|
-
}
|
100
|
-
}
|
101
|
-
|
102
|
-
@exemplars.each do |k, v|
|
103
|
-
v.each do |key, val|
|
104
|
-
it "should properly output a duration of #{k} seconds as #{val} using the #{key.to_s} format option" do
|
105
|
-
ChronicDuration.output(k, :format => key).should == val
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
|
113
|
-
# Some of the private methods deserve some spec'ing to aid
|
114
|
-
# us in development...
|
115
|
-
|
116
|
-
describe ChronicDuration, "private methods" do
|
117
|
-
|
118
|
-
describe ".filter_by_type" do
|
119
|
-
|
120
|
-
it "should take a chrono-formatted time like 3:14 and return a human time like 3 minutes 14 seconds" do
|
121
|
-
ChronicDuration.instance_eval("filter_by_type('3:14')").should == '3 minutes 14 seconds'
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should take a chrono-formatted time like 12:10:14 and return a human time like 12 hours 10 minutes 14 seconds" do
|
125
|
-
ChronicDuration.instance_eval("filter_by_type('12:10:14')").should == '12 hours 10 minutes 14 seconds'
|
126
|
-
end
|
127
|
-
|
128
|
-
it "should return the input if it's not a chrono-formatted time" do
|
129
|
-
ChronicDuration.instance_eval("filter_by_type('4 hours')").should == '4 hours'
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
describe ".cleanup" do
|
135
|
-
|
136
|
-
it "should clean up extraneous words" do
|
137
|
-
ChronicDuration.instance_eval("cleanup('4 days and 11 hours')").should == '4 days 11 hours'
|
138
|
-
end
|
139
|
-
|
140
|
-
it "should cleanup extraneous spaces" do
|
141
|
-
ChronicDuration.instance_eval("cleanup(' 4 days and 11 hours')").should == '4 days 11 hours'
|
142
|
-
end
|
143
|
-
|
144
|
-
it "should insert spaces where there aren't any" do
|
145
|
-
ChronicDuration.instance_eval("cleanup('4m11.5s')").should == '4 minutes 11.5 seconds'
|
146
|
-
end
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
data/spec/spec_helper.rb
DELETED