chronic_duration 0.9.6 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +1 -9
- data/{README.rdoc → README.md} +16 -15
- data/Rakefile +2 -41
- data/chronic_duration.gemspec +20 -56
- data/lib/chronic_duration.rb +78 -57
- data/lib/chronic_duration/version.rb +3 -0
- data/spec/chronic_duration_spec.rb +80 -47
- data/spec/lib/chronic_duration_spec.rb +212 -0
- data/spec/spec_helper.rb +8 -0
- metadata +69 -79
- data/Gemfile.lock +0 -30
- data/VERSION +0 -1
data/.gitignore
ADDED
data/Gemfile
CHANGED
data/{README.rdoc → README.md}
RENAMED
@@ -1,15 +1,10 @@
|
|
1
|
-
|
1
|
+
# Chronic Duration
|
2
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.)
|
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.
|
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
|
-
|
8
|
-
|
9
|
-
$ sudo gem sources -a http://gemcutter.org
|
10
|
-
$ sudo gem install chronic_duration
|
11
|
-
|
12
|
-
== Usage
|
7
|
+
## Usage
|
13
8
|
|
14
9
|
>> require 'chronic_duration'
|
15
10
|
=> true
|
@@ -23,13 +18,19 @@ The reverse can also be accomplished with the output method. So pass in seconds
|
|
23
18
|
=> 4 minutes 30 seconds
|
24
19
|
>> ChronicDuration.output(270, :format => :chrono)
|
25
20
|
=> 4:30
|
26
|
-
|
21
|
+
>> ChronicDuration.output(1299600, :weeks => true)
|
22
|
+
=> 2 wks 1 day 1 hr
|
23
|
+
>> ChronicDuration.output(1299600, :weeks => true, :units => 2)
|
24
|
+
=> 2 wks 1 day
|
25
|
+
>> ChronicDuration.output(1296000)
|
26
|
+
=> 15 days
|
27
|
+
|
27
28
|
Nil is returned if the string can't be parsed
|
28
29
|
|
29
30
|
Examples of parse-able strings:
|
30
31
|
|
31
32
|
* '12.4 secs'
|
32
|
-
* '1:20'
|
33
|
+
* '1:20'
|
33
34
|
* '1:20.51'
|
34
35
|
* '4:01:01'
|
35
36
|
* '3 mins 4 sec'
|
@@ -47,12 +48,12 @@ ChronicDuration.raise_exceptions can be set to true to raise exceptions when the
|
|
47
48
|
>> ChronicDuration.parse('4 elephants and 3 Astroids')
|
48
49
|
ChronicDuration::DurationParseError: An invalid word "elephants" was used in the string to be parsed.
|
49
50
|
|
50
|
-
|
51
|
-
|
51
|
+
|
52
|
+
## Contributors
|
52
53
|
|
53
54
|
brianjlandau, jduff, olauzon, roboman, ianlevesque
|
54
|
-
|
55
|
-
|
55
|
+
|
56
|
+
## TODO
|
56
57
|
|
57
58
|
* Benchmark, optimize
|
58
59
|
* Context specific matching (E.g., for '4m30s', assume 'm' is minutes not months)
|
data/Rakefile
CHANGED
@@ -1,45 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'rake'
|
11
|
-
|
12
|
-
require 'jeweler'
|
13
|
-
Jeweler::Tasks.new do |gem|
|
14
|
-
gem.name = "chronic_duration"
|
15
|
-
gem.summary = %Q{A Ruby natural language parser for elapsed time}
|
16
|
-
gem.license = "MIT"
|
17
|
-
gem.description = %Q{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.) The reverse can also be performed via the output method.}
|
18
|
-
gem.email = "hpoydar@gmail.com"
|
19
|
-
gem.homepage = "http://github.com/hpoydar/chronic_duration"
|
20
|
-
gem.authors = ["hpoydar"]
|
21
|
-
end
|
22
|
-
Jeweler::RubygemsDotOrgTasks.new
|
23
|
-
|
24
|
-
require 'rspec/core'
|
1
|
+
require "bundler/gem_tasks"
|
25
2
|
require 'rspec/core/rake_task'
|
26
|
-
RSpec::Core::RakeTask.new(:spec) do |spec|
|
27
|
-
spec.pattern = FileList['spec/**/*_spec.rb']
|
28
|
-
end
|
29
|
-
|
30
|
-
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
31
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
-
spec.rcov = true
|
33
|
-
end
|
34
3
|
|
4
|
+
RSpec::Core::RakeTask.new('spec')
|
35
5
|
task :default => :spec
|
36
6
|
|
37
|
-
require 'rake/rdoctask'
|
38
|
-
Rake::RDocTask.new do |rdoc|
|
39
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
-
|
41
|
-
rdoc.rdoc_dir = 'rdoc'
|
42
|
-
rdoc.title = "chronic_duration #{version}"
|
43
|
-
rdoc.rdoc_files.include('README*')
|
44
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
-
end
|
data/chronic_duration.gemspec
CHANGED
@@ -1,62 +1,26 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'chronic_duration/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
s.name = %q{chronic_duration}
|
8
|
-
s.version = "0.9.6"
|
6
|
+
Gem::Specification.new do |gem|
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
"Gemfile",
|
20
|
-
"Gemfile.lock",
|
21
|
-
"MIT-LICENSE",
|
22
|
-
"README.rdoc",
|
23
|
-
"Rakefile",
|
24
|
-
"VERSION",
|
25
|
-
"chronic_duration.gemspec",
|
26
|
-
"lib/chronic_duration.rb",
|
27
|
-
"spec/chronic_duration_spec.rb"
|
28
|
-
]
|
29
|
-
s.homepage = %q{http://github.com/hpoydar/chronic_duration}
|
30
|
-
s.licenses = ["MIT"]
|
31
|
-
s.require_paths = ["lib"]
|
32
|
-
s.rubygems_version = %q{1.5.2}
|
33
|
-
s.summary = %q{A Ruby natural language parser for elapsed time}
|
34
|
-
s.test_files = [
|
35
|
-
"spec/chronic_duration_spec.rb"
|
36
|
-
]
|
8
|
+
gem.name = "chronic_duration"
|
9
|
+
gem.version = ChronicDuration::VERSION
|
10
|
+
gem.authors = ["hpoydar"]
|
11
|
+
gem.email = ["henry@poydar.com"]
|
12
|
+
gem.description = %q{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.) The reverse can also be performed via the output method.}
|
13
|
+
gem.summary = %q{A simple Ruby natural language parser for elapsed time}
|
14
|
+
gem.homepage = "https://github.com/hpoydar/chronic_duration"
|
37
15
|
|
38
|
-
|
39
|
-
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
40
20
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
46
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
47
|
-
else
|
48
|
-
s.add_dependency(%q<numerizer>, ["~> 0.1.1"])
|
49
|
-
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
50
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
51
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
52
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
53
|
-
end
|
54
|
-
else
|
55
|
-
s.add_dependency(%q<numerizer>, ["~> 0.1.1"])
|
56
|
-
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
57
|
-
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
58
|
-
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
59
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
60
|
-
end
|
61
|
-
end
|
21
|
+
gem.add_runtime_dependency "numerizer", "~> 0.1.1"
|
22
|
+
|
23
|
+
gem.add_development_dependency "rake", "~> 10.0.3"
|
24
|
+
gem.add_development_dependency "rspec", "~> 2.12.0"
|
62
25
|
|
26
|
+
end
|
data/lib/chronic_duration.rb
CHANGED
@@ -1,40 +1,42 @@
|
|
1
1
|
require 'numerizer' unless defined?(Numerizer)
|
2
|
+
|
2
3
|
module ChronicDuration
|
4
|
+
|
3
5
|
extend self
|
4
|
-
|
6
|
+
|
5
7
|
class DurationParseError < StandardError
|
6
8
|
end
|
7
|
-
|
9
|
+
|
8
10
|
@@raise_exceptions = false
|
9
|
-
|
11
|
+
|
10
12
|
def self.raise_exceptions
|
11
13
|
!!@@raise_exceptions
|
12
14
|
end
|
13
|
-
|
15
|
+
|
14
16
|
def self.raise_exceptions=(value)
|
15
17
|
@@raise_exceptions = !!value
|
16
18
|
end
|
17
|
-
|
19
|
+
|
18
20
|
# Given a string representation of elapsed time,
|
19
21
|
# return an integer (or float, if fractions of a
|
20
22
|
# second are input)
|
21
23
|
def parse(string, opts = {})
|
22
24
|
result = calculate_from_words(cleanup(string), opts)
|
23
25
|
result == 0 ? nil : result
|
24
|
-
end
|
25
|
-
|
26
|
+
end
|
27
|
+
|
26
28
|
# Given an integer and an optional format,
|
27
29
|
# returns a formatted string representing elapsed time
|
28
30
|
def output(seconds, opts = {})
|
29
|
-
|
31
|
+
|
30
32
|
opts[:format] ||= :default
|
31
|
-
|
32
|
-
years = months = days = hours = minutes = 0
|
33
|
-
|
33
|
+
|
34
|
+
years = months = weeks = days = hours = minutes = 0
|
35
|
+
|
34
36
|
decimal_places = seconds.to_s.split('.').last.length if seconds.is_a?(Float)
|
35
37
|
|
36
38
|
if seconds >= 60
|
37
|
-
minutes = (seconds / 60).to_i
|
39
|
+
minutes = (seconds / 60).to_i
|
38
40
|
seconds = seconds % 60
|
39
41
|
if minutes >= 60
|
40
42
|
hours = (minutes / 60).to_i
|
@@ -42,40 +44,52 @@ module ChronicDuration
|
|
42
44
|
if hours >= 24
|
43
45
|
days = (hours / 24).to_i
|
44
46
|
hours = (hours % 24).to_i
|
45
|
-
if
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
if opts[:weeks]
|
48
|
+
if days >= 7
|
49
|
+
weeks = (days / 7).to_i
|
50
|
+
days = (days % 7).to_i
|
51
|
+
if weeks >= 4
|
52
|
+
months = (weeks / 4).to_i
|
53
|
+
weeks = (weeks % 4).to_i
|
54
|
+
end
|
55
|
+
end
|
56
|
+
else
|
57
|
+
if days >= 30
|
58
|
+
months = (days / 30).to_i
|
59
|
+
days = (days % 30).to_i
|
51
60
|
end
|
52
61
|
end
|
62
|
+
if months >= 12
|
63
|
+
years = (months / 12).to_i
|
64
|
+
months = (months % 12).to_i
|
65
|
+
days = days - (5 * years)
|
66
|
+
end
|
53
67
|
end
|
54
68
|
end
|
55
69
|
end
|
56
|
-
|
70
|
+
|
57
71
|
joiner = ' '
|
58
72
|
process = nil
|
59
|
-
|
73
|
+
|
60
74
|
case opts[:format]
|
61
75
|
when :micro
|
62
|
-
dividers = {
|
63
|
-
:years => 'y', :months => '
|
76
|
+
dividers = {
|
77
|
+
:years => 'y', :months => 'mo', :weeks => 'w', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
|
64
78
|
joiner = ''
|
65
79
|
when :short
|
66
|
-
dividers = {
|
67
|
-
:years => 'y', :months => 'm', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
|
68
|
-
when :default
|
69
80
|
dividers = {
|
70
|
-
:years => '
|
81
|
+
:years => 'y', :months => 'mo', :weeks => 'w', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
|
82
|
+
when :default
|
83
|
+
dividers = {
|
84
|
+
:years => ' yr', :months => ' mo', :weeks => ' wk', :days => ' day', :hours => ' hr', :minutes => ' min', :seconds => ' sec',
|
71
85
|
:pluralize => true }
|
72
|
-
when :long
|
86
|
+
when :long
|
73
87
|
dividers = {
|
74
|
-
:years => ' year', :months => ' month', :days => ' day', :hours => ' hour', :minutes => ' minute', :seconds => ' second',
|
88
|
+
:years => ' year', :months => ' month', :weeks => ' week', :days => ' day', :hours => ' hour', :minutes => ' minute', :seconds => ' second',
|
75
89
|
:pluralize => true }
|
76
90
|
when :chrono
|
77
91
|
dividers = {
|
78
|
-
:years => ':', :months => ':', :days => ':', :hours => ':', :minutes => ':', :seconds => ':', :keep_zero => true }
|
92
|
+
:years => ':', :months => ':', :weeks => ':', :days => ':', :hours => ':', :minutes => ':', :seconds => ':', :keep_zero => true }
|
79
93
|
process = lambda do |str|
|
80
94
|
# Pad zeros
|
81
95
|
# Get rid of lead off times if they are zero
|
@@ -85,34 +99,36 @@ module ChronicDuration
|
|
85
99
|
end
|
86
100
|
joiner = ''
|
87
101
|
end
|
88
|
-
|
89
|
-
result = []
|
90
|
-
|
102
|
+
|
103
|
+
result = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].map do |t|
|
104
|
+
next if t == :weeks && !opts[:weeks]
|
91
105
|
num = eval(t.to_s)
|
92
|
-
num = ("%.#{decimal_places}f" % num) if num.is_a?(Float) && t == :seconds
|
93
|
-
|
94
|
-
end
|
106
|
+
num = ("%.#{decimal_places}f" % num) if num.is_a?(Float) && t == :seconds
|
107
|
+
humanize_time_unit( num, dividers[t], dividers[:pluralize], dividers[:keep_zero] )
|
108
|
+
end.compact!
|
109
|
+
|
110
|
+
result = result[0...opts[:units]] if opts[:units]
|
111
|
+
|
112
|
+
result = result.join(joiner)
|
95
113
|
|
96
|
-
result = result.join(joiner).squeeze(' ').strip
|
97
|
-
|
98
114
|
if process
|
99
115
|
result = process.call(result)
|
100
116
|
end
|
101
|
-
|
117
|
+
|
102
118
|
result.length == 0 ? nil : result
|
103
119
|
|
104
120
|
end
|
105
|
-
|
121
|
+
|
106
122
|
private
|
107
|
-
|
123
|
+
|
108
124
|
def humanize_time_unit(number, unit, pluralize, keep_zero)
|
109
|
-
return
|
125
|
+
return nil if number == 0 && !keep_zero
|
110
126
|
res = "#{number}#{unit}"
|
111
127
|
# A poor man's pluralizer
|
112
128
|
res << 's' if !(number == 1) && pluralize
|
113
129
|
res
|
114
130
|
end
|
115
|
-
|
131
|
+
|
116
132
|
def calculate_from_words(string, opts)
|
117
133
|
val = 0
|
118
134
|
words = string.split(' ')
|
@@ -123,18 +139,18 @@ private
|
|
123
139
|
end
|
124
140
|
val
|
125
141
|
end
|
126
|
-
|
142
|
+
|
127
143
|
def cleanup(string)
|
128
144
|
res = string.downcase
|
129
145
|
res = filter_by_type(Numerizer.numerize(res))
|
130
146
|
res = res.gsub(float_matcher) {|n| " #{n} "}.squeeze(' ').strip
|
131
147
|
res = filter_through_white_list(res)
|
132
148
|
end
|
133
|
-
|
149
|
+
|
134
150
|
def convert_to_number(string)
|
135
151
|
string.to_f % 1 > 0 ? string.to_f : string.to_i
|
136
152
|
end
|
137
|
-
|
153
|
+
|
138
154
|
def duration_units_list
|
139
155
|
%w(seconds minutes hours days weeks months years)
|
140
156
|
end
|
@@ -150,18 +166,19 @@ private
|
|
150
166
|
when 'seconds'; 1
|
151
167
|
end
|
152
168
|
end
|
153
|
-
|
169
|
+
|
154
170
|
def error_message
|
155
171
|
'Sorry, that duration could not be parsed'
|
156
172
|
end
|
157
|
-
|
173
|
+
|
158
174
|
# Parse 3:41:59 and return 3 hours 41 minutes 59 seconds
|
159
175
|
def filter_by_type(string)
|
176
|
+
chrono_units_list = duration_units_list.reject {|v| v == "weeks"}
|
160
177
|
if string.gsub(' ', '') =~ /#{float_matcher}(:#{float_matcher})+/
|
161
178
|
res = []
|
162
179
|
string.gsub(' ', '').split(':').reverse.each_with_index do |v,k|
|
163
|
-
return unless
|
164
|
-
res << "#{v} #{
|
180
|
+
return unless chrono_units_list[k]
|
181
|
+
res << "#{v} #{chrono_units_list[k]}"
|
165
182
|
end
|
166
183
|
res = res.reverse.join(' ')
|
167
184
|
else
|
@@ -169,11 +186,11 @@ private
|
|
169
186
|
end
|
170
187
|
res
|
171
188
|
end
|
172
|
-
|
189
|
+
|
173
190
|
def float_matcher
|
174
191
|
/[0-9]*\.?[0-9]+/
|
175
192
|
end
|
176
|
-
|
193
|
+
|
177
194
|
# Get rid of unknown words and map found
|
178
195
|
# words to defined time units
|
179
196
|
def filter_through_white_list(string)
|
@@ -190,11 +207,13 @@ private
|
|
190
207
|
raise DurationParseError, "An invalid word #{word.inspect} was used in the string to be parsed."
|
191
208
|
end
|
192
209
|
end
|
210
|
+
# add '1' at front if string starts with something recognizable but not with a number, like 'day' or 'minute 30sec'
|
211
|
+
res.unshift(1) if res.length > 0 && mappings[res[0]]
|
193
212
|
res.join(' ')
|
194
213
|
end
|
195
|
-
|
214
|
+
|
196
215
|
def mappings
|
197
|
-
{
|
216
|
+
{
|
198
217
|
'seconds' => 'seconds',
|
199
218
|
'second' => 'seconds',
|
200
219
|
'secs' => 'seconds',
|
@@ -218,21 +237,23 @@ private
|
|
218
237
|
'week' => 'weeks',
|
219
238
|
'w' => 'weeks',
|
220
239
|
'months' => 'months',
|
240
|
+
'mo' => 'months',
|
221
241
|
'mos' => 'months',
|
222
242
|
'month' => 'months',
|
223
243
|
'years' => 'years',
|
224
244
|
'year' => 'years',
|
225
245
|
'yrs' => 'years',
|
246
|
+
'yr' => 'years',
|
226
247
|
'y' => 'years'
|
227
248
|
}
|
228
249
|
end
|
229
|
-
|
250
|
+
|
230
251
|
def join_words
|
231
252
|
['and', 'with', 'plus']
|
232
253
|
end
|
233
|
-
|
254
|
+
|
234
255
|
def white_list
|
235
|
-
self.mappings.
|
256
|
+
self.mappings.keys
|
236
257
|
end
|
237
|
-
|
258
|
+
|
238
259
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'chronic_duration'
|
2
2
|
|
3
3
|
describe ChronicDuration, '.parse' do
|
4
|
-
|
5
|
-
@exemplars = {
|
4
|
+
|
5
|
+
@exemplars = {
|
6
6
|
'1:20' => 60 + 20,
|
7
7
|
'1:20.51' => 60 + 20.51,
|
8
8
|
'4:01:01' => 4 * 3600 + 60 + 1,
|
@@ -22,47 +22,49 @@ describe ChronicDuration, '.parse' do
|
|
22
22
|
'3 weeks, plus 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
|
23
23
|
'3 weeks with 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
|
24
24
|
'1 month' => 3600 * 24 * 30,
|
25
|
-
'2 months' => 3600 * 24 * 30 * 2
|
25
|
+
'2 months' => 3600 * 24 * 30 * 2,
|
26
|
+
'day' => 3600 * 24,
|
27
|
+
'minute 30s' => 90
|
26
28
|
}
|
27
|
-
|
29
|
+
|
28
30
|
it "should return nil if the string can't be parsed" do
|
29
31
|
ChronicDuration.parse('gobblygoo').should be_nil
|
30
32
|
end
|
31
|
-
|
33
|
+
|
32
34
|
it "should raise an exception if the string can't be parsed and @@raise_exceptions is set to true" do
|
33
35
|
ChronicDuration.raise_exceptions = true
|
34
36
|
lambda { ChronicDuration.parse('23 gobblygoos') }.should raise_exception(ChronicDuration::DurationParseError)
|
35
37
|
ChronicDuration.raise_exceptions = false
|
36
38
|
end
|
37
|
-
|
39
|
+
|
38
40
|
it "should return a float if seconds are in decimals" do
|
39
41
|
ChronicDuration.parse('12 mins 3.141 seconds').is_a?(Float).should be_true
|
40
42
|
end
|
41
|
-
|
43
|
+
|
42
44
|
it "should return an integer unless the seconds are in decimals" do
|
43
45
|
ChronicDuration.parse('12 mins 3 seconds').is_a?(Integer).should be_true
|
44
46
|
end
|
45
|
-
|
47
|
+
|
46
48
|
it "should be able to parse minutes by default" do
|
47
49
|
ChronicDuration.parse('5', :default_unit => "minutes").should == 300
|
48
50
|
end
|
49
|
-
|
51
|
+
|
50
52
|
@exemplars.each do |k, v|
|
51
53
|
it "should properly parse a duration like #{k}" do
|
52
54
|
ChronicDuration.parse(k).should == v
|
53
55
|
end
|
54
56
|
end
|
55
|
-
|
57
|
+
|
56
58
|
end
|
57
59
|
|
58
60
|
describe ChronicDuration, '.output' do
|
59
|
-
|
61
|
+
|
60
62
|
it "should return nil if the input can't be parsed" do
|
61
63
|
ChronicDuration.parse('gobblygoo').should be_nil
|
62
64
|
end
|
63
|
-
|
64
|
-
@exemplars = {
|
65
|
-
#(0) =>
|
65
|
+
|
66
|
+
@exemplars = {
|
67
|
+
#(0) =>
|
66
68
|
#{
|
67
69
|
#:micro => '0s',
|
68
70
|
#:short => '0s',
|
@@ -70,64 +72,80 @@ describe ChronicDuration, '.output' do
|
|
70
72
|
#:long => '0 seconds',
|
71
73
|
#:chrono => '0'
|
72
74
|
#},
|
73
|
-
(60 + 20) =>
|
74
|
-
{
|
75
|
+
(60 + 20) =>
|
76
|
+
{
|
75
77
|
:micro => '1m20s',
|
76
78
|
:short => '1m 20s',
|
77
79
|
:default => '1 min 20 secs',
|
78
80
|
:long => '1 minute 20 seconds',
|
79
81
|
:chrono => '1:20'
|
80
82
|
},
|
81
|
-
(60 + 20.51) =>
|
82
|
-
{
|
83
|
+
(60 + 20.51) =>
|
84
|
+
{
|
83
85
|
:micro => '1m20.51s',
|
84
86
|
:short => '1m 20.51s',
|
85
87
|
:default => '1 min 20.51 secs',
|
86
88
|
:long => '1 minute 20.51 seconds',
|
87
89
|
:chrono => '1:20.51'
|
88
90
|
},
|
89
|
-
(60 + 20.51928) =>
|
90
|
-
{
|
91
|
+
(60 + 20.51928) =>
|
92
|
+
{
|
91
93
|
:micro => '1m20.51928s',
|
92
94
|
:short => '1m 20.51928s',
|
93
95
|
:default => '1 min 20.51928 secs',
|
94
96
|
:long => '1 minute 20.51928 seconds',
|
95
97
|
:chrono => '1:20.51928'
|
96
98
|
},
|
97
|
-
(4 * 3600 + 60 + 1) =>
|
98
|
-
{
|
99
|
+
(4 * 3600 + 60 + 1) =>
|
100
|
+
{
|
99
101
|
:micro => '4h1m1s',
|
100
102
|
:short => '4h 1m 1s',
|
101
103
|
:default => '4 hrs 1 min 1 sec',
|
102
104
|
:long => '4 hours 1 minute 1 second',
|
103
105
|
:chrono => '4:01:01'
|
104
106
|
},
|
105
|
-
(2 * 3600 + 20 * 60) =>
|
106
|
-
{
|
107
|
+
(2 * 3600 + 20 * 60) =>
|
108
|
+
{
|
107
109
|
:micro => '2h20m',
|
108
110
|
:short => '2h 20m',
|
109
111
|
:default => '2 hrs 20 mins',
|
110
112
|
:long => '2 hours 20 minutes',
|
111
113
|
:chrono => '2:20'
|
112
114
|
},
|
113
|
-
(2 * 3600 + 20 * 60) =>
|
114
|
-
{
|
115
|
+
(2 * 3600 + 20 * 60) =>
|
116
|
+
{
|
115
117
|
:micro => '2h20m',
|
116
118
|
:short => '2h 20m',
|
117
119
|
:default => '2 hrs 20 mins',
|
118
120
|
:long => '2 hours 20 minutes',
|
119
121
|
:chrono => '2:20:00'
|
120
122
|
},
|
121
|
-
(6 * 30 * 24 * 3600 + 24 * 3600) =>
|
122
|
-
{
|
123
|
-
:micro => '
|
124
|
-
:short => '
|
123
|
+
(6 * 30 * 24 * 3600 + 24 * 3600) =>
|
124
|
+
{
|
125
|
+
:micro => '6mo1d',
|
126
|
+
:short => '6mo 1d',
|
125
127
|
:default => '6 mos 1 day',
|
126
128
|
:long => '6 months 1 day',
|
127
129
|
:chrono => '6:01:00:00:00' # Yuck. FIXME
|
128
|
-
}
|
130
|
+
},
|
131
|
+
(365 * 24 * 3600 + 24 * 3600 ) =>
|
132
|
+
{
|
133
|
+
:micro => '1y1d',
|
134
|
+
:short => '1y 1d',
|
135
|
+
:default => '1 yr 1 day',
|
136
|
+
:long => '1 year 1 day',
|
137
|
+
:chrono => '1:00:01:00:00:00'
|
138
|
+
},
|
139
|
+
(3 * 365 * 24 * 3600 + 24 * 3600 ) =>
|
140
|
+
{
|
141
|
+
:micro => '3y1d',
|
142
|
+
:short => '3y 1d',
|
143
|
+
:default => '3 yrs 1 day',
|
144
|
+
:long => '3 years 1 day',
|
145
|
+
:chrono => '3:00:01:00:00:00'
|
146
|
+
},
|
129
147
|
}
|
130
|
-
|
148
|
+
|
131
149
|
@exemplars.each do |k, v|
|
132
150
|
v.each do |key, val|
|
133
151
|
it "should properly output a duration of #{k} seconds as #{val} using the #{key.to_s} format option" do
|
@@ -135,12 +153,27 @@ describe ChronicDuration, '.output' do
|
|
135
153
|
end
|
136
154
|
end
|
137
155
|
end
|
138
|
-
|
156
|
+
|
157
|
+
it "should show weeks when needed" do
|
158
|
+
ChronicDuration.output(15*24*60*60, :weeks => true).should =~ /.*wk.*/
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should show the specified number of units if provided" do
|
162
|
+
ChronicDuration.output(4 * 3600 + 60 + 1, units: 2).should == '4 hrs 1 min'
|
163
|
+
ChronicDuration.output(6 * 30 * 24 * 3600 + 24 * 3600 + 3600 + 60 + 1, units: 3, format: :long).should == '6 months 1 day 1 hour'
|
164
|
+
end
|
165
|
+
|
139
166
|
it "should use the default format when the format is not specified" do
|
140
167
|
ChronicDuration.output(2 * 3600 + 20 * 60).should == '2 hrs 20 mins'
|
141
168
|
end
|
142
|
-
|
143
|
-
|
169
|
+
|
170
|
+
@exemplars.each do |seconds,format_spec|
|
171
|
+
format_spec.each do |format,_|
|
172
|
+
it "it should properly output a duration for #{seconds} that parses back to the same thing when using the #{format.to_s} format" do
|
173
|
+
ChronicDuration.parse(ChronicDuration.output(seconds, :format => format)).should == seconds
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
144
177
|
end
|
145
178
|
|
146
179
|
|
@@ -148,37 +181,37 @@ end
|
|
148
181
|
# us in development...
|
149
182
|
|
150
183
|
describe ChronicDuration, "private methods" do
|
151
|
-
|
184
|
+
|
152
185
|
describe ".filter_by_type" do
|
153
|
-
|
186
|
+
|
154
187
|
it "should take a chrono-formatted time like 3:14 and return a human time like 3 minutes 14 seconds" do
|
155
188
|
ChronicDuration.instance_eval("filter_by_type('3:14')").should == '3 minutes 14 seconds'
|
156
189
|
end
|
157
|
-
|
190
|
+
|
158
191
|
it "should take a chrono-formatted time like 12:10:14 and return a human time like 12 hours 10 minutes 14 seconds" do
|
159
192
|
ChronicDuration.instance_eval("filter_by_type('12:10:14')").should == '12 hours 10 minutes 14 seconds'
|
160
193
|
end
|
161
|
-
|
194
|
+
|
162
195
|
it "should return the input if it's not a chrono-formatted time" do
|
163
196
|
ChronicDuration.instance_eval("filter_by_type('4 hours')").should == '4 hours'
|
164
197
|
end
|
165
|
-
|
198
|
+
|
166
199
|
end
|
167
|
-
|
200
|
+
|
168
201
|
describe ".cleanup" do
|
169
|
-
|
202
|
+
|
170
203
|
it "should clean up extraneous words" do
|
171
204
|
ChronicDuration.instance_eval("cleanup('4 days and 11 hours')").should == '4 days 11 hours'
|
172
205
|
end
|
173
|
-
|
206
|
+
|
174
207
|
it "should cleanup extraneous spaces" do
|
175
208
|
ChronicDuration.instance_eval("cleanup(' 4 days and 11 hours')").should == '4 days 11 hours'
|
176
209
|
end
|
177
|
-
|
210
|
+
|
178
211
|
it "should insert spaces where there aren't any" do
|
179
212
|
ChronicDuration.instance_eval("cleanup('4m11.5s')").should == '4 minutes 11.5 seconds'
|
180
213
|
end
|
181
|
-
|
214
|
+
|
182
215
|
end
|
183
|
-
|
184
|
-
end
|
216
|
+
|
217
|
+
end
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ChronicDuration do
|
4
|
+
|
5
|
+
describe ".parse" do
|
6
|
+
|
7
|
+
@exemplars = {
|
8
|
+
'1:20' => 60 + 20,
|
9
|
+
'1:20.51' => 60 + 20.51,
|
10
|
+
'4:01:01' => 4 * 3600 + 60 + 1,
|
11
|
+
'3 mins 4 sec' => 3 * 60 + 4,
|
12
|
+
'3 Mins 4 Sec' => 3 * 60 + 4,
|
13
|
+
'three mins four sec' => 3 * 60 + 4,
|
14
|
+
'2 hrs 20 min' => 2 * 3600 + 20 * 60,
|
15
|
+
'2h20min' => 2 * 3600 + 20 * 60,
|
16
|
+
'6 mos 1 day' => 6 * 30 * 24 * 3600 + 24 * 3600,
|
17
|
+
'1 year 6 mos 1 day' => 1 * 31536000 + 6 * 30 * 24 * 3600 + 24 * 3600,
|
18
|
+
'2.5 hrs' => 2.5 * 3600,
|
19
|
+
'47 yrs 6 mos and 4.5d' => 47 * 31536000 + 6 * 30 * 24 * 3600 + 4.5 * 24 * 3600,
|
20
|
+
'two hours and twenty minutes' => 2 * 3600 + 20 * 60,
|
21
|
+
'four hours and forty minutes' => 4 * 3600 + 40 * 60,
|
22
|
+
'four hours, and fourty minutes' => 4 * 3600 + 40 * 60,
|
23
|
+
'3 weeks and, 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
|
24
|
+
'3 weeks, plus 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
|
25
|
+
'3 weeks with 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
|
26
|
+
'1 month' => 3600 * 24 * 30,
|
27
|
+
'2 months' => 3600 * 24 * 30 * 2
|
28
|
+
}
|
29
|
+
|
30
|
+
context "when string can't be parsed" do
|
31
|
+
|
32
|
+
it "returns nil" do
|
33
|
+
ChronicDuration.parse('gobblygoo').should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when @@raise_exceptions set to true" do
|
37
|
+
|
38
|
+
it "raises with ChronicDuration::DurationParseError" do
|
39
|
+
ChronicDuration.raise_exceptions = true
|
40
|
+
lambda { ChronicDuration.parse('23 gobblygoos') }.should raise_exception(ChronicDuration::DurationParseError)
|
41
|
+
ChronicDuration.raise_exceptions = false
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return a float if seconds are in decimals" do
|
49
|
+
ChronicDuration.parse('12 mins 3.141 seconds').is_a?(Float).should be_true
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return an integer unless the seconds are in decimals" do
|
53
|
+
ChronicDuration.parse('12 mins 3 seconds').is_a?(Integer).should be_true
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should be able to parse minutes by default" do
|
57
|
+
ChronicDuration.parse('5', :default_unit => "minutes").should == 300
|
58
|
+
end
|
59
|
+
|
60
|
+
@exemplars.each do |k, v|
|
61
|
+
it "parses a duration like #{k}" do
|
62
|
+
ChronicDuration.parse(k).should == v
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '.output' do
|
69
|
+
|
70
|
+
@exemplars = {
|
71
|
+
(60 + 20) =>
|
72
|
+
{
|
73
|
+
:micro => '1m20s',
|
74
|
+
:short => '1m 20s',
|
75
|
+
:default => '1 min 20 secs',
|
76
|
+
:long => '1 minute 20 seconds',
|
77
|
+
:chrono => '1:20'
|
78
|
+
},
|
79
|
+
(60 + 20.51) =>
|
80
|
+
{
|
81
|
+
:micro => '1m20.51s',
|
82
|
+
:short => '1m 20.51s',
|
83
|
+
:default => '1 min 20.51 secs',
|
84
|
+
:long => '1 minute 20.51 seconds',
|
85
|
+
:chrono => '1:20.51'
|
86
|
+
},
|
87
|
+
(60 + 20.51928) =>
|
88
|
+
{
|
89
|
+
:micro => '1m20.51928s',
|
90
|
+
:short => '1m 20.51928s',
|
91
|
+
:default => '1 min 20.51928 secs',
|
92
|
+
:long => '1 minute 20.51928 seconds',
|
93
|
+
:chrono => '1:20.51928'
|
94
|
+
},
|
95
|
+
(4 * 3600 + 60 + 1) =>
|
96
|
+
{
|
97
|
+
:micro => '4h1m1s',
|
98
|
+
:short => '4h 1m 1s',
|
99
|
+
:default => '4 hrs 1 min 1 sec',
|
100
|
+
:long => '4 hours 1 minute 1 second',
|
101
|
+
:chrono => '4:01:01'
|
102
|
+
},
|
103
|
+
(2 * 3600 + 20 * 60) =>
|
104
|
+
{
|
105
|
+
:micro => '2h20m',
|
106
|
+
:short => '2h 20m',
|
107
|
+
:default => '2 hrs 20 mins',
|
108
|
+
:long => '2 hours 20 minutes',
|
109
|
+
:chrono => '2:20'
|
110
|
+
},
|
111
|
+
(2 * 3600 + 20 * 60) =>
|
112
|
+
{
|
113
|
+
:micro => '2h20m',
|
114
|
+
:short => '2h 20m',
|
115
|
+
:default => '2 hrs 20 mins',
|
116
|
+
:long => '2 hours 20 minutes',
|
117
|
+
:chrono => '2:20:00'
|
118
|
+
},
|
119
|
+
(6 * 30 * 24 * 3600 + 24 * 3600) =>
|
120
|
+
{
|
121
|
+
:micro => '6mo1d',
|
122
|
+
:short => '6mo 1d',
|
123
|
+
:default => '6 mos 1 day',
|
124
|
+
:long => '6 months 1 day',
|
125
|
+
:chrono => '6:01:00:00:00' # Yuck. FIXME
|
126
|
+
},
|
127
|
+
(365 * 24 * 3600 + 24 * 3600 ) =>
|
128
|
+
{
|
129
|
+
:micro => '1y1d',
|
130
|
+
:short => '1y 1d',
|
131
|
+
:default => '1 yr 1 day',
|
132
|
+
:long => '1 year 1 day',
|
133
|
+
:chrono => '1:00:01:00:00:00'
|
134
|
+
},
|
135
|
+
(3 * 365 * 24 * 3600 + 24 * 3600 ) =>
|
136
|
+
{
|
137
|
+
:micro => '3y1d',
|
138
|
+
:short => '3y 1d',
|
139
|
+
:default => '3 yrs 1 day',
|
140
|
+
:long => '3 years 1 day',
|
141
|
+
:chrono => '3:00:01:00:00:00'
|
142
|
+
},
|
143
|
+
}
|
144
|
+
|
145
|
+
@exemplars.each do |k, v|
|
146
|
+
v.each do |key, val|
|
147
|
+
it "properly outputs a duration of #{k} seconds as #{val} using the #{key.to_s} format option" do
|
148
|
+
ChronicDuration.output(k, :format => key).should == val
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it "returns weeks when needed" do
|
154
|
+
ChronicDuration.output(15*24*60*60, :weeks => true).should =~ /.*wk.*/
|
155
|
+
end
|
156
|
+
|
157
|
+
it "returns the specified number of units if provided" do
|
158
|
+
ChronicDuration.output(4 * 3600 + 60 + 1, units: 2).should == '4 hrs 1 min'
|
159
|
+
ChronicDuration.output(6 * 30 * 24 * 3600 + 24 * 3600 + 3600 + 60 + 1, units: 3, format: :long).should == '6 months 1 day 1 hour'
|
160
|
+
end
|
161
|
+
|
162
|
+
context "when the format is not specified" do
|
163
|
+
|
164
|
+
it "uses the default format" do
|
165
|
+
ChronicDuration.output(2 * 3600 + 20 * 60).should == '2 hrs 20 mins'
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
@exemplars.each do |seconds, format_spec|
|
171
|
+
format_spec.each do |format, _|
|
172
|
+
it "outputs a duration for #{seconds} that parses back to the same thing when using the #{format.to_s} format" do
|
173
|
+
ChronicDuration.parse(ChronicDuration.output(seconds, :format => format)).should == seconds
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
describe ".filter_by_type" do
|
181
|
+
|
182
|
+
it "receives a chrono-formatted time like 3:14 and return a human time like 3 minutes 14 seconds" do
|
183
|
+
ChronicDuration.instance_eval("filter_by_type('3:14')").should == '3 minutes 14 seconds'
|
184
|
+
end
|
185
|
+
|
186
|
+
it "receives chrono-formatted time like 12:10:14 and return a human time like 12 hours 10 minutes 14 seconds" do
|
187
|
+
ChronicDuration.instance_eval("filter_by_type('12:10:14')").should == '12 hours 10 minutes 14 seconds'
|
188
|
+
end
|
189
|
+
|
190
|
+
it "returns the input if it's not a chrono-formatted time" do
|
191
|
+
ChronicDuration.instance_eval("filter_by_type('4 hours')").should == '4 hours'
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
describe ".cleanup" do
|
197
|
+
|
198
|
+
it "cleans up extraneous words" do
|
199
|
+
ChronicDuration.instance_eval("cleanup('4 days and 11 hours')").should == '4 days 11 hours'
|
200
|
+
end
|
201
|
+
|
202
|
+
it "cleans up extraneous spaces" do
|
203
|
+
ChronicDuration.instance_eval("cleanup(' 4 days and 11 hours')").should == '4 days 11 hours'
|
204
|
+
end
|
205
|
+
|
206
|
+
it "inserts spaces where there aren't any" do
|
207
|
+
ChronicDuration.instance_eval("cleanup('4m11.5s')").should == '4 minutes 11.5 seconds'
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,121 +1,111 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: chronic_duration
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.0
|
4
5
|
prerelease:
|
5
|
-
version: 0.9.6
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- hpoydar
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-02-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: numerizer
|
18
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
18
|
+
requirements:
|
21
19
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
20
|
+
- !ruby/object:Gem::Version
|
23
21
|
version: 0.1.1
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rspec
|
29
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
25
|
none: false
|
31
|
-
requirements:
|
26
|
+
requirements:
|
32
27
|
- - ~>
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: bundler
|
40
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
41
33
|
none: false
|
42
|
-
requirements:
|
34
|
+
requirements:
|
43
35
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 10.0.3
|
46
38
|
type: :development
|
47
39
|
prerelease: false
|
48
|
-
version_requirements:
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: jeweler
|
51
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
41
|
none: false
|
53
|
-
requirements:
|
42
|
+
requirements:
|
54
43
|
- - ~>
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
- !ruby/object:Gem::Dependency
|
61
|
-
name: rcov
|
62
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 10.0.3
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
63
49
|
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version:
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.12.0
|
68
54
|
type: :development
|
69
55
|
prerelease: false
|
70
|
-
version_requirements:
|
71
|
-
|
72
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.12.0
|
62
|
+
description: A simple Ruby natural language parser for elapsed time. (For example,
|
63
|
+
4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in
|
64
|
+
seconds. Will return an integer unless you get tricky and need a float. (4 minutes
|
65
|
+
and 13.47 seconds, for example.) The reverse can also be performed via the output
|
66
|
+
method.
|
67
|
+
email:
|
68
|
+
- henry@poydar.com
|
73
69
|
executables: []
|
74
|
-
|
75
70
|
extensions: []
|
76
|
-
|
77
|
-
|
78
|
-
-
|
79
|
-
files:
|
71
|
+
extra_rdoc_files: []
|
72
|
+
files:
|
73
|
+
- .gitignore
|
80
74
|
- Gemfile
|
81
|
-
- Gemfile.lock
|
82
75
|
- MIT-LICENSE
|
83
|
-
- README.
|
76
|
+
- README.md
|
84
77
|
- Rakefile
|
85
|
-
- VERSION
|
86
78
|
- chronic_duration.gemspec
|
87
79
|
- lib/chronic_duration.rb
|
80
|
+
- lib/chronic_duration/version.rb
|
88
81
|
- spec/chronic_duration_spec.rb
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
82
|
+
- spec/lib/chronic_duration_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
homepage: https://github.com/hpoydar/chronic_duration
|
85
|
+
licenses: []
|
93
86
|
post_install_message:
|
94
87
|
rdoc_options: []
|
95
|
-
|
96
|
-
require_paths:
|
88
|
+
require_paths:
|
97
89
|
- lib
|
98
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
91
|
none: false
|
100
|
-
requirements:
|
101
|
-
- -
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
|
104
|
-
|
105
|
-
- 0
|
106
|
-
version: "0"
|
107
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
97
|
none: false
|
109
|
-
requirements:
|
110
|
-
- -
|
111
|
-
- !ruby/object:Gem::Version
|
112
|
-
version:
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
113
102
|
requirements: []
|
114
|
-
|
115
103
|
rubyforge_project:
|
116
|
-
rubygems_version: 1.
|
104
|
+
rubygems_version: 1.8.23
|
117
105
|
signing_key:
|
118
106
|
specification_version: 3
|
119
|
-
summary: A Ruby natural language parser for elapsed time
|
120
|
-
test_files:
|
107
|
+
summary: A simple Ruby natural language parser for elapsed time
|
108
|
+
test_files:
|
121
109
|
- spec/chronic_duration_spec.rb
|
110
|
+
- spec/lib/chronic_duration_spec.rb
|
111
|
+
- spec/spec_helper.rb
|
data/Gemfile.lock
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: http://rubygems.org/
|
3
|
-
specs:
|
4
|
-
diff-lcs (1.1.2)
|
5
|
-
git (1.2.5)
|
6
|
-
jeweler (1.5.2)
|
7
|
-
bundler (~> 1.0.0)
|
8
|
-
git (>= 1.2.5)
|
9
|
-
rake
|
10
|
-
numerizer (0.1.1)
|
11
|
-
rake (0.8.7)
|
12
|
-
rcov (0.9.9)
|
13
|
-
rspec (2.3.0)
|
14
|
-
rspec-core (~> 2.3.0)
|
15
|
-
rspec-expectations (~> 2.3.0)
|
16
|
-
rspec-mocks (~> 2.3.0)
|
17
|
-
rspec-core (2.3.1)
|
18
|
-
rspec-expectations (2.3.0)
|
19
|
-
diff-lcs (~> 1.1.2)
|
20
|
-
rspec-mocks (2.3.0)
|
21
|
-
|
22
|
-
PLATFORMS
|
23
|
-
ruby
|
24
|
-
|
25
|
-
DEPENDENCIES
|
26
|
-
bundler (~> 1.0.0)
|
27
|
-
jeweler (~> 1.5.2)
|
28
|
-
numerizer (~> 0.1.1)
|
29
|
-
rcov
|
30
|
-
rspec (~> 2.3.0)
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.9.6
|