slotter 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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +39 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/features/case_subtraction.txt +91 -0
- data/features/cases_addition.txt +91 -0
- data/features/step_definitions/time_slot_definitions.rb +48 -0
- data/features/support/env.rb +5 -0
- data/features/time_slot_addition.feature +103 -0
- data/features/time_slot_intersection.feature +5 -0
- data/features/time_slot_split.feature +32 -0
- data/features/time_slot_subtraction.feature +99 -0
- data/lib/slotter/time_slot.rb +154 -0
- data/lib/slotter.rb +2 -0
- data/slotter.gemspec +70 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/time_slot_spec.rb +4 -0
- metadata +105 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Bjarki Gudlaugsson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
= Slotter
|
2
|
+
|
3
|
+
Create and manipulate time slots simply and easily. The gem allows you to perform operations like addition, subtraction and splitting on time slots. Time slots are immutable.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
sudo gem install slotter --source http://gemcutter.org
|
8
|
+
|
9
|
+
== Examples
|
10
|
+
|
11
|
+
a = TimeSlot.new(Chronic.parse("today 10:00"), Chronic.parse("today 11:00"))
|
12
|
+
b = TimeSlot.new(Chronic.parse("today 10:00"), Chronic.parse("today 12:00"))
|
13
|
+
c = TimeSlot.new(Chronic.parse("today 11:00"), Chronic.parse("today 12:00"))
|
14
|
+
|
15
|
+
=== Concatenating
|
16
|
+
|
17
|
+
a + b #=> [#<TimeSlot:0x1018f90b0 @finish=Sun Nov 01 12:00:00 +0000 2009,
|
18
|
+
@start=Sun Nov 01 10:00:00 +0000 2009>]
|
19
|
+
a + c #=> [#<TimeSlot:0x1018df890 @finish=Sun Nov 01 12:00:00 +0000 2009,
|
20
|
+
@start=Sun Nov 01 10:00:00 +0000 2009>]
|
21
|
+
|
22
|
+
=== Subtracting
|
23
|
+
|
24
|
+
b - a #=> [#<TimeSlot:0x1018d91c0 @finish=Sun Nov 01 12:00:00 +0000 2009,
|
25
|
+
@start=Sun Nov 01 11:00:00 +0000 2009>]
|
26
|
+
b - c #=> [#<TimeSlot:0x1018dc528 @finish=Sun Nov 01 11:00:00 +0000 2009,
|
27
|
+
@start=Sun Nov 01 10:00:00 +0000 2009>]
|
28
|
+
|
29
|
+
=== Splitting
|
30
|
+
|
31
|
+
b.split(3600) #=>
|
32
|
+
[#<TimeSlot:0x1018d57f0 @finish=Sun Nov 01 11:00:00 +0000 2009,
|
33
|
+
@start=Sun Nov 01 10:00:00 +0000 2009>,
|
34
|
+
#<TimeSlot:0x1018d5728 @finish=Sun Nov 01 12:00:00 +0000 2009,
|
35
|
+
@start=Sun Nov 01 11:00:00 +0000 2009>]
|
36
|
+
|
37
|
+
== Copyright
|
38
|
+
|
39
|
+
Copyright (c) 2009 Bjarki Gudlaugsson. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "slotter"
|
8
|
+
gem.summary = %Q{create and manipulate time slots simply and easily}
|
9
|
+
gem.description = %Q{the gem allows you to perform operations like addition, subtraction and splitting on time slots}
|
10
|
+
gem.email = "bjarkigud@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/bjarkigud/slotter"
|
12
|
+
gem.authors = ["Bjarki Gudlaugsson"]
|
13
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
+
gem.add_development_dependency "chronic", ">= 0.2.3"
|
15
|
+
gem.add_development_dependency "cucumber", ">= 0.4.2"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :spec => :check_dependencies
|
36
|
+
|
37
|
+
begin
|
38
|
+
require 'cucumber/rake/task'
|
39
|
+
Cucumber::Rake::Task.new(:cucumber)
|
40
|
+
|
41
|
+
task :features => :check_dependencies
|
42
|
+
rescue LoadError
|
43
|
+
task :features do
|
44
|
+
abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
task :default => :spec
|
49
|
+
|
50
|
+
require 'rake/rdoctask'
|
51
|
+
Rake::RDocTask.new do |rdoc|
|
52
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
53
|
+
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
55
|
+
rdoc.title = "slotter #{version}"
|
56
|
+
rdoc.rdoc_files.include('README*')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,91 @@
|
|
1
|
+
##############################
|
2
|
+
# Case 1
|
3
|
+
# +-----+ +-----+
|
4
|
+
# | A | - | B | => nil
|
5
|
+
# +-----+ +-----+
|
6
|
+
##############################
|
7
|
+
# Case 2
|
8
|
+
# +-----+ +-----+
|
9
|
+
# | A | | |
|
10
|
+
# +-----+ - | B | => nil
|
11
|
+
# | |
|
12
|
+
# +-----+
|
13
|
+
##############################
|
14
|
+
# Case 3
|
15
|
+
# +-----+
|
16
|
+
# +-----+ | |
|
17
|
+
# | A | - | B | => nil
|
18
|
+
# +-----+ | |
|
19
|
+
# +-----+
|
20
|
+
##############################
|
21
|
+
# Case 4
|
22
|
+
# +-----+ +-----+ A.start
|
23
|
+
# | A | | C |
|
24
|
+
# +-----+ - +-----+ => +-----+ A.finish
|
25
|
+
# | B |
|
26
|
+
# +-----+
|
27
|
+
##############################
|
28
|
+
# Case 5
|
29
|
+
# +-----+
|
30
|
+
# | B |
|
31
|
+
# +-----+ - +-----+ => +-----+ A.start
|
32
|
+
# | A | | C |
|
33
|
+
# +-----+ +-----+ A.finish
|
34
|
+
##############################
|
35
|
+
# Case 6
|
36
|
+
# +-----+ +-----+ A.start
|
37
|
+
# | A | | C |
|
38
|
+
# +-----+ +-----+ A.finish
|
39
|
+
# - =>
|
40
|
+
# +-----+
|
41
|
+
# | B |
|
42
|
+
# +-----+
|
43
|
+
##############################
|
44
|
+
# Case 7
|
45
|
+
# +-----+
|
46
|
+
# | B |
|
47
|
+
# +-----+
|
48
|
+
# - =>
|
49
|
+
# +-----+ +-----+ A.start
|
50
|
+
# | A | | C |
|
51
|
+
# +-----+ +-----+ A.finish
|
52
|
+
##############################
|
53
|
+
# Case 8
|
54
|
+
# +-----+ +-----+
|
55
|
+
# | | | B |
|
56
|
+
# | A | - +-----+ => +-----+ B.finish
|
57
|
+
# | | | C |
|
58
|
+
# +-----+ +-----+ A.finish
|
59
|
+
##############################
|
60
|
+
# Case 9
|
61
|
+
# +-----+ +-----+ A.start
|
62
|
+
# | | | C |
|
63
|
+
# | A | - +-----+ => +-----+ B.start
|
64
|
+
# | | | B |
|
65
|
+
# +-----+ +-----+
|
66
|
+
##############################
|
67
|
+
# Case 10
|
68
|
+
# +-----+ +-----+ A.start
|
69
|
+
# | | | C |
|
70
|
+
# | | +-----+ +-----+ B.start
|
71
|
+
# | A | - | B | =>
|
72
|
+
# | | +-----+ +-----+ B.finish
|
73
|
+
# | | | C |
|
74
|
+
# +-----+ +-----+ A.finish
|
75
|
+
##############################
|
76
|
+
# Case 11
|
77
|
+
# +-----+ +-----+ A.start
|
78
|
+
# | | | |
|
79
|
+
# | A | | C |
|
80
|
+
# | | - +-----+ => +-----+ B.start
|
81
|
+
# +-----+ | B |
|
82
|
+
# +-----+
|
83
|
+
##############################
|
84
|
+
# Case 12
|
85
|
+
# +-----+
|
86
|
+
# +-----+ | B |
|
87
|
+
# | | - +-----+ => +-----+ B.finish
|
88
|
+
# | A | | C |
|
89
|
+
# | | | |
|
90
|
+
# +-----+ +-----+ A.finish
|
91
|
+
##############################
|
@@ -0,0 +1,91 @@
|
|
1
|
+
##############################
|
2
|
+
# Case 1
|
3
|
+
# +-----+ +-----+ +-----+ A.start
|
4
|
+
# | A | + | B | => | C |
|
5
|
+
# +-----+ +-----+ +-----+ A.finish
|
6
|
+
##############################
|
7
|
+
# Case 2
|
8
|
+
# +-----+ +-----+ +-----+ B.start
|
9
|
+
# | A | | | | |
|
10
|
+
# +-----+ + | B | => | C |
|
11
|
+
# | | | |
|
12
|
+
# +-----+ +-----+ B.finish
|
13
|
+
##############################
|
14
|
+
# Case 3
|
15
|
+
# +-----+ +-----+ B.start
|
16
|
+
# +-----+ | | | |
|
17
|
+
# | A | + | B | => | C |
|
18
|
+
# +-----+ | | | |
|
19
|
+
# +-----+ +-----+ B.finish
|
20
|
+
##############################
|
21
|
+
# Case 4
|
22
|
+
# +-----+ +-----+ A.start
|
23
|
+
# | A | | |
|
24
|
+
# +-----+ + +-----+ => | C |
|
25
|
+
# | B | | |
|
26
|
+
# +-----+ +-----+ B.finish
|
27
|
+
##############################
|
28
|
+
# Case 5
|
29
|
+
# +-----+ +-----+ B.start
|
30
|
+
# | B | | |
|
31
|
+
# +-----+ + +-----+ => | C |
|
32
|
+
# | A | | |
|
33
|
+
# +-----+ +-----+ A.finish
|
34
|
+
##############################
|
35
|
+
# Case 6
|
36
|
+
# +-----+ +-----+ A.start
|
37
|
+
# | A | | C |
|
38
|
+
# +-----+ +-----+ A.finish
|
39
|
+
# + =>
|
40
|
+
# +-----+ +-----+ B.start
|
41
|
+
# | B | | C |
|
42
|
+
# +-----+ +-----+ B.finish
|
43
|
+
##############################
|
44
|
+
# Case 7
|
45
|
+
# +-----+ +-----+ B.start
|
46
|
+
# | B | | C |
|
47
|
+
# +-----+ +-----+ B.finish
|
48
|
+
# + =>
|
49
|
+
# +-----+ +-----+ A.start
|
50
|
+
# | A | | C |
|
51
|
+
# +-----+ +-----+ A.finish
|
52
|
+
##############################
|
53
|
+
# Case 8
|
54
|
+
# +-----+ +-----+ +-----+ A.start
|
55
|
+
# | | | B | | |
|
56
|
+
# | A | + +-----+ => | C |
|
57
|
+
# | | | |
|
58
|
+
# +-----+ +-----+ A.finish
|
59
|
+
##############################
|
60
|
+
# Case 9
|
61
|
+
# +-----+ +-----+ A.start
|
62
|
+
# | | | |
|
63
|
+
# | A | + +-----+ => | C |
|
64
|
+
# | | | B | | |
|
65
|
+
# +-----+ +-----+ +-----+ A.finish
|
66
|
+
##############################
|
67
|
+
# Case 10
|
68
|
+
# +-----+ +-----+ A.start
|
69
|
+
# | | | |
|
70
|
+
# | | +-----+ | |
|
71
|
+
# | A | + | B | => | C |
|
72
|
+
# | | +-----+ | |
|
73
|
+
# | | | |
|
74
|
+
# +-----+ +-----+ A.finish
|
75
|
+
##############################
|
76
|
+
# Case 11
|
77
|
+
# +-----+ +-----+ A.start
|
78
|
+
# | | | |
|
79
|
+
# | A | | |
|
80
|
+
# | | + +-----+ => | C |
|
81
|
+
# +-----+ | B | | |
|
82
|
+
# +-----+ +-----+ B.finish
|
83
|
+
##############################
|
84
|
+
# Case 12
|
85
|
+
# +-----+ +-----+ B.start
|
86
|
+
# +-----+ | B | | |
|
87
|
+
# | | + +-----+ => | C |
|
88
|
+
# | A | | |
|
89
|
+
# | | | |
|
90
|
+
# +-----+ +-----+ A.finish
|
91
|
+
##############################
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Given /^I have a time slot "([^\"]*)" between "([^\"]*)" and "([^\"]*)"$/ do |name, start, finish|
|
2
|
+
@time_slots ||= {}
|
3
|
+
@time_slots[name] = TimeSlot.new(Chronic.parse("today " + start), Chronic.parse("today " + finish))
|
4
|
+
end
|
5
|
+
|
6
|
+
When /^I subtract time slot "([^\"]*)" from time slot "([^\"]*)"$/ do |a, b|
|
7
|
+
@result = @time_slots[b] - @time_slots[a]
|
8
|
+
end
|
9
|
+
|
10
|
+
When /^I add time slot "([^\"]*)" to time slot "([^\"]*)"$/ do |a, b|
|
11
|
+
@result = @time_slots[b] + @time_slots[a]
|
12
|
+
end
|
13
|
+
|
14
|
+
When /^I split time slot "([^\"]*)" into ([0-9]+) second slots$/ do |name, duration|
|
15
|
+
@result = @time_slots[name].split(duration.to_i)
|
16
|
+
end
|
17
|
+
|
18
|
+
Then /^I should have a time slot between "([^\"]*)" and "([^\"]*)"$/ do |start, finish|
|
19
|
+
@result.start.should == Chronic.parse(start)
|
20
|
+
@result.finish.should == Chronic.parse(finish)
|
21
|
+
end
|
22
|
+
|
23
|
+
Then /^I should have an array of ([0-9]+) time slots$/ do |size|
|
24
|
+
@result.is_a?(Array).should == true
|
25
|
+
@result.length.should == size.to_i
|
26
|
+
for slot in @result
|
27
|
+
slot.is_a?(TimeSlot).should == true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Then /^one should be between "([^\"]*)" and "([^\"]*)"$/ do |start, finish|
|
32
|
+
found = false
|
33
|
+
for slot in @result
|
34
|
+
if slot.start == Chronic.parse("today " + start) and
|
35
|
+
slot.finish == Chronic.parse("today " + finish)
|
36
|
+
found = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
found.should == true
|
40
|
+
end
|
41
|
+
|
42
|
+
Then /^I should have nil as a result$/ do
|
43
|
+
@result.should == nil
|
44
|
+
end
|
45
|
+
|
46
|
+
Then /^the array should be empty$/ do
|
47
|
+
@result.should be_empty
|
48
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
Feature: Time slot addition
|
2
|
+
In order to simplify creating applications based around time slots
|
3
|
+
As a developer
|
4
|
+
I want to be able to concatenate time slots through code
|
5
|
+
|
6
|
+
# Case 1
|
7
|
+
Scenario: Add a time slot to another where they are equal
|
8
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
9
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
10
|
+
When I add time slot "B" to time slot "A"
|
11
|
+
Then I should have an array of 1 time slots
|
12
|
+
Then one should be between "10:00" and "11:00"
|
13
|
+
|
14
|
+
# Case 2
|
15
|
+
Scenario: Add A.start == B.start
|
16
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
17
|
+
And I have a time slot "B" between "10:00" and "12:00"
|
18
|
+
When I add time slot "B" to time slot "A"
|
19
|
+
Then I should have an array of 1 time slots
|
20
|
+
Then one should be between "10:00" and "12:00"
|
21
|
+
|
22
|
+
# Case 3
|
23
|
+
Scenario: Add A.start > B.start and A.finish < B.finish
|
24
|
+
Given I have a time slot "A" between "11:00" and "12:00"
|
25
|
+
And I have a time slot "B" between "10:00" and "13:00"
|
26
|
+
When I add time slot "B" to time slot "A"
|
27
|
+
Then I should have an array of 1 time slots
|
28
|
+
Then one should be between "10:00" and "13:00"
|
29
|
+
|
30
|
+
# Case 4
|
31
|
+
Scenario: Add A.finish == B.start
|
32
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
33
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
34
|
+
When I add time slot "B" to time slot "A"
|
35
|
+
Then I should have an array of 1 time slots
|
36
|
+
Then one should be between "10:00" and "12:00"
|
37
|
+
|
38
|
+
# Case 5
|
39
|
+
Scenario: Add A.start == B.finish
|
40
|
+
Given I have a time slot "A" between "11:00" and "12:00"
|
41
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
42
|
+
When I add time slot "B" to time slot "A"
|
43
|
+
Then I should have an array of 1 time slots
|
44
|
+
Then one should be between "10:00" and "12:00"
|
45
|
+
|
46
|
+
# Case 6
|
47
|
+
Scenario: Add non-intersecting A.finish < B.start
|
48
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
49
|
+
And I have a time slot "B" between "12:00" and "13:00"
|
50
|
+
When I add time slot "B" to time slot "A"
|
51
|
+
Then I should have an array of 1 time slots
|
52
|
+
And one should be between "10:00" and "11:00"
|
53
|
+
And one should be between "12:00" and "13:00"
|
54
|
+
|
55
|
+
# Case 7
|
56
|
+
Scenario: Add non-intersecting A.start > B.finish
|
57
|
+
Given I have a time slot "A" between "12:00" and "13:00"
|
58
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
59
|
+
When I add time slot "B" to time slot "A"
|
60
|
+
Then I should have an array of 2 time slots
|
61
|
+
And one should be between "10:00" and "11:00"
|
62
|
+
And one should be between "12:00" and "13:00"
|
63
|
+
|
64
|
+
# Case 8
|
65
|
+
Scenario: Add A.start == B.start and A.finish > B.finish
|
66
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
67
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
68
|
+
When I add time slot "B" to time slot "A"
|
69
|
+
Then I should have an array of 1 time slots
|
70
|
+
And one should be between "10:00" and "12:00"
|
71
|
+
|
72
|
+
# Case 9
|
73
|
+
Scenario: Add A.start < B.start and A.finish == B.finish
|
74
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
75
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
76
|
+
When I add time slot "B" to time slot "A"
|
77
|
+
Then I should have an array of 1 time slots
|
78
|
+
And one should be between "10:00" and "12:00"
|
79
|
+
|
80
|
+
# Case 10
|
81
|
+
Scenario: Add A.start < B.start and A.finish > B.finish
|
82
|
+
Given I have a time slot "A" between "10:00" and "13:00"
|
83
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
84
|
+
When I add time slot "B" to time slot "A"
|
85
|
+
Then I should have an array of 1 time slots
|
86
|
+
And one should be between "10:00" and "13:00"
|
87
|
+
|
88
|
+
# Case 11
|
89
|
+
Scenario: Add a half intersecting time slot (A.finish < B.finish)
|
90
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
91
|
+
And I have a time slot "B" between "11:00" and "13:00"
|
92
|
+
When I add time slot "B" to time slot "A"
|
93
|
+
Then I should have an array of 1 time slots
|
94
|
+
And one should be between "10:00" and "13:00"
|
95
|
+
|
96
|
+
# Case 12
|
97
|
+
Scenario: Add a half intersecting time slot (A.start > B.start)
|
98
|
+
Given I have a time slot "A" between "11:00" and "13:00"
|
99
|
+
And I have a time slot "B" between "10:00" and "12:00"
|
100
|
+
When I add time slot "B" to time slot "A"
|
101
|
+
Then I should have an array of 1 time slots
|
102
|
+
And one should be between "10:00" and "13:00"
|
103
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Feature: Time slot split
|
2
|
+
In order to do correct time slot calculations
|
3
|
+
As a developer
|
4
|
+
I want to be able to split time slots through code
|
5
|
+
|
6
|
+
Scenario: Split a 1 hour time slot into 1 hour time slots
|
7
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
8
|
+
When I split time slot "A" into 3600 second slots
|
9
|
+
Then I should have an array of 1 time slots
|
10
|
+
And one should be between "10:00" and "11:00"
|
11
|
+
|
12
|
+
Scenario: Split a 3 hour time slot into 1 hour time slots
|
13
|
+
Given I have a time slot "A" between "10:00" and "13:00"
|
14
|
+
When I split time slot "A" into 3600 second slots
|
15
|
+
Then I should have an array of 3 time slots
|
16
|
+
And one should be between "10:00" and "11:00"
|
17
|
+
And one should be between "11:00" and "12:00"
|
18
|
+
And one should be between "12:00" and "13:00"
|
19
|
+
|
20
|
+
Scenario: Split a 2 hour and 45 minute time slot into 1 hour time slots
|
21
|
+
Given I have a time slot "A" between "10:00" and "12:45"
|
22
|
+
When I split time slot "A" into 3600 second slots
|
23
|
+
Then I should have an array of 3 time slots
|
24
|
+
And one should be between "10:00" and "11:00"
|
25
|
+
And one should be between "11:00" and "12:00"
|
26
|
+
And one should be between "12:00" and "12:45"
|
27
|
+
|
28
|
+
Scenario: Split a 30 minute slot into 1 hour time slots
|
29
|
+
Given I have a time slot "A" between "10:00" and "10:30"
|
30
|
+
When I split time slot "A" into 3600 second slots
|
31
|
+
Then I should have an array of 1 time slots
|
32
|
+
And one should be between "10:00" and "10:30"
|
@@ -0,0 +1,99 @@
|
|
1
|
+
Feature: Time slot subtraction
|
2
|
+
In order to simplify creating applications based around time slots
|
3
|
+
As a developer
|
4
|
+
I want to be able to subtract time slots through code
|
5
|
+
|
6
|
+
# Case 1
|
7
|
+
Scenario: Subtract a time slot from another where they are equal
|
8
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
9
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
10
|
+
When I subtract time slot "B" from time slot "A"
|
11
|
+
Then I should have an array of 0 time slots
|
12
|
+
|
13
|
+
# Case 2
|
14
|
+
Scenario: Subtract a large time slot from a small time slot with equal start
|
15
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
16
|
+
And I have a time slot "B" between "10:00" and "12:00"
|
17
|
+
When I subtract time slot "B" from time slot "A"
|
18
|
+
Then I should have an array of 0 time slots
|
19
|
+
|
20
|
+
# Case 3
|
21
|
+
Scenario: Subtract a bigger time slot from a smaller
|
22
|
+
Given I have a time slot "A" between "11:00" and "12:00"
|
23
|
+
And I have a time slot "B" between "10:00" and "13:00"
|
24
|
+
When I subtract time slot "B" from time slot "A"
|
25
|
+
Then I should have an array of 0 time slots
|
26
|
+
|
27
|
+
# Case 4
|
28
|
+
Scenario: Subtract non-intersecting A.finish == B.start
|
29
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
30
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
31
|
+
When I subtract time slot "B" from time slot "A"
|
32
|
+
Then I should have an array of 1 time slots
|
33
|
+
And one should be between "10:00" and "11:00"
|
34
|
+
|
35
|
+
# Case 5
|
36
|
+
Scenario: Subtract non-intersecting A.start == B.finish
|
37
|
+
Given I have a time slot "A" between "11:00" and "12:00"
|
38
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
39
|
+
When I subtract time slot "B" from time slot "A"
|
40
|
+
Then I should have an array of 1 time slots
|
41
|
+
And one should be between "11:00" and "12:00"
|
42
|
+
|
43
|
+
# Case 6
|
44
|
+
Scenario: Subtract non-intersecting A.finish < B.start
|
45
|
+
Given I have a time slot "A" between "10:00" and "11:00"
|
46
|
+
And I have a time slot "B" between "12:00" and "13:00"
|
47
|
+
When I subtract time slot "B" from time slot "A"
|
48
|
+
Then I should have an array of 1 time slots
|
49
|
+
And one should be between "10:00" and "11:00"
|
50
|
+
|
51
|
+
# Case 7
|
52
|
+
Scenario: Subtract non-intersecting A.start > B.finish
|
53
|
+
Given I have a time slot "A" between "12:00" and "13:00"
|
54
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
55
|
+
When I subtract time slot "B" from time slot "A"
|
56
|
+
Then I should have an array of 1 time slots
|
57
|
+
And one should be between "12:00" and "13:00"
|
58
|
+
|
59
|
+
# Case 8
|
60
|
+
Scenario: Subtract a small time slot from a bit time slot when start is equal
|
61
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
62
|
+
And I have a time slot "B" between "10:00" and "11:00"
|
63
|
+
When I subtract time slot "B" from time slot "A"
|
64
|
+
Then I should have an array of 1 time slots
|
65
|
+
And one should be between "11:00" and "12:00"
|
66
|
+
|
67
|
+
# Case 9
|
68
|
+
Scenario: Subtract a small time slot from a big time slot when finish is equal
|
69
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
70
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
71
|
+
When I subtract time slot "B" from time slot "A"
|
72
|
+
Then I should have an array of 1 time slots
|
73
|
+
And one should be between "10:00" and "11:00"
|
74
|
+
|
75
|
+
# Case 10
|
76
|
+
Scenario: Subtract a contained time slot
|
77
|
+
Given I have a time slot "A" between "10:00" and "13:00"
|
78
|
+
And I have a time slot "B" between "11:00" and "12:00"
|
79
|
+
When I subtract time slot "B" from time slot "A"
|
80
|
+
Then I should have an array of 2 time slots
|
81
|
+
And one should be between "10:00" and "11:00"
|
82
|
+
And one should be between "12:00" and "13:00"
|
83
|
+
|
84
|
+
# Case 11
|
85
|
+
Scenario: Subtract a half intersecting time slot (A.finish < B.finish)
|
86
|
+
Given I have a time slot "A" between "10:00" and "12:00"
|
87
|
+
And I have a time slot "B" between "11:00" and "13:00"
|
88
|
+
When I subtract time slot "B" from time slot "A"
|
89
|
+
Then I should have an array of 1 time slots
|
90
|
+
And one should be between "10:00" and "11:00"
|
91
|
+
|
92
|
+
# Case 12
|
93
|
+
Scenario: Subtract a half intersecting time slot (A.start > B.start)
|
94
|
+
Given I have a time slot "A" between "11:00" and "13:00"
|
95
|
+
And I have a time slot "B" between "10:00" and "12:00"
|
96
|
+
When I subtract time slot "B" from time slot "A"
|
97
|
+
Then I should have an array of 1 time slots
|
98
|
+
And one should be between "12:00" and "13:00"
|
99
|
+
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# A TimeSlot object holds the start date and finish date of a period in time
|
2
|
+
class TimeSlot
|
3
|
+
include Comparable
|
4
|
+
attr_reader :start, :finish
|
5
|
+
|
6
|
+
def initialize(start, finish)
|
7
|
+
@start = start
|
8
|
+
@finish = finish
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the difference between start and finish of the TimeSlot in seconds
|
12
|
+
def duration
|
13
|
+
(self.finish - self.start)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Subtraction---Returns a set of new TimeSlot(s) that are the result of
|
17
|
+
# removing the other_slot from this slot.
|
18
|
+
def -(other_slot)
|
19
|
+
# Case 1, Case 2 or Case 3
|
20
|
+
if (self.start == other_slot.start and self.finish == other_slot.finish) or
|
21
|
+
(self.start == other_slot.start and self.finish < other_slot.finish) or
|
22
|
+
(self.start > other_slot.start and self.finish < other_slot.finish)
|
23
|
+
return []
|
24
|
+
end
|
25
|
+
# Case 4, Case 5, Case 6 or Case 7
|
26
|
+
if (self.finish == other_slot.start) or
|
27
|
+
(self.start == other_slot.finish) or
|
28
|
+
(self.finish < other_slot.start) or
|
29
|
+
(self.start > other_slot.finish)
|
30
|
+
return [self.clone]
|
31
|
+
end
|
32
|
+
# Case 8
|
33
|
+
if self.start == other_slot.start and self.finish > other_slot.finish
|
34
|
+
return [TimeSlot.new(other_slot.finish, self.finish)]
|
35
|
+
end
|
36
|
+
# Case 9 or Case 11
|
37
|
+
if (self.start < other_slot.start and self.finish == other_slot.finish) or
|
38
|
+
(self.start < other_slot.start and self.finish < other_slot.finish and self.finish > other_slot.start)
|
39
|
+
return [TimeSlot.new(self.start, other_slot.start)]
|
40
|
+
end
|
41
|
+
# Case 10
|
42
|
+
if self.start < other_slot.start and self.finish > other_slot.finish
|
43
|
+
return [TimeSlot.new(self.start, other_slot.start),
|
44
|
+
TimeSlot.new(other_slot.finish, self.finish)]
|
45
|
+
end
|
46
|
+
# Case 12
|
47
|
+
if self.start > other_slot.start and self.finish > other_slot.finish and self.start < other_slot.finish
|
48
|
+
return [TimeSlot.new(other_slot.finish, self.finish)]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Concatenation---Returns a set of new TimeSlot(s) that are the result of
|
53
|
+
# concatenating the other_slot to this slot.
|
54
|
+
def +(other_slot)
|
55
|
+
# Case 1
|
56
|
+
if self.start == other_slot.start and self.finish == other_slot.finish
|
57
|
+
return [self.clone]
|
58
|
+
end
|
59
|
+
# Case 2 or Case 3
|
60
|
+
if (self.start == other_slot.start and self.finish < other_slot.finish) or
|
61
|
+
(self.start > other_slot.start and self.finish < other_slot.finish)
|
62
|
+
return [other_slot.clone]
|
63
|
+
end
|
64
|
+
# Case 4
|
65
|
+
if self.finish == other_slot.start
|
66
|
+
return [TimeSlot.new(self.start, other_slot.finish)]
|
67
|
+
end
|
68
|
+
# Case 5
|
69
|
+
if self.start == other_slot.finish
|
70
|
+
return [TimeSlot.new(other_slot.start, self.finish)]
|
71
|
+
end
|
72
|
+
# Case 6 or Case 7
|
73
|
+
if (self.finish < other_slot.start) or
|
74
|
+
(self.start > other_slot.finish)
|
75
|
+
return [self.clone, other_slot.clone].sort!
|
76
|
+
end
|
77
|
+
# Case 8, Case 9 or Case 10
|
78
|
+
if (self.start == other_slot.start and self.finish > other_slot.finish) or
|
79
|
+
(self.start < other_slot.start and self.finish == other_slot.finish) or
|
80
|
+
(self.start < other_slot.start and self.finish > other_slot.finish)
|
81
|
+
return [self.clone]
|
82
|
+
end
|
83
|
+
# Case 11
|
84
|
+
if self.start < other_slot.start and self.finish < other_slot.finish and self.finish > other_slot.start
|
85
|
+
return [TimeSlot.new(self.start, other_slot.finish)]
|
86
|
+
end
|
87
|
+
# Case 12
|
88
|
+
if self.start > other_slot.start and self.finish > other_slot.finish and self.start < other_slot.finish
|
89
|
+
return [TimeSlot.new(other_slot.start, self.finish)]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Equality---Two time slots are equal if they have the same start and finish
|
94
|
+
def ==(other_slot)
|
95
|
+
(self.start == other_slot.start and self.finish == other_slot.finish)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Comparison---Returns an integer (-1, 0,
|
99
|
+
# or +1) if this time slot is less than, equal to, or greater than
|
100
|
+
# other_slot. First we compare the start of both slots and if they are equal
|
101
|
+
# then we compare the finish of both slots. Thus, two arrays are ``equal''
|
102
|
+
# according to <code>TimeSlot#<=></code> if an only if they have the same
|
103
|
+
# start and finish.
|
104
|
+
#
|
105
|
+
# today_at_nine = Chronic.parse("today 09:00")
|
106
|
+
# today_at_ten = Chronic.parse("today 10:00")
|
107
|
+
# today_at_eleven = Chronic.parse("today 11:00")
|
108
|
+
#
|
109
|
+
# a = TimeSlot.new(today_at_nine, today_at_ten)
|
110
|
+
# b = TimeSlot.new(today_at_ten, today_at_eleven)
|
111
|
+
# c = TimeSlot.new(today_at_nine, today_at_eleven)
|
112
|
+
#
|
113
|
+
# a <=> b #=> -1
|
114
|
+
# a <=> c #=> -1
|
115
|
+
# b <=> c #=> +1
|
116
|
+
#
|
117
|
+
def <=>(other_slot)
|
118
|
+
cmp = self.start <=> other_slot.start
|
119
|
+
(cmp == 0) ? self.finish <=> other_slot.finish : cmp
|
120
|
+
end
|
121
|
+
|
122
|
+
# Split this time slot into a set of new TimeSlot(s) where the duration of
|
123
|
+
# each slot is equal to or smaller than <i>length</i>.
|
124
|
+
#
|
125
|
+
# The duration of the last slot in the result will be set to the remainder if
|
126
|
+
# the this time slot cannot be divided equally based on <i>length</i>.
|
127
|
+
#
|
128
|
+
# a = TimeSlot.new(Chronic.parse("today 10:00"), Chronic.parse("today 12:30"))
|
129
|
+
#
|
130
|
+
# a.split(3600) #=> [
|
131
|
+
# #<TimeSlot:0x1018cf3a0 @start=Sun Nov 01 10:00:00 +0000 2009,
|
132
|
+
# @finish=Sun Nov 01 11:00:00 +0000 2009>,
|
133
|
+
# #<TimeSlot:0x1018cf260 @start=Sun Nov 01 11:00:00 +0000 2009,
|
134
|
+
# @finish=Sun Nov 01 12:00:00 +0000 2009>,
|
135
|
+
# #<TimeSlot:0x1018cf198 @start=Sun Nov 01 12:00:00 +0000 2009,
|
136
|
+
# @finish=Sun Nov 01 12:30:00 +0000 2009>]
|
137
|
+
#
|
138
|
+
def split(length)
|
139
|
+
result = []
|
140
|
+
if self.duration <= length
|
141
|
+
result << self.clone
|
142
|
+
else
|
143
|
+
current = TimeSlot.new(self.start, self.start + length)
|
144
|
+
result << current
|
145
|
+
result += (self - current)[0].split(length)
|
146
|
+
end
|
147
|
+
return result
|
148
|
+
end
|
149
|
+
|
150
|
+
# Shows the start and end of this TimeSlot
|
151
|
+
def to_s
|
152
|
+
"#{self.start} to #{self.finish}"
|
153
|
+
end
|
154
|
+
end
|
data/lib/slotter.rb
ADDED
data/slotter.gemspec
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{slotter}
|
8
|
+
s.version = "0.0.1"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Bjarki Gudlaugsson"]
|
12
|
+
s.date = %q{2009-11-01}
|
13
|
+
s.description = %q{the gem allows you to perform operations like addition, subtraction and splitting on time slots}
|
14
|
+
s.email = %q{bjarkigud@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"features/case_subtraction.txt",
|
27
|
+
"features/cases_addition.txt",
|
28
|
+
"features/step_definitions/time_slot_definitions.rb",
|
29
|
+
"features/support/env.rb",
|
30
|
+
"features/time_slot_addition.feature",
|
31
|
+
"features/time_slot_intersection.feature",
|
32
|
+
"features/time_slot_split.feature",
|
33
|
+
"features/time_slot_subtraction.feature",
|
34
|
+
"lib/slotter.rb",
|
35
|
+
"lib/slotter/time_slot.rb",
|
36
|
+
"slotter.gemspec",
|
37
|
+
"spec/spec.opts",
|
38
|
+
"spec/spec_helper.rb",
|
39
|
+
"spec/time_slot_spec.rb"
|
40
|
+
]
|
41
|
+
s.homepage = %q{http://github.com/bjarkigud/slotter}
|
42
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
43
|
+
s.require_paths = ["lib"]
|
44
|
+
s.rubygems_version = %q{1.3.5}
|
45
|
+
s.summary = %q{create and manipulate time slots simply and easily}
|
46
|
+
s.test_files = [
|
47
|
+
"spec/spec_helper.rb",
|
48
|
+
"spec/time_slot_spec.rb"
|
49
|
+
]
|
50
|
+
|
51
|
+
if s.respond_to? :specification_version then
|
52
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
53
|
+
s.specification_version = 3
|
54
|
+
|
55
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
56
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
57
|
+
s.add_development_dependency(%q<chronic>, [">= 0.2.3"])
|
58
|
+
s.add_development_dependency(%q<cucumber>, [">= 0.4.2"])
|
59
|
+
else
|
60
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
61
|
+
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
62
|
+
s.add_dependency(%q<cucumber>, [">= 0.4.2"])
|
63
|
+
end
|
64
|
+
else
|
65
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
66
|
+
s.add_dependency(%q<chronic>, [">= 0.2.3"])
|
67
|
+
s.add_dependency(%q<cucumber>, [">= 0.4.2"])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'slotter'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'chronic'
|
8
|
+
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: slotter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bjarki Gudlaugsson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-01 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: chronic
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.3
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: cucumber
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.4.2
|
44
|
+
version:
|
45
|
+
description: the gem allows you to perform operations like addition, subtraction and splitting on time slots
|
46
|
+
email: bjarkigud@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
- README.rdoc
|
54
|
+
files:
|
55
|
+
- .document
|
56
|
+
- .gitignore
|
57
|
+
- LICENSE
|
58
|
+
- README.rdoc
|
59
|
+
- Rakefile
|
60
|
+
- VERSION
|
61
|
+
- features/case_subtraction.txt
|
62
|
+
- features/cases_addition.txt
|
63
|
+
- features/step_definitions/time_slot_definitions.rb
|
64
|
+
- features/support/env.rb
|
65
|
+
- features/time_slot_addition.feature
|
66
|
+
- features/time_slot_intersection.feature
|
67
|
+
- features/time_slot_split.feature
|
68
|
+
- features/time_slot_subtraction.feature
|
69
|
+
- lib/slotter.rb
|
70
|
+
- lib/slotter/time_slot.rb
|
71
|
+
- slotter.gemspec
|
72
|
+
- spec/spec.opts
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/time_slot_spec.rb
|
75
|
+
has_rdoc: true
|
76
|
+
homepage: http://github.com/bjarkigud/slotter
|
77
|
+
licenses: []
|
78
|
+
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options:
|
81
|
+
- --charset=UTF-8
|
82
|
+
require_paths:
|
83
|
+
- lib
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
version:
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: "0"
|
95
|
+
version:
|
96
|
+
requirements: []
|
97
|
+
|
98
|
+
rubyforge_project:
|
99
|
+
rubygems_version: 1.3.5
|
100
|
+
signing_key:
|
101
|
+
specification_version: 3
|
102
|
+
summary: create and manipulate time slots simply and easily
|
103
|
+
test_files:
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
- spec/time_slot_spec.rb
|