tod 1.5.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +25 -35
- data/MIT-LICENSE +1 -1
- data/README.markdown +138 -59
- data/lib/tod.rb +0 -10
- data/lib/tod/conversions.rb +9 -11
- data/lib/tod/core_extensions.rb +2 -0
- data/lib/tod/date_extensions.rb +15 -0
- data/lib/tod/mongoization.rb +10 -1
- data/lib/tod/shift.rb +35 -21
- data/lib/tod/time_extensions.rb +9 -0
- data/lib/tod/version.rb +1 -1
- data/test/support/active_record.rb +2 -2
- data/test/test_helper.rb +5 -3
- data/test/tod/conversion_test.rb +29 -25
- data/test/tod/date_test.rb +11 -12
- data/test/tod/shift_test.rb +132 -57
- data/test/tod/time_of_day_serializable_attribute_test.rb +14 -10
- data/test/tod/time_of_day_test.rb +94 -97
- data/test/tod/time_of_day_time_zone_with_active_support_test.rb +23 -9
- data/test/tod/time_test.rb +4 -4
- data/tod.gemspec +1 -3
- metadata +6 -34
- data/lib/tod/date.rb +0 -11
- data/lib/tod/time.rb +0 -5
- data/test/tod/a_a_a_time_of_day_time_zone_without_active_support_test.rb +0 -12
data/lib/tod/shift.rb
CHANGED
@@ -1,41 +1,55 @@
|
|
1
1
|
module Tod
|
2
|
+
|
3
|
+
# Shift is a range-like class that handles wrapping around midnight.
|
4
|
+
# For example, the Shift of 2300 to 0200 would include 0100.
|
2
5
|
class Shift
|
3
|
-
attr_reader :beginning, :ending
|
6
|
+
attr_reader :beginning, :ending, :range
|
4
7
|
|
5
|
-
def initialize(beginning, ending)
|
8
|
+
def initialize(beginning, ending, exclude_end=false)
|
6
9
|
raise ArgumentError, "beginning can not be nil" unless beginning
|
7
10
|
raise ArgumentError, "ending can not be nil" unless ending
|
11
|
+
unless [true, false].include? exclude_end
|
12
|
+
raise ArgumentError, "exclude_end must be true or false"
|
13
|
+
end
|
8
14
|
|
9
15
|
@beginning = beginning
|
10
16
|
@ending = ending
|
17
|
+
@exclude_end = exclude_end
|
18
|
+
|
19
|
+
normalized_ending = ending.to_i
|
20
|
+
normalized_ending += TimeOfDay::NUM_SECONDS_IN_DAY if normalized_ending < beginning.to_i
|
21
|
+
|
22
|
+
@range = Range.new(beginning.to_i, normalized_ending, @exclude_end)
|
23
|
+
|
11
24
|
freeze # Shift instances are value objects
|
12
25
|
end
|
13
26
|
|
14
|
-
# Returns true if the time of day is inside the shift
|
27
|
+
# Returns true if the time of day is inside the shift, false otherwise.
|
15
28
|
def include?(tod)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
29
|
+
second = tod.to_i
|
30
|
+
second += TimeOfDay::NUM_SECONDS_IN_DAY if second < @range.first
|
31
|
+
@range.cover?(second)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns true if ranges overlap, false otherwise.
|
35
|
+
def overlaps?(other)
|
36
|
+
a, b = [self, other].map(&:range).sort_by(&:first)
|
37
|
+
op = a.exclude_end? ? :> : :>=
|
38
|
+
a.last.send(op, b.first)
|
39
|
+
end
|
40
|
+
|
41
|
+
def contains?(shift)
|
42
|
+
self.include?(shift.beginning) && self.include?(shift.ending)
|
23
43
|
end
|
24
44
|
|
25
45
|
# Return shift duration in seconds.
|
26
46
|
# if ending is lower than beginning this method will calculate the duration as the ending time is from the following day
|
27
47
|
def duration
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
duration_day_1 = (end_of_day.to_i - beginning.to_i) + 1
|
34
|
-
duration_day_2 = (ending.to_i - start_of_day.to_i)
|
35
|
-
duration_day_1 + duration_day_2
|
36
|
-
end
|
48
|
+
@range.last - @range.first
|
49
|
+
end
|
50
|
+
|
51
|
+
def exclude_end?
|
52
|
+
@exclude_end
|
37
53
|
end
|
38
54
|
end
|
39
55
|
end
|
40
|
-
|
41
|
-
Shift = Tod::Shift
|
data/lib/tod/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__),'..','lib')
|
2
2
|
|
3
3
|
require 'bundler/setup'
|
4
|
+
require 'active_support/time'
|
4
5
|
require 'tod'
|
5
|
-
require '
|
6
|
-
require '
|
7
|
-
|
6
|
+
require 'tod/core_extensions'
|
7
|
+
require 'minitest/autorun'
|
8
|
+
|
9
|
+
Time.zone = "Central Time (US & Canada)"
|
data/test/tod/conversion_test.rb
CHANGED
@@ -1,48 +1,52 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
|
2
|
-
require 'active_support/time'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
t = TimeOfDay.new(13, 56, 12)
|
7
|
-
tod = TimeOfDay(t)
|
3
|
+
describe "TimeOfDay()" do
|
4
|
+
it "handles Tod::TimeOfDay" do
|
5
|
+
t = Tod::TimeOfDay.new(13, 56, 12)
|
6
|
+
tod = Tod::TimeOfDay(t)
|
8
7
|
|
9
8
|
assert_equal(t, tod)
|
10
9
|
end
|
11
|
-
|
10
|
+
|
11
|
+
it "handles Time" do
|
12
12
|
t = Time.new(2014, 2, 27, 12, 01, 02)
|
13
|
-
tod = TimeOfDay(t)
|
13
|
+
tod = Tod::TimeOfDay(t)
|
14
14
|
|
15
|
-
assert_equal(tod, TimeOfDay.new(12, 01, 02))
|
15
|
+
assert_equal(tod, Tod::TimeOfDay.new(12, 01, 02))
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
|
+
it "handles Date" do
|
18
19
|
t = Date.new(2014, 2, 27)
|
19
|
-
tod = TimeOfDay(t)
|
20
|
+
tod = Tod::TimeOfDay(t)
|
20
21
|
|
21
|
-
assert_equal(tod, TimeOfDay.new(0, 0, 0))
|
22
|
+
assert_equal(tod, Tod::TimeOfDay.new(0, 0, 0))
|
22
23
|
end
|
23
|
-
|
24
|
+
|
25
|
+
it "handles DateTime" do
|
24
26
|
t = DateTime.new(2014, 2, 27, 12, 01, 02)
|
25
|
-
tod = TimeOfDay(t)
|
27
|
+
tod = Tod::TimeOfDay(t)
|
26
28
|
|
27
|
-
assert_equal(tod, TimeOfDay.new(12, 01, 02))
|
29
|
+
assert_equal(tod, Tod::TimeOfDay.new(12, 01, 02))
|
28
30
|
end
|
29
|
-
|
31
|
+
|
32
|
+
it "parses string" do
|
30
33
|
t = "12:01:02"
|
31
|
-
tod = TimeOfDay(t)
|
34
|
+
tod = Tod::TimeOfDay(t)
|
32
35
|
|
33
|
-
assert_equal(tod, TimeOfDay.new(12, 01, 02))
|
36
|
+
assert_equal(tod, Tod::TimeOfDay.new(12, 01, 02))
|
34
37
|
end
|
35
|
-
|
38
|
+
|
39
|
+
it "parses 'noon'" do
|
36
40
|
t = "noon"
|
37
|
-
tod = TimeOfDay(t)
|
41
|
+
tod = Tod::TimeOfDay(t)
|
38
42
|
|
39
|
-
assert_equal(tod, TimeOfDay.new(12, 00, 00))
|
43
|
+
assert_equal(tod, Tod::TimeOfDay.new(12, 00, 00))
|
40
44
|
end
|
41
|
-
|
45
|
+
|
46
|
+
it "parses 'midnight'" do
|
42
47
|
t = "midnight"
|
43
|
-
tod = TimeOfDay(t)
|
48
|
+
tod = Tod::TimeOfDay(t)
|
44
49
|
|
45
|
-
assert_equal(tod, TimeOfDay.new(0, 00, 00))
|
50
|
+
assert_equal(tod, Tod::TimeOfDay.new(0, 00, 00))
|
46
51
|
end
|
47
|
-
|
48
|
-
end
|
52
|
+
end
|
data/test/tod/date_test.rb
CHANGED
@@ -1,28 +1,27 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
|
2
|
-
require 'active_support/time'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
describe "Date extensions" do
|
4
|
+
describe "#at" do
|
5
|
+
it "accepts TimeOfDay and return Time on same date" do
|
7
6
|
date = Date.civil 2000,1,1
|
8
|
-
tod = TimeOfDay.new 8,30
|
9
|
-
assert_equal Time.local(2000,1,1, 8,30), date.at(tod)
|
7
|
+
tod = Tod::TimeOfDay.new 8,30
|
8
|
+
assert_equal Time.zone.local(2000,1,1, 8,30), date.at(tod)
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
11
|
+
describe "with a time zone" do
|
12
|
+
it "accepts TimeOfDay and TimeWithZone on same date" do
|
14
13
|
date = Date.civil 2000,1,1
|
15
|
-
tod = TimeOfDay.new 8,30
|
14
|
+
tod = Tod::TimeOfDay.new 8,30
|
16
15
|
time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
|
17
16
|
assert_equal time_zone.local(2000,1,1, 8,30), date.at(tod, time_zone)
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
|
-
|
23
|
-
|
21
|
+
describe "#to_time_day" do
|
22
|
+
it "is TimeOfDay" do
|
24
23
|
date_time = DateTime.new 2013, 9, 19, 15, 17, 34
|
25
|
-
assert_equal TimeOfDay.new(15, 17, 34), date_time.to_time_of_day
|
24
|
+
assert_equal Tod::TimeOfDay.new(15, 17, 34), date_time.to_time_of_day
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
data/test/tod/shift_test.rb
CHANGED
@@ -1,94 +1,169 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
|
2
|
-
require 'active_support/time'
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
describe "Shift" do
|
4
|
+
describe "#initialize" do
|
5
|
+
it "parses bounds" do
|
6
|
+
shift = Tod::Shift.new Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(10), false
|
7
|
+
refute shift.exclude_end?
|
8
|
+
|
9
|
+
shift = Tod::Shift.new Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(10), true
|
10
|
+
assert shift.exclude_end?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#duration" do
|
15
|
+
it "returns correct duration when first time is lower than the second one" do
|
7
16
|
duration_expected = 4 * 60 * 60 + 30 * 60 + 30 # 4 hours, 30 min and 30 sec later
|
8
|
-
tod1 = TimeOfDay.new 8,30
|
9
|
-
tod2 = TimeOfDay.new 13,00,30
|
10
|
-
shift = Shift.new tod1, tod2
|
17
|
+
tod1 = Tod::TimeOfDay.new 8,30
|
18
|
+
tod2 = Tod::TimeOfDay.new 13,00,30
|
19
|
+
shift = Tod::Shift.new tod1, tod2
|
11
20
|
duration = shift.duration
|
12
21
|
assert_equal duration, duration_expected
|
13
22
|
end
|
14
|
-
|
23
|
+
|
24
|
+
it "returns correct duration when first time is greater than the second one" do
|
15
25
|
duration_expected = 4 * 60 * 60 + 30 * 60 + 30 # 4 hours, 30 min and 30 sec later
|
16
|
-
tod1 = TimeOfDay.new 22,30
|
17
|
-
tod2 = TimeOfDay.new 3,00,30
|
18
|
-
shift = Shift.new tod1, tod2
|
26
|
+
tod1 = Tod::TimeOfDay.new 22,30
|
27
|
+
tod2 = Tod::TimeOfDay.new 3,00,30
|
28
|
+
shift = Tod::Shift.new tod1, tod2
|
19
29
|
duration = shift.duration
|
20
30
|
assert_equal duration, duration_expected
|
21
31
|
end
|
22
|
-
|
23
|
-
|
24
|
-
|
32
|
+
|
33
|
+
it "is zero when both times are equal" do
|
34
|
+
tod1 = Tod::TimeOfDay.new 3,00,30
|
35
|
+
shift = Tod::Shift.new tod1, tod1
|
25
36
|
duration = shift.duration
|
26
37
|
assert_equal duration, 0
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
|
41
|
+
describe "overlaps?" do
|
42
|
+
it "is true when shifts overlap" do
|
43
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(12), Tod::TimeOfDay.new(18))
|
44
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(13), Tod::TimeOfDay.new(15))
|
45
|
+
assert shift1.overlaps?(shift2)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "is false when shifts don't overlap" do
|
49
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5))
|
50
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(12))
|
51
|
+
refute shift1.overlaps?(shift2)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "is true when shifts touch with inclusive end" do
|
55
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5))
|
56
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12))
|
57
|
+
assert shift1.overlaps?(shift2)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "is false when shifts touch with exclusive end" do
|
61
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5), true)
|
62
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12), true)
|
63
|
+
refute shift1.overlaps?(shift2)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "contains?" do
|
68
|
+
it "is true when one shift contains another" do
|
69
|
+
outside = Tod::Shift.new(Tod::TimeOfDay.new(12), Tod::TimeOfDay.new(18))
|
70
|
+
inside = Tod::Shift.new(Tod::TimeOfDay.new(13), Tod::TimeOfDay.new(15))
|
71
|
+
assert outside.contains?(inside)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "is false when a shift is contained by another" do
|
75
|
+
outside = Tod::Shift.new(Tod::TimeOfDay.new(12), Tod::TimeOfDay.new(18))
|
76
|
+
inside = Tod::Shift.new(Tod::TimeOfDay.new(13), Tod::TimeOfDay.new(15))
|
77
|
+
refute inside.contains?(outside)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "is false when shifts don't even overlap" do
|
81
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(12), Tod::TimeOfDay.new(15))
|
82
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(18), Tod::TimeOfDay.new(19))
|
83
|
+
refute shift1.contains?(shift2)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#include?" do
|
31
88
|
# |------------------------|--------T1----V----T2----|------------------------|
|
32
|
-
|
33
|
-
tod1 = TimeOfDay.new 8
|
34
|
-
tod2 = TimeOfDay.new 16
|
35
|
-
value = TimeOfDay.new 12
|
36
|
-
shift = Shift.new tod1, tod2
|
37
|
-
|
89
|
+
it "is true when value is between ToDs and boths tods are in the same day" do
|
90
|
+
tod1 = Tod::TimeOfDay.new 8
|
91
|
+
tod2 = Tod::TimeOfDay.new 16
|
92
|
+
value = Tod::TimeOfDay.new 12
|
93
|
+
shift = Tod::Shift.new tod1, tod2
|
94
|
+
assert shift.include?(value)
|
38
95
|
end
|
39
96
|
|
40
97
|
# |------------------T1----|-------V----------T2-----|------------------------|
|
41
|
-
|
42
|
-
tod1 = TimeOfDay.new 20
|
43
|
-
tod2 = TimeOfDay.new 15
|
44
|
-
value = TimeOfDay.new 12
|
45
|
-
shift = Shift.new tod1, tod2
|
46
|
-
|
98
|
+
it "is true when value is on second day between ToDs and start ToD is in a different day" do
|
99
|
+
tod1 = Tod::TimeOfDay.new 20
|
100
|
+
tod2 = Tod::TimeOfDay.new 15
|
101
|
+
value = Tod::TimeOfDay.new 12
|
102
|
+
shift = Tod::Shift.new tod1, tod2
|
103
|
+
assert shift.include?(value)
|
47
104
|
end
|
48
105
|
|
49
106
|
# |------------------T1--V-|------------------T2-----|------------------------|
|
50
|
-
|
51
|
-
tod1 = TimeOfDay.new 20
|
52
|
-
tod2 = TimeOfDay.new 15
|
53
|
-
value = TimeOfDay.new 22
|
54
|
-
shift = Shift.new tod1, tod2
|
55
|
-
|
107
|
+
it "is true when value is on first day between ToDs and start ToD is in a different day" do
|
108
|
+
tod1 = Tod::TimeOfDay.new 20
|
109
|
+
tod2 = Tod::TimeOfDay.new 15
|
110
|
+
value = Tod::TimeOfDay.new 22
|
111
|
+
shift = Tod::Shift.new tod1, tod2
|
112
|
+
assert shift.include?(value)
|
56
113
|
end
|
57
114
|
|
58
115
|
# |------------------------|--------T1----------V----|----T2------------------|
|
59
|
-
|
60
|
-
tod1 = TimeOfDay.new 16
|
61
|
-
tod2 = TimeOfDay.new 4
|
62
|
-
value = TimeOfDay.new 20
|
63
|
-
shift = Shift.new tod1, tod2
|
64
|
-
|
116
|
+
it "is true when value is on first day between ToDs and end ToD is in a different day" do
|
117
|
+
tod1 = Tod::TimeOfDay.new 16
|
118
|
+
tod2 = Tod::TimeOfDay.new 4
|
119
|
+
value = Tod::TimeOfDay.new 20
|
120
|
+
shift = Tod::Shift.new tod1, tod2
|
121
|
+
assert shift.include?(value)
|
65
122
|
end
|
66
123
|
|
67
124
|
# |------------------------|--------T1---------------|--V---T2----------------|
|
68
|
-
|
69
|
-
tod1 = TimeOfDay.new 16
|
70
|
-
tod2 = TimeOfDay.new 4
|
71
|
-
value = TimeOfDay.new 2
|
72
|
-
shift = Shift.new tod1, tod2
|
73
|
-
|
125
|
+
it "is true when value is on second day between ToDs and end ToD is in a different day" do
|
126
|
+
tod1 = Tod::TimeOfDay.new 16
|
127
|
+
tod2 = Tod::TimeOfDay.new 4
|
128
|
+
value = Tod::TimeOfDay.new 2
|
129
|
+
shift = Tod::Shift.new tod1, tod2
|
130
|
+
assert shift.include?(value)
|
74
131
|
end
|
75
132
|
|
76
133
|
# |------------------------|--------T1-----T2----V---|------------------------|
|
77
|
-
|
78
|
-
tod1 = TimeOfDay.new 10
|
79
|
-
tod2 = TimeOfDay.new 16
|
80
|
-
value = TimeOfDay.new 20
|
81
|
-
shift = Shift.new tod1, tod2
|
82
|
-
|
134
|
+
it "is false when value is after second ToD" do
|
135
|
+
tod1 = Tod::TimeOfDay.new 10
|
136
|
+
tod2 = Tod::TimeOfDay.new 16
|
137
|
+
value = Tod::TimeOfDay.new 20
|
138
|
+
shift = Tod::Shift.new tod1, tod2
|
139
|
+
refute shift.include?(value)
|
83
140
|
end
|
84
141
|
|
85
142
|
# |------------------------|--V-----T1-----T2--------|------------------------|
|
86
|
-
|
87
|
-
tod1 = TimeOfDay.new 10
|
88
|
-
tod2 = TimeOfDay.new 16
|
89
|
-
value = TimeOfDay.new 8
|
90
|
-
shift = Shift.new tod1, tod2
|
91
|
-
|
143
|
+
it "is false when value is before first ToD" do
|
144
|
+
tod1 = Tod::TimeOfDay.new 10
|
145
|
+
tod2 = Tod::TimeOfDay.new 16
|
146
|
+
value = Tod::TimeOfDay.new 8
|
147
|
+
shift = Tod::Shift.new tod1, tod2
|
148
|
+
refute shift.include?(value)
|
149
|
+
end
|
150
|
+
|
151
|
+
# |------------------------|--------T1-----T2V-------|------------------------|
|
152
|
+
it "is false when value is equal to second ToD and Shift is ending exclusive" do
|
153
|
+
tod1 = Tod::TimeOfDay.new 10
|
154
|
+
tod2 = Tod::TimeOfDay.new 16
|
155
|
+
value = Tod::TimeOfDay.new 16
|
156
|
+
shift = Tod::Shift.new tod1, tod2, true
|
157
|
+
refute shift.include?(value)
|
158
|
+
end
|
159
|
+
|
160
|
+
# |------------------------|--------T1-----T2V-------|------------------------|
|
161
|
+
it "is true when value is equal to second ToD and Shift is ending inclusive" do
|
162
|
+
tod1 = Tod::TimeOfDay.new 10
|
163
|
+
tod2 = Tod::TimeOfDay.new 16
|
164
|
+
value = Tod::TimeOfDay.new 16
|
165
|
+
shift = Tod::Shift.new tod1, tod2, false
|
166
|
+
assert shift.include?(value)
|
92
167
|
end
|
93
168
|
end
|
94
169
|
end
|