rduration 0.0.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.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/Gemfile +12 -0
- data/Guardfile +10 -0
- data/LICENSE +22 -0
- data/README.md +95 -0
- data/Rakefile +2 -0
- data/lib/duration/arithmatic.rb +15 -0
- data/lib/duration/string_ext.rb +5 -0
- data/lib/duration/version.rb +3 -0
- data/lib/duration.rb +99 -0
- data/rduration.gemspec +20 -0
- data/spec/duration/string_ext_spec.rb +12 -0
- data/spec/duration_spec.rb +205 -0
- data/spec/spec_helper.rb +11 -0
- metadata +87 -0
data/.gitignore
ADDED
data/.rspec
ADDED
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,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
|
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,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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|