tod 1.5.0 → 2.0.0
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.
- 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
|