tod 2.1.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +1 -8
- data/CHANGELOG.md +22 -0
- data/Gemfile.lock +33 -35
- data/README.markdown +54 -9
- data/lib/tod/conversions.rb +2 -2
- data/lib/tod/railtie.rb +12 -0
- data/lib/tod/shift.rb +46 -15
- data/lib/tod/time_of_day.rb +57 -19
- data/lib/tod/time_of_day_type.rb +18 -0
- data/lib/tod/version.rb +1 -1
- data/lib/tod.rb +2 -0
- data/test/test_helper.rb +0 -1
- data/test/tod/conversion_test.rb +22 -1
- data/test/tod/date_test.rb +1 -1
- data/test/tod/shift_test.rb +60 -1
- data/test/tod/time_of_day_attribute_test.rb +74 -0
- data/test/tod/time_of_day_test.rb +87 -12
- data/test/tod/time_of_day_time_zone_with_active_support_test.rb +1 -1
- data/test/tod/time_test.rb +1 -1
- data/tod.gemspec +2 -3
- metadata +13 -31
- data/gemfiles/3.2.gemfile +0 -5
- data/gemfiles/4.0.gemfile +0 -5
- data/gemfiles/4.1.gemfile +0 -5
- data/gemfiles/4.2.gemfile +0 -5
- data/lib/tod/arel_extensions.rb +0 -25
- data/test/tod/time_of_day_serializable_attribute_test.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fd0d2d6c4e128195e0162e4516a89be2ceb08d42787e114e9a03a094e2d24f35
|
4
|
+
data.tar.gz: 1a879241486d84fb99744a23688e48b3d9cd1da0d42019d221ab332c145aaea6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df47cc6c284da3c00d8faa6b6fa064cd2d0e69fd696e2ef3be7e4a8a88823d82713de5e70407aea76d71f12dded69e8fb3f1fad45dfd2ccda2f223c48f76d7b1
|
7
|
+
data.tar.gz: a9e9cd0823b2870e8ec4d2dd687b3ec963132a5c795a50d4bb16fbcc0f7117212bc188885f951acdf61806c2e6bb1fc6caf3937d91747857e9e184682b4157ed
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# 3.1.0 (December 20, 2021)
|
2
|
+
|
3
|
+
* Allow / ignore parsing milliseconds (Eli Fatsi)
|
4
|
+
* Improve TimeOfDate#inspect and Shift#inspect (zverok)
|
5
|
+
* Fix Shift#contains? with exclusive ending (nazamoresco)
|
6
|
+
|
7
|
+
# 3.0.0 (March 6, 2021)
|
8
|
+
|
9
|
+
* Support and require Rails 6
|
10
|
+
|
11
|
+
# 2.2.0 (October 10, 2018)
|
12
|
+
|
13
|
+
* Add string formatting compatible with Rails (Tate Johnson)
|
14
|
+
* Add ability to use ActiveRecord's attribute API (Brent Wheeldon)
|
15
|
+
* Add method for use in Rails database quoting (Ben Jackson)
|
16
|
+
|
17
|
+
# 2.1.1 (April 14, 2017)
|
18
|
+
|
19
|
+
* Fix serialize Ruby Time to Tod::TimeOfDay (Ryan Dick)
|
20
|
+
* Fix TimeOfDay.from_second_of_day when passed float (Jack Christensen)
|
21
|
+
* Fix Rails 5 multi-param assignment (Miklos Fazekas)
|
22
|
+
|
1
23
|
# 2.1.0 (May 9, 2016)
|
2
24
|
|
3
25
|
* Fix date extensions requiring date (ambirdsall)
|
data/Gemfile.lock
CHANGED
@@ -1,54 +1,52 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tod (
|
4
|
+
tod (3.1.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
activemodel (
|
10
|
-
activesupport (=
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
rake (
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
thread_safe (~> 0.1)
|
9
|
+
activemodel (6.1.3)
|
10
|
+
activesupport (= 6.1.3)
|
11
|
+
activerecord (6.1.3)
|
12
|
+
activemodel (= 6.1.3)
|
13
|
+
activesupport (= 6.1.3)
|
14
|
+
activesupport (6.1.3)
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
16
|
+
i18n (>= 1.6, < 2)
|
17
|
+
minitest (>= 5.1)
|
18
|
+
tzinfo (~> 2.0)
|
19
|
+
zeitwerk (~> 2.3)
|
20
|
+
byebug (11.1.3)
|
21
|
+
coderay (1.1.3)
|
22
|
+
concurrent-ruby (1.1.8)
|
23
|
+
i18n (1.8.9)
|
24
|
+
concurrent-ruby (~> 1.0)
|
25
|
+
method_source (1.0.0)
|
26
|
+
minitest (5.14.4)
|
27
|
+
pry (0.13.1)
|
28
|
+
coderay (~> 1.1)
|
29
|
+
method_source (~> 1.0)
|
30
|
+
pry-byebug (3.9.0)
|
31
|
+
byebug (~> 11.0)
|
32
|
+
pry (~> 0.13.0)
|
33
|
+
rake (13.0.3)
|
34
|
+
sqlite3 (1.4.2)
|
35
|
+
tzinfo (2.0.4)
|
36
|
+
concurrent-ruby (~> 1.0)
|
37
|
+
zeitwerk (2.4.2)
|
39
38
|
|
40
39
|
PLATFORMS
|
41
40
|
ruby
|
42
41
|
|
43
42
|
DEPENDENCIES
|
44
|
-
activerecord (>=
|
45
|
-
arel
|
43
|
+
activerecord (>= 6.0.0)
|
46
44
|
minitest
|
47
|
-
pry
|
45
|
+
pry-byebug
|
48
46
|
rake
|
49
47
|
sqlite3
|
50
48
|
tod!
|
51
49
|
tzinfo
|
52
50
|
|
53
51
|
BUNDLED WITH
|
54
|
-
|
52
|
+
2.2.15
|
data/README.markdown
CHANGED
@@ -54,6 +54,12 @@ parsable.
|
|
54
54
|
Tod::TimeOfDay.try_parse "3:30pm" # => 15:30:00
|
55
55
|
Tod::TimeOfDay.try_parse "foo" # => nil
|
56
56
|
|
57
|
+
You can also give a block to parse to handle special input with your own logic.
|
58
|
+
|
59
|
+
Tod::TimeOfDay.parse "25" do |time_string|
|
60
|
+
Tod::TimeOfDay.new(time_string.to_i % 24)
|
61
|
+
end # => 01:00:00
|
62
|
+
|
57
63
|
Values can be tested with Tod::TimeOfDay.parsable? to see if they can be parsed.
|
58
64
|
|
59
65
|
Tod::TimeOfDay.parsable? "3:30pm" # => true
|
@@ -62,7 +68,7 @@ Values can be tested with Tod::TimeOfDay.parsable? to see if they can be parsed.
|
|
62
68
|
Adding or subtracting time
|
63
69
|
-----------------------------
|
64
70
|
|
65
|
-
Seconds can be added to or subtracted Tod::TimeOfDay objects. Time correctly wraps
|
71
|
+
Seconds can be added to or subtracted from Tod::TimeOfDay objects. Time correctly wraps
|
66
72
|
around midnight.
|
67
73
|
|
68
74
|
Tod::TimeOfDay.new(8) + 3600 # => 09:00:00
|
@@ -89,10 +95,33 @@ Format strings are passed to Time#strftime.
|
|
89
95
|
Tod::TimeOfDay.new(17,15).strftime("%I:%M %p") # => "05:15 PM"
|
90
96
|
Tod::TimeOfDay.new(22,5,15).strftime("%I:%M:%S %p") # => "10:05:15 PM"
|
91
97
|
|
98
|
+
Or a Rails style `to_formatted_s` is aliased to `to_s`.
|
99
|
+
|
100
|
+
Tod::TimeOfDay.new(8,30).to_s(:short) # => "8:30 am"
|
101
|
+
|
102
|
+
Or [i18n](https://github.com/svenfuchs/i18n) in a Rails ERB view.
|
103
|
+
|
104
|
+
<%= l Tod::TimeOfDay.new(8, 30), format: :short %>
|
105
|
+
|
106
|
+
Add new formatters to `Tod::TimeOfDay::FORMATS`.
|
107
|
+
|
108
|
+
Tod::TimeOfDay::FORMATS[:seconds_only] = "%S"
|
109
|
+
Tod::TimeOfDay.new(8,30,57).to_s(:seconds_only) # => "57"
|
110
|
+
|
111
|
+
Rounding
|
112
|
+
----------
|
113
|
+
|
114
|
+
Round to the given nearest number of seconds.
|
115
|
+
|
116
|
+
Tod::TimeOfDay.new(8,15,31).round(5) # => "08:15:30"
|
117
|
+
Tod::TimeOfDay.new(8,15,34).round(60) # => "08:16:00"
|
118
|
+
Tod::TimeOfDay.new(8,02,29).round(300) # => "08:00:00"
|
119
|
+
|
92
120
|
Convenience methods for dates and times
|
93
121
|
---------------------------------------
|
94
122
|
|
95
|
-
Pass a date to Tod::TimeOfDay#on and it will return a time with that date and time
|
123
|
+
Pass a date to Tod::TimeOfDay#on and it will return a time with that date and time,
|
124
|
+
in the time zone of the ruby runtime (`Time.now.zone`).
|
96
125
|
|
97
126
|
tod = Tod::TimeOfDay.new 8, 30 # => 08:30:00
|
98
127
|
tod.on Date.today # => 2010-12-29 08:30:00 -0600
|
@@ -153,7 +182,7 @@ Include?
|
|
153
182
|
Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(9), true).include?(Tod::TimeOfDay.new(9)) # => false
|
154
183
|
|
155
184
|
|
156
|
-
|
185
|
+
Overlaps?
|
157
186
|
--------------------
|
158
187
|
|
159
188
|
breakfast = Tod::Shift.new(Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(11))
|
@@ -184,16 +213,32 @@ Contains?
|
|
184
213
|
Rails Time Zone Support
|
185
214
|
=======================
|
186
215
|
|
187
|
-
If Rails time zone support is loaded, Date#on and Tod::TimeOfDay#at will automatically use Time.zone.
|
216
|
+
If Rails time zone support is loaded, Date#on and Tod::TimeOfDay#at (when given a Date) will automatically use Time.zone.
|
217
|
+
|
218
|
+
When Tod::TimeOfDay#on is given a `Time` or `Time`-like object like `ActiveSupport::TimeWithZone`,
|
219
|
+
Tod will ignore the specified timezone and return the time on that date in UTC. In order to
|
220
|
+
produce an object with the correct time and time zone, pass in an
|
221
|
+
`ActiveSupport::TimeZone` object. Date#at has analogous behavior.
|
188
222
|
|
189
|
-
|
223
|
+
time = Time.now.in_time_zone("US/Eastern") # => Mon, 24 Sep 2018 05:07:23 EDT -04:00
|
224
|
+
tod.on time # => Mon, 24 Sep 2018 08:30:00 UTC +00:00
|
225
|
+
tod.on time, time.time_zone # => Mon, 24 Sep 2018 08:30:00 EDT -04:00
|
226
|
+
tod.on time, Time.find_zone!("US/Mountain") # => Mon, 24 Sep 2018 08:30:00 MDT -06:00
|
227
|
+
Date.tomorrow.at tod, Time.find_zone!("US/Mountain") # => Tue, 25 Sep 2018 08:30:00 MDT -06:00
|
228
|
+
|
229
|
+
ActiveRecord Attribute Support
|
190
230
|
=======================
|
191
|
-
Tod::TimeOfDay
|
231
|
+
Tod::TimeOfDay can be used as an ActiveRecord attribute to store Tod::TimeOfDay directly
|
192
232
|
in a column of the time type.
|
233
|
+
|
193
234
|
Example:
|
235
|
+
|
194
236
|
```ruby
|
237
|
+
ActiveModel::Type.register(:time_only, Tod::TimeOfDayType)
|
238
|
+
ActiveRecord::Type.register(:time_only, Tod::TimeOfDayType)
|
239
|
+
|
195
240
|
class Order < ActiveRecord::Base
|
196
|
-
|
241
|
+
attribute :time, :time_only
|
197
242
|
end
|
198
243
|
order = Order.create(time: Tod::TimeOfDay.new(9,30))
|
199
244
|
order.time # => 09:30:00
|
@@ -241,10 +286,10 @@ Compatibility
|
|
241
286
|
|
242
287
|
[![Build Status](https://travis-ci.org/jackc/tod.png)](https://travis-ci.org/jackc/tod)
|
243
288
|
|
244
|
-
Tod is
|
289
|
+
Tod is tested against Ruby 2.6.x and Rails 6.x.
|
245
290
|
|
246
291
|
|
247
292
|
License
|
248
293
|
=======
|
249
294
|
|
250
|
-
Copyright (c) 2010-
|
295
|
+
Copyright (c) 2010-2021 Jack Christensen, released under the MIT license
|
data/lib/tod/conversions.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Tod
|
2
|
-
def TimeOfDay(obj_or_string)
|
2
|
+
def TimeOfDay(obj_or_string, &block)
|
3
3
|
if obj_or_string.is_a?(TimeOfDay)
|
4
4
|
obj_or_string
|
5
5
|
elsif obj_or_string.respond_to?(:to_time_of_day)
|
@@ -9,7 +9,7 @@ module Tod
|
|
9
9
|
elsif obj_or_string.is_a?(Date)
|
10
10
|
TimeOfDay.new 0
|
11
11
|
else
|
12
|
-
TimeOfDay.parse(obj_or_string)
|
12
|
+
TimeOfDay.parse(obj_or_string, &block)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
data/lib/tod/railtie.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "active_model/type"
|
2
|
+
require "active_record/type"
|
3
|
+
require "tod/time_of_day_type"
|
4
|
+
|
5
|
+
module Tod
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer "tod.register_active_model_type" do
|
8
|
+
ActiveModel::Type.register(:time_only, Tod::TimeOfDayType)
|
9
|
+
ActiveRecord::Type.register(:time_only, Tod::TimeOfDayType)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/tod/shift.rb
CHANGED
@@ -24,6 +24,10 @@ module Tod
|
|
24
24
|
freeze # Shift instances are value objects
|
25
25
|
end
|
26
26
|
|
27
|
+
def inspect
|
28
|
+
"#<#{self.class} #{beginning}#{exclude_end? ? '...' : '..'}#{ending}>"
|
29
|
+
end
|
30
|
+
|
27
31
|
# Returns true if the time of day is inside the shift, false otherwise.
|
28
32
|
def include?(tod)
|
29
33
|
second = tod.to_i
|
@@ -33,24 +37,44 @@ module Tod
|
|
33
37
|
|
34
38
|
# Returns true if ranges overlap, false otherwise.
|
35
39
|
def overlaps?(other)
|
36
|
-
|
37
|
-
|
38
|
-
#
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
40
|
+
a, b = [self, other].map(&:range)
|
41
|
+
#
|
42
|
+
# Although a Shift which passes through midnight is stored
|
43
|
+
# internally as lasting more than TimeOfDay::NUM_SECONDS_IN_DAY
|
44
|
+
# seconds from midnight, that's not how it is meant to be
|
45
|
+
# handled. Rather, it consists of two chunks:
|
46
|
+
#
|
47
|
+
# range.first => Midnight
|
48
|
+
# Midnight => range.last
|
49
|
+
#
|
50
|
+
# The second one is *before* the first. None of it is more than
|
51
|
+
# TimeOfDay::NUM_SECONDS_IN_DAY after midnight. We thus need to shift
|
52
|
+
# each of our ranges to cover all overlapping possibilities.
|
53
|
+
#
|
54
|
+
one_day = TimeOfDay::NUM_SECONDS_IN_DAY
|
55
|
+
ashifted =
|
56
|
+
Range.new(a.first + one_day, a.last + one_day, a.exclude_end?)
|
57
|
+
bshifted =
|
58
|
+
Range.new(b.first + one_day, b.last + one_day, b.exclude_end?)
|
59
|
+
#
|
60
|
+
# For exclusive ranges we need:
|
61
|
+
#
|
62
|
+
# a.ending > b.beginning && b.ending > a.beginning
|
63
|
+
#
|
64
|
+
# and for inclusive we need:
|
65
|
+
#
|
66
|
+
# a.ending >= b.beginning && b.ending >= a.beginning
|
67
|
+
#
|
68
|
+
aop = a.exclude_end? ? :> : :>=
|
69
|
+
bop = b.exclude_end? ? :> : :>=
|
70
|
+
#
|
71
|
+
(a.last.send(aop, b.first) && b.last.send(bop, a.first)) ||
|
72
|
+
(ashifted.last.send(aop, b.first) && b.last.send(bop, ashifted.first)) ||
|
73
|
+
(a.last.send(aop, bshifted.first) && bshifted.last.send(bop, a.first))
|
50
74
|
end
|
51
75
|
|
52
76
|
def contains?(shift)
|
53
|
-
self.include?(shift.beginning) && self.include?(shift.
|
77
|
+
self.include?(shift.beginning) && self.include?(shift.inclusive_ending)
|
54
78
|
end
|
55
79
|
|
56
80
|
# Return shift duration in seconds.
|
@@ -79,5 +103,12 @@ module Tod
|
|
79
103
|
def slide(seconds)
|
80
104
|
self.class.new(beginning + seconds, ending + seconds, exclude_end?)
|
81
105
|
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
# If exclusive ending returns equivalent ending but inclusive
|
110
|
+
def inclusive_ending
|
111
|
+
self.exclude_end? ? ending - 1 : ending
|
112
|
+
end
|
82
113
|
end
|
83
114
|
end
|
data/lib/tod/time_of_day.rb
CHANGED
@@ -9,11 +9,12 @@ module Tod
|
|
9
9
|
|
10
10
|
PARSE_24H_REGEX = /
|
11
11
|
\A
|
12
|
-
([01]?\d|2[0-
|
12
|
+
([01]?\d|2[0-4])
|
13
13
|
:?
|
14
14
|
([0-5]\d)?
|
15
15
|
:?
|
16
16
|
([0-5]\d)?
|
17
|
+
(?:\.\d{3})?
|
17
18
|
\z
|
18
19
|
/x
|
19
20
|
|
@@ -24,6 +25,7 @@ module Tod
|
|
24
25
|
([0-5]\d)?
|
25
26
|
:?
|
26
27
|
([0-5]\d)?
|
28
|
+
(?:\.\d{3})?
|
27
29
|
\s*
|
28
30
|
([ap])
|
29
31
|
\.?
|
@@ -34,20 +36,29 @@ module Tod
|
|
34
36
|
/x
|
35
37
|
|
36
38
|
WORDS = {
|
37
|
-
"noon" => "12pm",
|
38
|
-
"midnight" => "12am"
|
39
|
+
"noon" => "12pm".freeze,
|
40
|
+
"midnight" => "12am".freeze
|
39
41
|
}
|
40
42
|
|
41
43
|
NUM_SECONDS_IN_DAY = 86400
|
42
44
|
NUM_SECONDS_IN_HOUR = 3600
|
43
45
|
NUM_SECONDS_IN_MINUTE = 60
|
44
46
|
|
47
|
+
FORMATS = {
|
48
|
+
short: "%-l:%M %P".freeze,
|
49
|
+
medium: "%-l:%M:%S %P".freeze,
|
50
|
+
time: "%H:%M".freeze
|
51
|
+
}
|
52
|
+
|
45
53
|
def initialize(h, m=0, s=0)
|
46
54
|
@hour = Integer(h)
|
47
55
|
@minute = Integer(m)
|
48
56
|
@second = Integer(s)
|
49
57
|
|
50
|
-
raise ArgumentError, "hour must be between 0 and
|
58
|
+
raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
|
59
|
+
if @hour == 24 && (@minute != 0 || @second != 0)
|
60
|
+
raise ArgumentError, "hour can only be 24 when minute and second are 0"
|
61
|
+
end
|
51
62
|
raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
|
52
63
|
raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)
|
53
64
|
|
@@ -61,13 +72,48 @@ module Tod
|
|
61
72
|
@second_of_day <=> other.second_of_day
|
62
73
|
end
|
63
74
|
|
75
|
+
# Rounding to the given nearest number of seconds
|
76
|
+
def round(round_sec = 1)
|
77
|
+
down = self - (self.to_i % round_sec)
|
78
|
+
up = down + round_sec
|
79
|
+
|
80
|
+
difference_down = self - down
|
81
|
+
difference_up = up - self
|
82
|
+
|
83
|
+
if (difference_down < difference_up)
|
84
|
+
return down
|
85
|
+
else
|
86
|
+
return up
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
64
90
|
# Formats identically to Time#strftime
|
65
91
|
def strftime(format_string)
|
92
|
+
# Special case 2400 because strftime will load TimeOfDay into Time which
|
93
|
+
# will convert 24 to 0
|
94
|
+
format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
|
66
95
|
Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
|
67
96
|
end
|
68
97
|
|
69
|
-
def
|
70
|
-
|
98
|
+
def to_formatted_s(format = :default)
|
99
|
+
if formatter = FORMATS[format]
|
100
|
+
if formatter.respond_to?(:call)
|
101
|
+
formatter.call(self).to_s
|
102
|
+
else
|
103
|
+
strftime(formatter)
|
104
|
+
end
|
105
|
+
else
|
106
|
+
strftime "%H:%M:%S"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
alias_method :to_s, :to_formatted_s
|
110
|
+
|
111
|
+
def value_for_database
|
112
|
+
to_s
|
113
|
+
end
|
114
|
+
|
115
|
+
def inspect
|
116
|
+
"#<#{self.class} #{self}>"
|
71
117
|
end
|
72
118
|
|
73
119
|
# Return a new TimeOfDay num_seconds greater than self. It will wrap around
|
@@ -96,6 +142,8 @@ module Tod
|
|
96
142
|
#
|
97
143
|
# TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1) # => true
|
98
144
|
def self.from_second_of_day(second_of_day)
|
145
|
+
second_of_day = Integer(second_of_day)
|
146
|
+
return new 24 if second_of_day == NUM_SECONDS_IN_DAY
|
99
147
|
remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
|
100
148
|
hour = remaining_seconds / NUM_SECONDS_IN_HOUR
|
101
149
|
remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
|
@@ -122,8 +170,10 @@ module Tod
|
|
122
170
|
# TimeOfDay.parse "3:25:58" # => 03:25:58
|
123
171
|
# TimeOfDay.parse "515p" # => 17:15:00
|
124
172
|
# TimeOfDay.parse "151253" # => 15:12:53
|
173
|
+
# You can give a block, that is called with the input if the string is not parsable.
|
174
|
+
# If no block is given an ArgumentError is raised if try_parse returns nil.
|
125
175
|
def self.parse(tod_string)
|
126
|
-
try_parse(tod_string) || (raise
|
176
|
+
try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
|
127
177
|
end
|
128
178
|
|
129
179
|
# Same as parse(), but return nil if not parsable (instead of raising an error)
|
@@ -160,17 +210,5 @@ module Tod
|
|
160
210
|
def self.time_zone
|
161
211
|
(Time.respond_to?(:zone) && Time.zone) || Time
|
162
212
|
end
|
163
|
-
|
164
|
-
def self.dump(time_of_day)
|
165
|
-
if time_of_day.to_s == ''
|
166
|
-
nil
|
167
|
-
else
|
168
|
-
time_of_day.to_s
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
def self.load(time)
|
173
|
-
::Tod::TimeOfDay(time) if time && !time.to_s.empty?
|
174
|
-
end
|
175
213
|
end
|
176
214
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Tod
|
2
|
+
class TimeOfDayType < ActiveModel::Type::Value
|
3
|
+
def cast(value)
|
4
|
+
if value.is_a? Hash
|
5
|
+
# rails multiparam attribute
|
6
|
+
# get hour, minute and second and construct new TimeOfDay object
|
7
|
+
::Tod::TimeOfDay.new(value[4], value[5], value[6])
|
8
|
+
else
|
9
|
+
# return nil, if input is not parsable
|
10
|
+
Tod::TimeOfDay(value){}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def serialize(value)
|
15
|
+
value.to_s if value.present?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/tod/version.rb
CHANGED
data/lib/tod.rb
CHANGED
data/test/test_helper.rb
CHANGED
data/test/tod/conversion_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative '../test_helper'
|
2
2
|
|
3
3
|
describe "TimeOfDay()" do
|
4
4
|
it "handles Tod::TimeOfDay" do
|
@@ -81,4 +81,25 @@ describe "TimeOfDay()" do
|
|
81
81
|
|
82
82
|
assert_equal(tod, Tod::TimeOfDay.new(0, 00, 00))
|
83
83
|
end
|
84
|
+
|
85
|
+
it "parses 24:00:00" do
|
86
|
+
t = "24:00:00"
|
87
|
+
tod = Tod::TimeOfDay(t)
|
88
|
+
|
89
|
+
assert_equal(tod, Tod::TimeOfDay.new(24, 00, 00))
|
90
|
+
end
|
91
|
+
|
92
|
+
it "parses 24:00:00.000" do
|
93
|
+
t = "24:00:00.000"
|
94
|
+
tod = Tod::TimeOfDay(t)
|
95
|
+
|
96
|
+
assert_equal(tod, Tod::TimeOfDay.new(24, 00, 00))
|
97
|
+
end
|
98
|
+
|
99
|
+
it "parses 04:00:00.000 pm" do
|
100
|
+
t = "04:00:00.000 pm"
|
101
|
+
tod = Tod::TimeOfDay(t)
|
102
|
+
|
103
|
+
assert_equal(tod, Tod::TimeOfDay.new(16, 00, 00))
|
104
|
+
end
|
84
105
|
end
|
data/test/tod/date_test.rb
CHANGED
data/test/tod/shift_test.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative '../test_helper'
|
2
2
|
|
3
3
|
describe "Shift" do
|
4
4
|
describe "#initialize" do
|
@@ -11,6 +11,16 @@ describe "Shift" do
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
describe "inspect" do
|
15
|
+
it "provides friendly description" do
|
16
|
+
shift = Tod::Shift.new Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(10), false
|
17
|
+
assert_equal "#<Tod::Shift 08:00:00..10:00:00>", shift.inspect
|
18
|
+
|
19
|
+
shift = Tod::Shift.new Tod::TimeOfDay.new(8), Tod::TimeOfDay.new(10), true
|
20
|
+
assert_equal "#<Tod::Shift 08:00:00...10:00:00>", shift.inspect
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
14
24
|
describe "#duration" do
|
15
25
|
it "returns correct duration when first time is lower than the second one" do
|
16
26
|
duration_expected = 4 * 60 * 60 + 30 * 60 + 30 # 4 hours, 30 min and 30 sec later
|
@@ -99,6 +109,49 @@ describe "Shift" do
|
|
99
109
|
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12), true)
|
100
110
|
refute shift1.overlaps?(shift2)
|
101
111
|
end
|
112
|
+
|
113
|
+
it "copes correctly with mixed shifts" do
|
114
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5))
|
115
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12), true)
|
116
|
+
assert shift1.overlaps?(shift2)
|
117
|
+
assert shift2.overlaps?(shift1)
|
118
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5), true)
|
119
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12))
|
120
|
+
refute shift1.overlaps?(shift2)
|
121
|
+
refute shift2.overlaps?(shift1)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "copes correctly with zero length inclusive end shifts" do
|
125
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17))
|
126
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(10))
|
127
|
+
shift3 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(9))
|
128
|
+
shift4 = Tod::Shift.new(Tod::TimeOfDay.new(17), Tod::TimeOfDay.new(17))
|
129
|
+
assert shift1.overlaps?(shift2)
|
130
|
+
assert shift2.overlaps?(shift1)
|
131
|
+
|
132
|
+
assert shift1.overlaps?(shift3)
|
133
|
+
assert shift3.overlaps?(shift1)
|
134
|
+
|
135
|
+
assert shift1.overlaps?(shift4)
|
136
|
+
assert shift4.overlaps?(shift1)
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
it "copes correctly with zero length exclusive end shifts" do
|
141
|
+
shift1 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17), true)
|
142
|
+
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(10), true)
|
143
|
+
shift3 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(9), true)
|
144
|
+
shift4 = Tod::Shift.new(Tod::TimeOfDay.new(17), Tod::TimeOfDay.new(17), true)
|
145
|
+
assert shift1.overlaps?(shift2)
|
146
|
+
assert shift2.overlaps?(shift1)
|
147
|
+
|
148
|
+
refute shift1.overlaps?(shift3)
|
149
|
+
refute shift3.overlaps?(shift1)
|
150
|
+
|
151
|
+
refute shift1.overlaps?(shift4)
|
152
|
+
refute shift4.overlaps?(shift1)
|
153
|
+
|
154
|
+
end
|
102
155
|
end
|
103
156
|
|
104
157
|
describe "contains?" do
|
@@ -119,6 +172,12 @@ describe "Shift" do
|
|
119
172
|
shift2 = Tod::Shift.new(Tod::TimeOfDay.new(18), Tod::TimeOfDay.new(19))
|
120
173
|
refute shift1.contains?(shift2)
|
121
174
|
end
|
175
|
+
|
176
|
+
it "is true when beginning is included and exclusive endings match" do
|
177
|
+
inside = Tod::Shift.new(Tod::TimeOfDay.new(13), Tod::TimeOfDay.new(17), true)
|
178
|
+
outside = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(17), true)
|
179
|
+
assert outside.contains?(inside)
|
180
|
+
end
|
122
181
|
end
|
123
182
|
|
124
183
|
describe "#include?" do
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','support/active_record'))
|
3
|
+
|
4
|
+
require 'tod/time_of_day_type'
|
5
|
+
|
6
|
+
ActiveModel::Type.register(:time_only, Tod::TimeOfDayType)
|
7
|
+
ActiveRecord::Type.register(:time_only, Tod::TimeOfDayType)
|
8
|
+
|
9
|
+
class Order < ActiveRecord::Base
|
10
|
+
attribute :time, :time_only
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "TimeOfDay with ActiveRecord Attribute" do
|
14
|
+
it "sets time of day" do
|
15
|
+
Order.create!(time: Tod::TimeOfDay.new(9, 30))
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sets nil as value" do
|
19
|
+
Order.create!(time: nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "works with multiparam time arguments" do
|
23
|
+
order = Order.create!({"time(4i)" => "8", "time(5i)" => "6", "time(6i)" => "5"})
|
24
|
+
assert_equal Tod::TimeOfDay.new(8,6,5), order.time
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not raise Exception on access of unparsable values" do
|
28
|
+
order = Order.new(time: 'unparsable')
|
29
|
+
order.time
|
30
|
+
assert order.valid?
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should dump unparsable values to nil" do
|
34
|
+
assert_nil Order.new(time: '').time
|
35
|
+
assert_nil Order.new(time: 'unparsable').time
|
36
|
+
assert_nil Order.new(time: nil).time
|
37
|
+
end
|
38
|
+
|
39
|
+
it "loads set Tod::TimeOfDay" do
|
40
|
+
time_of_day = Tod::TimeOfDay.new(9, 30)
|
41
|
+
order = Order.create!(time: time_of_day)
|
42
|
+
order.reload
|
43
|
+
assert_equal order.time, time_of_day
|
44
|
+
end
|
45
|
+
|
46
|
+
it "loads set Time" do
|
47
|
+
time_of_day = Time.new(2015, 10, 21, 16, 29, 0, "-07:00")
|
48
|
+
order = Order.create!(time: time_of_day)
|
49
|
+
order.reload
|
50
|
+
assert_equal order.time, Tod::TimeOfDay.new(16, 29)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "returns nil if time is not set" do
|
54
|
+
order = Order.create!(time: nil)
|
55
|
+
order.reload
|
56
|
+
assert_nil order.time
|
57
|
+
end
|
58
|
+
|
59
|
+
it "dump 24:00:00 and get it back" do
|
60
|
+
time_of_day = Tod::TimeOfDay.new(24, 0, 0)
|
61
|
+
order = Order.create!(time: time_of_day)
|
62
|
+
order.reload
|
63
|
+
assert_equal Tod::TimeOfDay.new(24), order.time
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "Order.where" do
|
67
|
+
it "handles TimeOfDay as a parameter" do
|
68
|
+
tod = Tod::TimeOfDay.new(11, 11)
|
69
|
+
expected = Order.create!(time: tod)
|
70
|
+
actual = Order.where(time: tod).first
|
71
|
+
assert_equal expected, actual
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
|
1
|
+
require_relative '../test_helper'
|
2
2
|
|
3
3
|
describe "TimeOfDay" do
|
4
4
|
describe "#initialize" do
|
5
5
|
it "blocks invalid hours" do
|
6
|
-
assert_raises(ArgumentError) { Tod::TimeOfDay.new
|
7
|
-
assert_raises(ArgumentError) { Tod::TimeOfDay.new
|
6
|
+
assert_raises(ArgumentError) { Tod::TimeOfDay.new(-1) }
|
7
|
+
assert_raises(ArgumentError) { Tod::TimeOfDay.new 25 }
|
8
8
|
end
|
9
9
|
|
10
10
|
it "blocks invalid minutes" do
|
@@ -31,6 +31,10 @@ describe "TimeOfDay" do
|
|
31
31
|
assert_equal 86399, Tod::TimeOfDay.new(23,59,59).second_of_day
|
32
32
|
end
|
33
33
|
|
34
|
+
it "is 86400 at beginning of next day" do
|
35
|
+
assert_equal 86400, Tod::TimeOfDay.new(24,0,0).second_of_day
|
36
|
+
end
|
37
|
+
|
34
38
|
it "have alias to_i" do
|
35
39
|
tod = Tod::TimeOfDay.new(0,0,0)
|
36
40
|
assert_equal tod.method(:second_of_day), tod.method(:to_i)
|
@@ -50,7 +54,7 @@ describe "TimeOfDay" do
|
|
50
54
|
def self.should_not_parse(parse_string)
|
51
55
|
it "does not parse '#{parse_string}'" do
|
52
56
|
assert_equal false, Tod::TimeOfDay.parsable?(parse_string)
|
53
|
-
|
57
|
+
assert_nil Tod::TimeOfDay.try_parse(parse_string)
|
54
58
|
assert_raises(ArgumentError) { Tod::TimeOfDay.parse(parse_string) }
|
55
59
|
end
|
56
60
|
end
|
@@ -84,9 +88,12 @@ describe "TimeOfDay" do
|
|
84
88
|
should_parse "12a", 0, 0, 0
|
85
89
|
should_parse "12p", 12, 0, 0
|
86
90
|
|
91
|
+
should_parse "24:00:00", 24, 0, 0
|
92
|
+
should_parse "24:00", 24, 0, 0
|
93
|
+
should_parse "24", 24, 0, 0
|
94
|
+
should_parse "2400", 24, 0, 0
|
95
|
+
|
87
96
|
should_not_parse "-1:30"
|
88
|
-
should_not_parse "24:00:00"
|
89
|
-
should_not_parse "24"
|
90
97
|
should_not_parse "00:60"
|
91
98
|
should_not_parse "00:00:60"
|
92
99
|
should_not_parse "13a"
|
@@ -98,12 +105,17 @@ describe "TimeOfDay" do
|
|
98
105
|
|
99
106
|
it "does not parse 'nil'" do
|
100
107
|
assert_equal false, Tod::TimeOfDay.parsable?(nil)
|
101
|
-
|
108
|
+
assert_nil Tod::TimeOfDay.try_parse(nil)
|
102
109
|
assert_raises(ArgumentError) { Tod::TimeOfDay.parse(nil) }
|
103
110
|
end
|
104
111
|
|
112
|
+
it "executes block on parsing failure and return result instead" do
|
113
|
+
assert_equal Tod::TimeOfDay.new(1), Tod::TimeOfDay.parse('25:00:00') { Tod::TimeOfDay.new(1) }
|
114
|
+
assert_equal Tod::TimeOfDay.new(1), Tod::TimeOfDay.parse('25:00:00') { |time_string| Tod::TimeOfDay.parse(time_string.sub('25', '01')) }
|
115
|
+
end
|
116
|
+
|
105
117
|
it "provides spaceship operator" do
|
106
|
-
assert_equal
|
118
|
+
assert_equal(-1, Tod::TimeOfDay.new(8,0,0) <=> Tod::TimeOfDay.new(9,0,0))
|
107
119
|
assert_equal 0, Tod::TimeOfDay.new(9,0,0) <=> Tod::TimeOfDay.new(9,0,0)
|
108
120
|
assert_equal 1, Tod::TimeOfDay.new(10,0,0) <=> Tod::TimeOfDay.new(9,0,0)
|
109
121
|
end
|
@@ -112,6 +124,20 @@ describe "TimeOfDay" do
|
|
112
124
|
assert_equal Tod::TimeOfDay.new(8,0,0), Tod::TimeOfDay.new(8,0,0)
|
113
125
|
end
|
114
126
|
|
127
|
+
describe "round_nearest" do
|
128
|
+
it "rounds to the given nearest number of seconds" do
|
129
|
+
assert_equal Tod::TimeOfDay.new(8,15,30), Tod::TimeOfDay.new(8,15,31).round(5)
|
130
|
+
assert_equal Tod::TimeOfDay.new(8,15,35), Tod::TimeOfDay.new(8,15,33).round(5)
|
131
|
+
assert_equal Tod::TimeOfDay.new(8,16,0), Tod::TimeOfDay.new(8,15,34).round(60)
|
132
|
+
assert_equal Tod::TimeOfDay.new(8,15,0), Tod::TimeOfDay.new(8,15,15).round(60)
|
133
|
+
assert_equal Tod::TimeOfDay.new(8,15,0), Tod::TimeOfDay.new(8,17,15).round(300)
|
134
|
+
assert_equal Tod::TimeOfDay.new(8,20,0), Tod::TimeOfDay.new(8,18,15).round(300)
|
135
|
+
assert_equal Tod::TimeOfDay.new(8,20,0), Tod::TimeOfDay.new(8,20,00).round(300)
|
136
|
+
assert_equal Tod::TimeOfDay.new(9,0,0), Tod::TimeOfDay.new(8,58,00).round(300)
|
137
|
+
assert_equal Tod::TimeOfDay.new(8,0,0), Tod::TimeOfDay.new(8,02,29).round(300)
|
138
|
+
assert_equal Tod::TimeOfDay.new(24,0,0), Tod::TimeOfDay.new(23,58,29).round(300)
|
139
|
+
end
|
140
|
+
end
|
115
141
|
|
116
142
|
describe "strftime" do
|
117
143
|
it "accepts standard strftime format codes" do
|
@@ -119,10 +145,55 @@ describe "TimeOfDay" do
|
|
119
145
|
end
|
120
146
|
end
|
121
147
|
|
148
|
+
describe "to_formatted_s" do
|
149
|
+
it "has a default format" do
|
150
|
+
assert_equal "08:15:30", Tod::TimeOfDay.new(8,15,30).to_formatted_s
|
151
|
+
assert_equal "22:10:45", Tod::TimeOfDay.new(22,10,45).to_formatted_s
|
152
|
+
end
|
153
|
+
|
154
|
+
it "has a short format" do
|
155
|
+
assert_equal "8:15 am", Tod::TimeOfDay.new(8,15,30).to_formatted_s(:short)
|
156
|
+
assert_equal "10:10 pm", Tod::TimeOfDay.new(22,10,45).to_formatted_s(:short)
|
157
|
+
end
|
158
|
+
|
159
|
+
it "has a medium format" do
|
160
|
+
assert_equal "8:15:30 am", Tod::TimeOfDay.new(8,15,30).to_formatted_s(:medium)
|
161
|
+
assert_equal "10:10:45 pm", Tod::TimeOfDay.new(22,10,45).to_formatted_s(:medium)
|
162
|
+
end
|
163
|
+
|
164
|
+
it "has an ActiveSupport compatible time format" do
|
165
|
+
assert_equal "08:15", Tod::TimeOfDay.new(8,15,30).to_formatted_s(:time)
|
166
|
+
assert_equal "22:10", Tod::TimeOfDay.new(22,10,45).to_formatted_s(:time)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "evaluates custom lambda lambda formats" do
|
170
|
+
begin
|
171
|
+
Tod::TimeOfDay::FORMATS[:lambda] = -> (t) { t.strftime("%H%M 😎") }
|
172
|
+
assert_equal "1337 😎", Tod::TimeOfDay.new(13,37).to_formatted_s(:lambda)
|
173
|
+
ensure
|
174
|
+
Tod::TimeOfDay::FORMATS.delete(:lambda)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "value_for_database" do
|
180
|
+
it "returns a formatted value for database query serialization" do
|
181
|
+
t = Tod::TimeOfDay.new(12,15,05)
|
182
|
+
assert_equal "12:15:05", t.value_for_database
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
122
186
|
describe "to_s" do
|
123
|
-
it "
|
124
|
-
|
125
|
-
assert_equal
|
187
|
+
it "is aliased to to_formatted_s" do
|
188
|
+
t = Tod::TimeOfDay.new(8,15,30)
|
189
|
+
assert_equal t.to_formatted_s, t.to_s
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "inspect" do
|
194
|
+
it "is friendly representation" do
|
195
|
+
t = Tod::TimeOfDay.new(12,15,05)
|
196
|
+
assert_equal "#<Tod::TimeOfDay 12:15:05>", t.inspect
|
126
197
|
end
|
127
198
|
end
|
128
199
|
|
@@ -201,7 +272,7 @@ describe "TimeOfDay" do
|
|
201
272
|
end
|
202
273
|
|
203
274
|
it "handles positive numbers a day or more away" do
|
204
|
-
assert_equal Tod::TimeOfDay.new(
|
275
|
+
assert_equal Tod::TimeOfDay.new(24,0,0), Tod::TimeOfDay.from_second_of_day(86400)
|
205
276
|
assert_equal Tod::TimeOfDay.new(0,0,30), Tod::TimeOfDay.from_second_of_day(86430)
|
206
277
|
assert_equal Tod::TimeOfDay.new(0,1,30), Tod::TimeOfDay.from_second_of_day(86490)
|
207
278
|
assert_equal Tod::TimeOfDay.new(1,1,5), Tod::TimeOfDay.from_second_of_day(90065)
|
@@ -219,6 +290,10 @@ describe "TimeOfDay" do
|
|
219
290
|
it "has alias from_i" do
|
220
291
|
assert_equal Tod::TimeOfDay.method(:from_second_of_day), Tod::TimeOfDay.method(:from_i)
|
221
292
|
end
|
293
|
+
|
294
|
+
it "handles floats" do
|
295
|
+
assert_equal Tod::TimeOfDay.new(15,30,0), Tod::TimeOfDay.from_second_of_day(55800.0)
|
296
|
+
end
|
222
297
|
end
|
223
298
|
|
224
299
|
describe "on" do
|
data/test/tod/time_test.rb
CHANGED
data/tod.gemspec
CHANGED
@@ -16,10 +16,9 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.add_development_dependency "minitest"
|
17
17
|
s.add_development_dependency "tzinfo"
|
18
18
|
s.add_development_dependency "rake"
|
19
|
-
s.add_development_dependency "activerecord", ">=
|
19
|
+
s.add_development_dependency "activerecord", ">= 6.0.0"
|
20
20
|
s.add_development_dependency "sqlite3"
|
21
|
-
s.add_development_dependency "pry"
|
22
|
-
s.add_development_dependency "arel"
|
21
|
+
s.add_development_dependency "pry-byebug"
|
23
22
|
|
24
23
|
s.files = `git ls-files`.split("\n")
|
25
24
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jack Christensen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 6.0.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 6.0.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sqlite3
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -81,21 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: pry
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: arel
|
84
|
+
name: pry-byebug
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - ">="
|
@@ -124,26 +110,23 @@ files:
|
|
124
110
|
- MIT-LICENSE
|
125
111
|
- README.markdown
|
126
112
|
- Rakefile
|
127
|
-
- gemfiles/3.2.gemfile
|
128
|
-
- gemfiles/4.0.gemfile
|
129
|
-
- gemfiles/4.1.gemfile
|
130
|
-
- gemfiles/4.2.gemfile
|
131
113
|
- lib/tod.rb
|
132
|
-
- lib/tod/arel_extensions.rb
|
133
114
|
- lib/tod/conversions.rb
|
134
115
|
- lib/tod/core_extensions.rb
|
135
116
|
- lib/tod/date_extensions.rb
|
136
117
|
- lib/tod/mongoization.rb
|
118
|
+
- lib/tod/railtie.rb
|
137
119
|
- lib/tod/shift.rb
|
138
120
|
- lib/tod/time_extensions.rb
|
139
121
|
- lib/tod/time_of_day.rb
|
122
|
+
- lib/tod/time_of_day_type.rb
|
140
123
|
- lib/tod/version.rb
|
141
124
|
- test/support/active_record.rb
|
142
125
|
- test/test_helper.rb
|
143
126
|
- test/tod/conversion_test.rb
|
144
127
|
- test/tod/date_test.rb
|
145
128
|
- test/tod/shift_test.rb
|
146
|
-
- test/tod/
|
129
|
+
- test/tod/time_of_day_attribute_test.rb
|
147
130
|
- test/tod/time_of_day_test.rb
|
148
131
|
- test/tod/time_of_day_time_zone_with_active_support_test.rb
|
149
132
|
- test/tod/time_test.rb
|
@@ -152,7 +135,7 @@ homepage: https://github.com/JackC/tod
|
|
152
135
|
licenses:
|
153
136
|
- MIT
|
154
137
|
metadata: {}
|
155
|
-
post_install_message:
|
138
|
+
post_install_message:
|
156
139
|
rdoc_options: []
|
157
140
|
require_paths:
|
158
141
|
- lib
|
@@ -167,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
150
|
- !ruby/object:Gem::Version
|
168
151
|
version: '0'
|
169
152
|
requirements: []
|
170
|
-
|
171
|
-
|
172
|
-
signing_key:
|
153
|
+
rubygems_version: 3.2.15
|
154
|
+
signing_key:
|
173
155
|
specification_version: 4
|
174
156
|
summary: Supplies TimeOfDay and Shift class
|
175
157
|
test_files:
|
@@ -178,7 +160,7 @@ test_files:
|
|
178
160
|
- test/tod/conversion_test.rb
|
179
161
|
- test/tod/date_test.rb
|
180
162
|
- test/tod/shift_test.rb
|
181
|
-
- test/tod/
|
163
|
+
- test/tod/time_of_day_attribute_test.rb
|
182
164
|
- test/tod/time_of_day_test.rb
|
183
165
|
- test/tod/time_of_day_time_zone_with_active_support_test.rb
|
184
166
|
- test/tod/time_test.rb
|
data/gemfiles/3.2.gemfile
DELETED
data/gemfiles/4.0.gemfile
DELETED
data/gemfiles/4.1.gemfile
DELETED
data/gemfiles/4.2.gemfile
DELETED
data/lib/tod/arel_extensions.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'arel'
|
2
|
-
|
3
|
-
module Tod
|
4
|
-
module ArelDepthFirstExtensions
|
5
|
-
def self.included(base)
|
6
|
-
base.send :alias_method, :visit_Tod_TimeOfDay, :terminal
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
module ArelDotExtensions
|
11
|
-
def self.included(base)
|
12
|
-
base.send :alias_method, :visit_Tod_TimeOfDay, :visit_String
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module ArelToSqlExtensions
|
17
|
-
def visit_Tod_TimeOfDay(o, collector=nil)
|
18
|
-
quote Tod::TimeOfDay.dump(o)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
Arel::Visitors::DepthFirst.send :include, Tod::ArelDepthFirstExtensions
|
24
|
-
Arel::Visitors::Dot.send :include, Tod::ArelDotExtensions
|
25
|
-
Arel::Visitors::ToSql.send :include, Tod::ArelToSqlExtensions
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
|
2
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..','support/active_record'))
|
3
|
-
|
4
|
-
class Order < ActiveRecord::Base
|
5
|
-
serialize :time, Tod::TimeOfDay
|
6
|
-
end
|
7
|
-
|
8
|
-
describe "TimeOfDay with ActiveRecord Serializable Attribute" do
|
9
|
-
describe ".dump" do
|
10
|
-
it "sets time of day" do
|
11
|
-
Order.create!(time: Tod::TimeOfDay.new(9, 30))
|
12
|
-
end
|
13
|
-
|
14
|
-
it "sets nil as value" do
|
15
|
-
Order.create!(time: nil)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe ".load" do
|
20
|
-
it "loads set time" do
|
21
|
-
time_of_day = Tod::TimeOfDay.new(9, 30)
|
22
|
-
order = Order.create!(time: time_of_day)
|
23
|
-
order.reload
|
24
|
-
assert_equal order.time, time_of_day
|
25
|
-
end
|
26
|
-
|
27
|
-
it "returns nil if time is not set" do
|
28
|
-
order = Order.create!(time: nil)
|
29
|
-
order.reload
|
30
|
-
assert_equal order.time, nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "Order.where" do
|
35
|
-
it "handles TimeOfDay as a parameter" do
|
36
|
-
tod = Tod::TimeOfDay.new(11, 11)
|
37
|
-
expected = Order.create!(time: tod)
|
38
|
-
actual = Order.where(time: tod).first
|
39
|
-
assert_equal expected, actual
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|