rduration 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create 1.9.3@duration_gem
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby-duration.gemspec
4
+ gemspec
5
+
6
+ # Guard & Devtools
7
+ gem 'guard', '~> 0.8.8'
8
+ # MacOS notifications:
9
+ gem 'rb-fsevent', :require => ('rb-fsevent' if RUBY_PLATFORM =~ /darwin/i)
10
+ gem 'growl', :require => ('growl' if RUBY_PLATFORM =~ /darwin/i)
11
+ gem 'guard-bundler'
12
+ gem 'guard-rspec'
data/Guardfile ADDED
@@ -0,0 +1,10 @@
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard 'rspec', :version => 2, :cli => '--color --format nested', :all_on_start => true, :all_after_pass => true do
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ watch(%r{^spec/.+_spec\.rb$})
9
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
10
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Matt Wilson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # Duration
2
+
3
+ Provides simple (somewhat naive) Duration parsing from strings. Allows you to compare and modify durations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rduration', :require => 'duration'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rduration
18
+
19
+ ## Usage
20
+
21
+ `duration_spec.rb` has more details about the types of strings this can handle, but here's brief overview:
22
+
23
+ ```ruby
24
+ a = Duration.new("01:46:00")
25
+ b = Duration.new("25 minutes 17 seconds")
26
+ a > b # => true
27
+ a - b # => #<Duration:2164349940 @raw="4843">
28
+ [b, a].sort # => [a, b]
29
+
30
+ b.to_clock_format # => "25:17"
31
+ ```
32
+
33
+ If you require 'duration/string_ext' then strings gain a new method: `#to_duration`
34
+
35
+ ```ruby
36
+ "35m 5s".to_duration # => NoMethodError: undefined method `to_duration' for "35m 5s":String
37
+
38
+ require 'duration/string_ext'
39
+ "35m 5s".to_duration # => #<Duration:2151903540 @raw="35m 5s">
40
+
41
+ # once you've done this, the arithmetic and comparison stuff works too
42
+ "35m 5s".to_duration > "10m" # => true
43
+ "35m 5s".to_duration > "50m" # => false
44
+ "35m 5s".to_duration + "10m" # => #<Duration:2156162420 @raw="2705">
45
+ ```
46
+
47
+ ### Formats
48
+
49
+ Here's a list of formats that will parse:
50
+
51
+ ```
52
+ Duration
53
+ #parse
54
+ parses "0" as 0 seconds
55
+ parses "00:00" as 0 seconds
56
+ parses "0 seconds" as 0 seconds
57
+ parses nil as 0 seconds
58
+ parses "45s" as 45 seconds
59
+ parses "45 seconds" as 45 seconds
60
+ parses "00:00:45" as 45 seconds
61
+ parses "45" as 45 seconds
62
+ parses "137s" as 137 seconds
63
+ parses "2m17s" as 137 seconds
64
+ parses "2 minutes 17 seconds" as 137 seconds
65
+ parses "02:17" as 137 seconds
66
+ parses "2:17" as 137 seconds
67
+ parses "1h32m07s" as 5527 seconds
68
+ parses "1:32:07" as 5527 seconds
69
+ parses "92 minutes and 7 seconds" as 5527 seconds
70
+ parses "3d10h15m" as 296100 seconds
71
+ parses "3:10:15:00" as 296100 seconds
72
+ parses "82 hours 15 minutes" as 296100 seconds
73
+ ```
74
+
75
+ ### Interesting Methods
76
+
77
+ * `#to_clock_format` leverages `#to_s`'s newfound proc handling powers to format the output. Speaking of...
78
+ * `#to_s` takes a proc, and yields the duration in seconds to it. This is useful for output.
79
+
80
+ ## CHANGELOG
81
+
82
+ * **v0.0.1 Hello World**
83
+ * Handles all of my use cases. Could be better at everything, though :).
84
+
85
+ ## Contributing
86
+
87
+ 1. Fork it
88
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
89
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
90
+ 4. Push to the branch (`git push origin my-new-feature`)
91
+ 5. Create new Pull Request
92
+
93
+ ## Copyright
94
+
95
+ Copyright (c) 2012 Matt Wilson. See LICENSE for details, but it's MIT.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,15 @@
1
+ class Duration
2
+ module Arithmatic
3
+ def + other_duration
4
+ raise StandardError.new("Cannot add #{other_duration.class} to #{self}") unless other_duration.respond_to?(:to_i)
5
+ other_duration = other_duration.to_duration if other_duration.respond_to?(:to_duration)
6
+ Duration.new(self.to_i + other_duration.to_i)
7
+ end
8
+
9
+ def - other_duration
10
+ raise StandardError.new("Cannot subtract #{other_duration.class} from #{self}") unless other_duration.respond_to?(:to_i)
11
+ other_duration = other_duration.to_duration if other_duration.respond_to?(:to_duration)
12
+ Duration.new(self.to_i - other_duration.to_i)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,5 @@
1
+ class String
2
+ def to_duration
3
+ Duration.new(self)
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ class Duration
2
+ VERSION = "0.0.1"
3
+ end
data/lib/duration.rb ADDED
@@ -0,0 +1,99 @@
1
+ require "duration/version"
2
+ require "duration/arithmatic"
3
+
4
+ class Duration
5
+ attr_accessor :raw
6
+
7
+ include Comparable
8
+ include Arithmatic
9
+
10
+ def initialize input
11
+ self.raw = input.to_s
12
+ end
13
+
14
+ def parse
15
+ @parsed ||= count normalize_input
16
+ end
17
+ alias_method :to_i, :parse
18
+
19
+ def normalize_input input = raw.dup
20
+ input = condense_duration_tokens input # => '92 m and 7 s'
21
+ input = strip_useless_words input # => '92 m 7 s'
22
+ input = intelligently_space input # => '92m 7s'
23
+ convert_to_normal_form input # '92:07' => '92m 7s'
24
+ end
25
+
26
+ def condense_duration_tokens input = raw.dup
27
+ input.gsub(/(#{DURATIONS.keys.join("|")})/, DURATIONS)
28
+ end
29
+
30
+ def strip_useless_words input = raw.dup
31
+ input.gsub(/[[:alpha:]]{2,}/, "").gsub(/[^\ddhms:]/, " ").squeeze(" ")
32
+ end
33
+
34
+ def intelligently_space input = raw.dup
35
+ input.gsub(/\s/, "").gsub(/([[:alpha:]])(?=[[:digit:]])/, '\1 ')
36
+ end
37
+
38
+ def convert_to_normal_form input = raw.dup
39
+ return input unless input =~ /:/ || input !~ /[[:alpha:]]/
40
+ split = input.split(":").reverse
41
+ split.zip(UNITS).reverse.map { |unit| unit.join("") }.join(" ")
42
+ end
43
+
44
+ def hashify string
45
+ string.split(" ").inject({}) do |accum, token|
46
+ _, amount, type = token.split(/([[:digit:]]+)(?=[[:alpha:]])/)
47
+ accum[type] = amount.to_i
48
+ accum
49
+ end
50
+ end
51
+
52
+ def count input = normalize_input
53
+ hashify(input).inject(0) do |accum, (unit, how_many)|
54
+ accum += how_many * STANDARD_CONVERSION[unit]
55
+ accum
56
+ end
57
+ end
58
+
59
+ def to_clock_format
60
+ to_s proc { |s|
61
+ a = STANDARD_CONVERSION.values.dup
62
+ [(s / a[3]), (s % a[3] / a[2]), (s % a[2] / a[1]), (s % a[1])].
63
+ each_with_index.
64
+ reject { |value, index| index < 2 && value == 0 }.
65
+ map { |value| "%02d" % value }.
66
+ join(":")
67
+ }
68
+ end
69
+
70
+ def to_s formatter = nil
71
+ formatter ? formatter.call(parse) : "#<Duration:#{self.object_id} @raw=#{raw.inspect} @clock=#{to_clock_format.inspect}>"
72
+ end
73
+
74
+ UNITS = ['s', 'm', 'h', 'd']
75
+
76
+ DURATIONS = {
77
+ 'seconds' => 's',
78
+ 'minutes' => 'm',
79
+ 'hours' => 'h',
80
+ 'days' => 'd',
81
+ 'sec' => 's',
82
+ 'hrs' => 'h',
83
+ 'mins' => 'm'
84
+ }
85
+ DURATIONS.default_proc = proc { |hash, key| hash[key] = "" }
86
+
87
+ STANDARD_CONVERSION = {
88
+ 's' => 1,
89
+ 'm' => 60,
90
+ 'h' => 3600,
91
+ 'd' => 86_400
92
+ }
93
+
94
+ # Comparable Protocol:
95
+ def <=> other_thing
96
+ other_thing = other_thing.to_duration if other_thing.respond_to?(:to_duration)
97
+ self.to_i <=> other_thing.to_i
98
+ end
99
+ end
data/rduration.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/duration/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.authors = ["Matt Wilson"]
6
+ s.email = ["mhw@hypomodern.com"]
7
+ s.description = %q{Simple utility for parsing durations from strings and comparing them. Basic math is also supported.}
8
+ s.summary = %q{Parse durations from strings and manipulate them.}
9
+ s.homepage = "https://github.com/hypomodern/rduration"
10
+
11
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ s.name = "rduration"
15
+ s.require_paths = ["lib"]
16
+ s.version = Duration::VERSION
17
+
18
+ s.add_development_dependency 'rake'
19
+ s.add_development_dependency 'rspec'
20
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+ require 'duration/string_ext'
3
+
4
+ describe String do
5
+ describe "#to_duration" do
6
+ it "returns a duration object" do
7
+ duration = "2 hours 5 minutes".to_duration
8
+ duration.should be_a_kind_of(Duration)
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+
3
+ describe Duration do
4
+ describe "#initialize" do
5
+ it "stores the raw input string in an attribute called #raw" do
6
+ d = Duration.new("00:01")
7
+ d.raw.should == "00:01"
8
+ end
9
+ it "coerces the input to a string" do
10
+ d = Duration.new(nil)
11
+ d.raw.should == ""
12
+ end
13
+ end
14
+
15
+ describe "#parse" do
16
+ expected_second_values_and_their_strings = {
17
+ 0 => [ '0', '00:00', '0 seconds', nil ],
18
+ 45 => [ '45s', '45 seconds', '00:00:45', '45' ],
19
+ 137 => [ '137s', '2m17s', '2 minutes 17 seconds', '02:17', '2:17' ],
20
+ 5_527 => [ '1h32m07s', '1:32:07', '92 minutes and 7 seconds' ],
21
+ 296_100 => [ '3d10h15m', '3:10:15:00', '82 hours 15 minutes' ]
22
+ }
23
+ expected_second_values_and_their_strings.each do |(expected, inputs)|
24
+ inputs.each do |possible_input|
25
+ it "parses #{possible_input.inspect} as #{expected} seconds" do
26
+ Duration.new(possible_input).parse.should == expected
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ describe "#to_i" do
33
+ it "is an alias for #parse" do
34
+ Duration.new('45s').to_i.should == 45
35
+ end
36
+ end
37
+
38
+ describe "#normalize_input" do
39
+ normal_form_and_variants = {
40
+ '45s' => [ '45s', '45 seconds', '45' ],
41
+ '00h 00m 45s' => ['00:00:45'],
42
+ '2m 17s' => [ '2m17s', '2 minutes 17 seconds', '2:17','2m 17s' ],
43
+ '137s' => ['137s'],
44
+ '1h 32m 07s' => [ '1h32m07s', '1:32:07', '1h 32m 07s' ],
45
+ '3d 10h 15m 00s' => [ '3d10h15m00s', '3:10:15:00', '3d 10h 15m 00s' ],
46
+ '82h 15m' => ['82 hours, 15 minutes'],
47
+ '92m 7s' => ['92 minutes and 7 seconds']
48
+ }
49
+ normal_form_and_variants.each do |(expected, inputs)|
50
+ inputs.each do |input|
51
+ it "normalizes #{input.inspect} to #{expected.inspect}" do
52
+ Duration.new(input).normalize_input.should == expected
53
+ end
54
+ end
55
+ end
56
+ it "doesn't modify the #raw attibute" do
57
+ input = '92 minutes and 7 seconds'
58
+ Duration.new(input).tap { |s| s.normalize_input }.raw.should == input
59
+ end
60
+ end
61
+
62
+ describe "#condense_duration_tokens" do
63
+ forms_to_condense = {
64
+ '2 minutes 17 seconds' => '2 m 17 s',
65
+ '3 days 10 hours 15 minutes' => '3 d 10 h 15 m',
66
+ '2:17' => '2:17'
67
+ }
68
+ forms_to_condense.each do |(input, expectation)|
69
+ it "converts #{input.inspect} into #{expectation.inspect}" do
70
+ Duration.new(input).condense_duration_tokens.should == expectation
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "#strip_useless_words" do
76
+ forms_with_useless_words = {
77
+ '92 m and 7 s' => '92 m 7 s',
78
+ '3 d, 8 h, and 11 m' => '3 d 8 h 11 m',
79
+ '3m + 18s' => '3m 18s',
80
+ '2:17' => '2:17'
81
+ }
82
+ forms_with_useless_words.each do |(input, expectation)|
83
+ it "converts #{input.inspect} to #{expectation.inspect}" do
84
+ Duration.new(input).strip_useless_words.should == expectation
85
+ end
86
+ end
87
+ end
88
+
89
+ describe "#intelligently_space" do
90
+ spaced_out_forms = {
91
+ '1h32m07s' => '1h 32m 07s',
92
+ '92 m 7 s' => '92m 7s',
93
+ '3 d 8 h 11 m' => '3d 8h 11m',
94
+ '3m 18s' => '3m 18s',
95
+ '2:17' => '2:17'
96
+ }
97
+ spaced_out_forms.each do |(input, expectation)|
98
+ it "converts #{input.inspect} to #{expectation.inspect}" do
99
+ Duration.new(input).intelligently_space.should == expectation
100
+ end
101
+ end
102
+ end
103
+
104
+ describe "#convert_to_normal_form" do
105
+ clock_forms = {
106
+ '1:32:07' => '1h 32m 07s',
107
+ '92:07' => '92m 07s',
108
+ '03:08:11:00' => '03d 08h 11m 00s',
109
+ '03:00' => '03m 00s',
110
+ '2m 17s' => '2m 17s',
111
+ '45' => '45s'
112
+ }
113
+ clock_forms.each do |(input, expectation)|
114
+ it "converts #{input.inspect} to #{expectation.inspect}" do
115
+ Duration.new(input).convert_to_normal_form.should == expectation
116
+ end
117
+ end
118
+ end
119
+
120
+ describe "#hashify" do
121
+ it "maps a string to an easily-countable hash form" do
122
+ Duration.new("42m 3s").hashify("42m 3s").should == {
123
+ "m" => 42,
124
+ "s" => 3
125
+ }
126
+ end
127
+ normalized_inputs = {
128
+ '1h 32m 07s' => { 'h' => 1, 'm' => 32, 's' => 7 },
129
+ '03d 08h 11m 00s' => { 'd' => 3, 'h' => 8, 'm' => 11, 's' => 0 },
130
+ }
131
+ normalized_inputs.each do |(input, expectation)|
132
+ it "converts #{input.inspect} to #{expectation.inspect}" do
133
+ Duration.new(input).hashify(input).should == expectation
134
+ end
135
+ end
136
+ end
137
+
138
+ describe "#to_clock_format" do
139
+ clocks = {
140
+ 0 => '00:00',
141
+ 45 => '00:45',
142
+ 137 => '02:17',
143
+ 5_527 => '01:32:07',
144
+ 296_100 => '03:10:15:00'
145
+ }
146
+ clocks.each do |seconds, formatted|
147
+ it "outputs #{formatted.inspect} given #{seconds} seconds" do
148
+ Duration.new(seconds).to_clock_format.should == formatted
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "#to_s" do
154
+ context "but with a formatter proc/lambda" do
155
+ it "calls the formatter, yielding the current number of seconds" do
156
+ formatted = Duration.new(500).to_s proc { |s| "Mein formatt sagt #{s}" }
157
+ formatted.should == "Mein formatt sagt 500"
158
+ end
159
+ end
160
+ it "just returns something like #to_s normally does" do
161
+ d = Duration.new(500)
162
+ d.to_s.should == "#<Duration:#{d.object_id} @raw=\"500\" @clock=\"08:20\">"
163
+ end
164
+ end
165
+
166
+ describe "Comparable compatibility" do
167
+ describe "#<=>" do
168
+ it "compares Durations based on their #to_i values" do
169
+ ( Duration.new("01:04:55") > Duration.new("55m 3s") ).should be_true
170
+ ( Duration.new("55m 3s") > Duration.new("30 minutes and 14 seconds") ).should be_true
171
+ ( Duration.new("04:22") > Duration.new("75") ).should be_true
172
+ end
173
+ end
174
+ end
175
+
176
+ describe "basic maths" do
177
+ let(:a) { Duration.new("55 seconds") }
178
+ let(:b) { Duration.new("1m 10s") }
179
+ describe "#+" do
180
+ it "returns a new Duration..." do
181
+ added = a + b
182
+ added.should be_a_kind_of(Duration)
183
+ [a.object_id, b.object_id].should_not include(added.object_id)
184
+ end
185
+ it "sums the two Durations by seconds" do
186
+ added = a+b
187
+ added.to_i.should == 125
188
+ added.to_clock_format.should == "02:05"
189
+ end
190
+ end
191
+ describe "#-" do
192
+ it "returns a new Duration..." do
193
+ difference = b - a
194
+ difference.should be_a_kind_of(Duration)
195
+ [a.object_id, b.object_id].should_not include(difference.object_id)
196
+ end
197
+ it "subtracts the two Durations by seconds" do
198
+ difference = b - a
199
+ difference.to_i.should == 15
200
+ difference.to_clock_format.should == "00:15"
201
+ end
202
+ end
203
+ end
204
+
205
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'duration' # and any other gems you need
5
+
6
+
7
+ RSpec.configure do |config|
8
+ config.treat_symbols_as_metadata_keys_with_true_values = true
9
+ config.run_all_when_everything_filtered = true
10
+ config.filter_run :focus
11
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rduration
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Wilson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &2156379680 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2156379680
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &2156379180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *2156379180
36
+ description: Simple utility for parsing durations from strings and comparing them.
37
+ Basic math is also supported.
38
+ email:
39
+ - mhw@hypomodern.com
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - .rspec
46
+ - .rvmrc
47
+ - Gemfile
48
+ - Guardfile
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - lib/duration.rb
53
+ - lib/duration/arithmatic.rb
54
+ - lib/duration/string_ext.rb
55
+ - lib/duration/version.rb
56
+ - rduration.gemspec
57
+ - spec/duration/string_ext_spec.rb
58
+ - spec/duration_spec.rb
59
+ - spec/spec_helper.rb
60
+ homepage: https://github.com/hypomodern/rduration
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.17
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Parse durations from strings and manipulate them.
84
+ test_files:
85
+ - spec/duration/string_ext_spec.rb
86
+ - spec/duration_spec.rb
87
+ - spec/spec_helper.rb