tod 2.0.1 → 3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0e1df7c0f812d7e18d6d9b10c256f2e26e63268c
4
- data.tar.gz: f01a512e048fa9087ab1b89376a2f6a49574357f
2
+ SHA256:
3
+ metadata.gz: 8986b140f4dcc736d253b188cd5f9a46a72110f38887cd6e8ff93ecee823c438
4
+ data.tar.gz: 95d31c83abc1264946bf2ce6aa6ba6fac45dcaeca1362b76a22d54eab27f402f
5
5
  SHA512:
6
- metadata.gz: cf81e8e52153b7e894d0a970a88c6da2fe94dbabf984cd289be160b7ab1eb43ce78e6c991c0f833ac25ebc818a7950deae44d19610a1f66081ba1998dae3bbd3
7
- data.tar.gz: d6665499e05b78076fab42c5dfe4b67c94750ad71fc722384f51b7c97aad9b6fc78fc3b2e9906d3af273f66c769bdd73bce956cb206f7a4b63209cd8237d43d0
6
+ metadata.gz: 2d1c3b50deb1df502928666b38e113fb7d58b4a25c140119bac8155ad3ff3add0689cffba810b7bdd6ab1461493838873a839ac259895630210e47679ae9ef89
7
+ data.tar.gz: 98a76ddcb2b8c866f602efe1def27c236b88ffcc6bbb12812580794113dc964d5b6df1bd95b0f055a48e9e95ca4b69ccf3dea93b20f866ca72be7932596e1aaf
data/.gitignore CHANGED
@@ -4,3 +4,5 @@ pkg/*
4
4
  nbproject
5
5
  *.swp
6
6
  .rvmrc
7
+ vendor/
8
+ .idea
data/.travis.yml CHANGED
@@ -1,11 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2.0
4
- - 2.1.5
5
- - 2.0.0
6
- - 1.9.3
7
- gemfile:
8
- - gemfiles/3.2.gemfile
9
- - gemfiles/4.0.gemfile
10
- - gemfiles/4.1.gemfile
11
- - gemfiles/4.2.gemfile
3
+ - 2.6.5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ # 3.0.0 (March 6, 2021)
2
+
3
+ * Support and require Rails 6
4
+
5
+ # 2.2.0 (October 10, 2018)
6
+
7
+ * Add string formatting compatible with Rails (Tate Johnson)
8
+ * Add ability to use ActiveRecord's attribute API (Brent Wheeldon)
9
+ * Add method for use in Rails database quoting (Ben Jackson)
10
+
11
+ # 2.1.1 (April 14, 2017)
12
+
13
+ * Fix serialize Ruby Time to Tod::TimeOfDay (Ryan Dick)
14
+ * Fix TimeOfDay.from_second_of_day when passed float (Jack Christensen)
15
+ * Fix Rails 5 multi-param assignment (Miklos Fazekas)
16
+
17
+ # 2.1.0 (May 9, 2016)
18
+
19
+ * Fix date extensions requiring date (ambirdsall)
20
+ * Add subtraction to TimeOfDay (Hiroki Shirai)
21
+ * Add equality comparison for shifts (Greg Beech)
22
+ * Add arel_extensions for TimeOfDay (Paul Tyng)
23
+ * Support for shifts that span to other days (kennyeni)
24
+
25
+ # 2.0.2 (May 21, 2015)
26
+
27
+ * Fix ActiveRecord serialization when core extensions not loaded
28
+
1
29
  # 2.0.1 (May 8, 2015)
2
30
 
3
31
  * Fix Tod::TimeOfDay() without core extensions
data/Gemfile.lock CHANGED
@@ -1,50 +1,52 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tod (2.0.0)
4
+ tod (3.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- activemodel (4.2.0)
10
- activesupport (= 4.2.0)
11
- builder (~> 3.1)
12
- activerecord (4.2.0)
13
- activemodel (= 4.2.0)
14
- activesupport (= 4.2.0)
15
- arel (~> 6.0)
16
- activesupport (4.2.0)
17
- i18n (~> 0.7)
18
- json (~> 1.7, >= 1.7.7)
19
- minitest (~> 5.1)
20
- thread_safe (~> 0.3, >= 0.3.4)
21
- tzinfo (~> 1.1)
22
- arel (6.0.0)
23
- builder (3.2.2)
24
- coderay (1.1.0)
25
- i18n (0.7.0)
26
- json (1.8.2)
27
- method_source (0.8.2)
28
- minitest (5.5.1)
29
- pry (0.10.1)
30
- coderay (~> 1.1.0)
31
- method_source (~> 0.8.1)
32
- slop (~> 3.4)
33
- rake (10.4.2)
34
- slop (3.6.0)
35
- sqlite3 (1.3.10)
36
- thread_safe (0.3.4)
37
- tzinfo (1.2.2)
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 (>= 3.0.0)
43
+ activerecord (>= 6.0.0)
45
44
  minitest
46
- pry
45
+ pry-byebug
47
46
  rake
48
47
  sqlite3
49
48
  tod!
50
49
  tzinfo
50
+
51
+ BUNDLED WITH
52
+ 2.0.2
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
@@ -184,16 +213,29 @@ 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.
188
217
 
189
- Active Record Serializable Attribute Support
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.
222
+
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 implements a custom serialization contract for ActiveRecord serialize which allows to store Tod::TimeOfDay directly
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
195
237
  class Order < ActiveRecord::Base
196
- serialize :time, Tod::TimeOfDay
238
+ attribute :time, :time_only
197
239
  end
198
240
  order = Order.create(time: Tod::TimeOfDay.new(9,30))
199
241
  order.time # => 09:30:00
@@ -241,10 +283,10 @@ Compatibility
241
283
 
242
284
  [![Build Status](https://travis-ci.org/jackc/tod.png)](https://travis-ci.org/jackc/tod)
243
285
 
244
- Tod is compatible with Ruby 1.9.3, 2.0.0, 2.1.8, and 2.2.0. It is tested against Rails 3.2, 4.0, 4.1, 4.2.
286
+ Tod is tested against Ruby 2.6.x and Rails 6.x.
245
287
 
246
288
 
247
289
  License
248
290
  =======
249
291
 
250
- Copyright (c) 2010-2015 Jack Christensen, released under the MIT license
292
+ Copyright (c) 2010-2021 Jack Christensen, released under the MIT license
data/lib/tod.rb CHANGED
@@ -1,3 +1,5 @@
1
1
  require 'tod/time_of_day'
2
2
  require 'tod/shift'
3
3
  require 'tod/conversions'
4
+
5
+ require 'tod/railtie' if defined?(Rails)
@@ -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
 
@@ -1,3 +1,5 @@
1
+ require 'date'
2
+
1
3
  module Tod
2
4
  module DateExtensions
3
5
  # Returns a local Time instance with this date and time_of_day
@@ -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
@@ -33,9 +33,40 @@ module Tod
33
33
 
34
34
  # Returns true if ranges overlap, false otherwise.
35
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)
36
+ a, b = [self, other].map(&:range)
37
+ #
38
+ # Although a Shift which passes through midnight is stored
39
+ # internally as lasting more than TimeOfDay::NUM_SECONDS_IN_DAY
40
+ # seconds from midnight, that's not how it is meant to be
41
+ # handled. Rather, it consists of two chunks:
42
+ #
43
+ # range.first => Midnight
44
+ # Midnight => range.last
45
+ #
46
+ # The second one is *before* the first. None of it is more than
47
+ # TimeOfDay::NUM_SECONDS_IN_DAY after midnight. We thus need to shift
48
+ # each of our ranges to cover all overlapping possibilities.
49
+ #
50
+ one_day = TimeOfDay::NUM_SECONDS_IN_DAY
51
+ ashifted =
52
+ Range.new(a.first + one_day, a.last + one_day, a.exclude_end?)
53
+ bshifted =
54
+ Range.new(b.first + one_day, b.last + one_day, b.exclude_end?)
55
+ #
56
+ # For exclusive ranges we need:
57
+ #
58
+ # a.ending > b.beginning && b.ending > a.beginning
59
+ #
60
+ # and for inclusive we need:
61
+ #
62
+ # a.ending >= b.beginning && b.ending >= a.beginning
63
+ #
64
+ aop = a.exclude_end? ? :> : :>=
65
+ bop = b.exclude_end? ? :> : :>=
66
+ #
67
+ (a.last.send(aop, b.first) && b.last.send(bop, a.first)) ||
68
+ (ashifted.last.send(aop, b.first) && b.last.send(bop, ashifted.first)) ||
69
+ (a.last.send(aop, bshifted.first) && bshifted.last.send(bop, a.first))
39
70
  end
40
71
 
41
72
  def contains?(shift)
@@ -51,5 +82,22 @@ module Tod
51
82
  def exclude_end?
52
83
  @exclude_end
53
84
  end
85
+
86
+ def ==(other)
87
+ @range == other.range
88
+ end
89
+
90
+ def eql?(other)
91
+ @range.eql?(other.range)
92
+ end
93
+
94
+ def hash
95
+ @range.hash
96
+ end
97
+
98
+ # Move start and end by a number of seconds and return new shift.
99
+ def slide(seconds)
100
+ self.class.new(beginning + seconds, ending + seconds, exclude_end?)
101
+ end
54
102
  end
55
103
  end
@@ -9,7 +9,7 @@ module Tod
9
9
 
10
10
  PARSE_24H_REGEX = /
11
11
  \A
12
- ([01]?\d|2[0-3])
12
+ ([01]?\d|2[0-4])
13
13
  :?
14
14
  ([0-5]\d)?
15
15
  :?
@@ -34,20 +34,29 @@ module Tod
34
34
  /x
35
35
 
36
36
  WORDS = {
37
- "noon" => "12pm",
38
- "midnight" => "12am"
37
+ "noon" => "12pm".freeze,
38
+ "midnight" => "12am".freeze
39
39
  }
40
40
 
41
41
  NUM_SECONDS_IN_DAY = 86400
42
42
  NUM_SECONDS_IN_HOUR = 3600
43
43
  NUM_SECONDS_IN_MINUTE = 60
44
44
 
45
+ FORMATS = {
46
+ short: "%-l:%M %P".freeze,
47
+ medium: "%-l:%M:%S %P".freeze,
48
+ time: "%H:%M".freeze
49
+ }
50
+
45
51
  def initialize(h, m=0, s=0)
46
52
  @hour = Integer(h)
47
53
  @minute = Integer(m)
48
54
  @second = Integer(s)
49
55
 
50
- raise ArgumentError, "hour must be between 0 and 23" unless (0..23).include?(@hour)
56
+ raise ArgumentError, "hour must be between 0 and 24" unless (0..24).include?(@hour)
57
+ if @hour == 24 && (@minute != 0 || @second != 0)
58
+ raise ArgumentError, "hour can only be 24 when minute and second are 0"
59
+ end
51
60
  raise ArgumentError, "minute must be between 0 and 59" unless (0..59).include?(@minute)
52
61
  raise ArgumentError, "second must be between 0 and 59" unless (0..59).include?(@second)
53
62
 
@@ -61,13 +70,44 @@ module Tod
61
70
  @second_of_day <=> other.second_of_day
62
71
  end
63
72
 
73
+ # Rounding to the given nearest number of seconds
74
+ def round(round_sec = 1)
75
+ down = self - (self.to_i % round_sec)
76
+ up = down + round_sec
77
+
78
+ difference_down = self - down
79
+ difference_up = up - self
80
+
81
+ if (difference_down < difference_up)
82
+ return down
83
+ else
84
+ return up
85
+ end
86
+ end
87
+
64
88
  # Formats identically to Time#strftime
65
89
  def strftime(format_string)
90
+ # Special case 2400 because strftime will load TimeOfDay into Time which
91
+ # will convert 24 to 0
92
+ format_string = format_string.gsub(/%H|%k/, '24') if @hour == 24
66
93
  Time.local(2000,1,1, @hour, @minute, @second).strftime(format_string)
67
94
  end
68
95
 
69
- def to_s
70
- strftime "%H:%M:%S"
96
+ def to_formatted_s(format = :default)
97
+ if formatter = FORMATS[format]
98
+ if formatter.respond_to?(:call)
99
+ formatter.call(self).to_s
100
+ else
101
+ strftime(formatter)
102
+ end
103
+ else
104
+ strftime "%H:%M:%S"
105
+ end
106
+ end
107
+ alias_method :to_s, :to_formatted_s
108
+
109
+ def value_for_database
110
+ to_s
71
111
  end
72
112
 
73
113
  # Return a new TimeOfDay num_seconds greater than self. It will wrap around
@@ -78,8 +118,12 @@ module Tod
78
118
 
79
119
  # Return a new TimeOfDay num_seconds less than self. It will wrap around
80
120
  # at midnight.
81
- def -(num_seconds)
82
- TimeOfDay.from_second_of_day @second_of_day - num_seconds
121
+ def -(other)
122
+ if other.instance_of?(TimeOfDay)
123
+ TimeOfDay.from_second_of_day @second_of_day - other.second_of_day
124
+ else
125
+ TimeOfDay.from_second_of_day @second_of_day - other
126
+ end
83
127
  end
84
128
 
85
129
  # Returns a Time instance on date using self as the time of day
@@ -92,6 +136,8 @@ module Tod
92
136
  #
93
137
  # TimeOfDay.from_second_of_day(3600) == TimeOfDay.new(1) # => true
94
138
  def self.from_second_of_day(second_of_day)
139
+ second_of_day = Integer(second_of_day)
140
+ return new 24 if second_of_day == NUM_SECONDS_IN_DAY
95
141
  remaining_seconds = second_of_day % NUM_SECONDS_IN_DAY
96
142
  hour = remaining_seconds / NUM_SECONDS_IN_HOUR
97
143
  remaining_seconds -= hour * NUM_SECONDS_IN_HOUR
@@ -118,8 +164,10 @@ module Tod
118
164
  # TimeOfDay.parse "3:25:58" # => 03:25:58
119
165
  # TimeOfDay.parse "515p" # => 17:15:00
120
166
  # TimeOfDay.parse "151253" # => 15:12:53
167
+ # You can give a block, that is called with the input if the string is not parsable.
168
+ # If no block is given an ArgumentError is raised if try_parse returns nil.
121
169
  def self.parse(tod_string)
122
- try_parse(tod_string) || (raise ArgumentError, "Invalid time of day string")
170
+ try_parse(tod_string) || (block_given? ? yield(tod_string) : raise(ArgumentError, "Invalid time of day string"))
123
171
  end
124
172
 
125
173
  # Same as parse(), but return nil if not parsable (instead of raising an error)
@@ -156,21 +204,5 @@ module Tod
156
204
  def self.time_zone
157
205
  (Time.respond_to?(:zone) && Time.zone) || Time
158
206
  end
159
-
160
- def self.dump(time_of_day)
161
- if time_of_day.to_s == ''
162
- nil
163
- else
164
- time_of_day.to_s
165
- end
166
- end
167
-
168
- def self.load(time)
169
- if time.respond_to?(:to_time_of_day)
170
- time.to_time_of_day
171
- else
172
- TimeOfDay.parse(time) if time && !time.empty?
173
- end
174
- end
175
207
  end
176
208
  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
@@ -1,3 +1,3 @@
1
1
  module Tod
2
- VERSION = "2.0.1"
2
+ VERSION = "3.0.0"
3
3
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe "TimeOfDay()" do
4
4
  it "handles Tod::TimeOfDay" do
@@ -81,4 +81,11 @@ 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
84
91
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe "Date extensions" do
4
4
  describe "#at" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe "Shift" do
4
4
  describe "#initialize" do
@@ -43,12 +43,49 @@ describe "Shift" do
43
43
  shift1 = Tod::Shift.new(Tod::TimeOfDay.new(12), Tod::TimeOfDay.new(18))
44
44
  shift2 = Tod::Shift.new(Tod::TimeOfDay.new(13), Tod::TimeOfDay.new(15))
45
45
  assert shift1.overlaps?(shift2)
46
+
47
+ # Additional Testing for Shifts that span from one day to another
48
+ cases = [
49
+ [5, 8, 7, 2],
50
+ [7, 2, 1, 8],
51
+ [7, 2, 5, 8],
52
+ [4, 8, 1, 5],
53
+ [1, 5, 4, 8],
54
+ [7, 2, 1, 4],
55
+ [1, 4, 7, 2],
56
+ [1, 4, 3, 2],
57
+ [5, 8, 7, 2],
58
+ [7, 2, 8, 3],
59
+ [7, 2, 6, 3],
60
+ [7, 2, 1, 8]
61
+ ]
62
+
63
+ cases.each do |c|
64
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(c[0]), Tod::TimeOfDay.new(c[1]))
65
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(c[2]), Tod::TimeOfDay.new(c[3]))
66
+ assert shift1.overlaps?(shift2), "Failed with args: #{c}"
67
+ end
46
68
  end
47
69
 
48
70
  it "is false when shifts don't overlap" do
49
71
  shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5))
50
72
  shift2 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(12))
51
73
  refute shift1.overlaps?(shift2)
74
+
75
+ # Additional Testing for Shifts that span from one day to another
76
+ cases = [
77
+ [7, 8, 1, 5],
78
+ [1, 5, 7, 8],
79
+ [7, 2, 3, 4],
80
+ [3, 4, 5, 2],
81
+ [1, 5, 9, 12]
82
+ ]
83
+
84
+ cases.each do |c|
85
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(c[0]), Tod::TimeOfDay.new(c[1]))
86
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(c[2]), Tod::TimeOfDay.new(c[3]))
87
+ refute shift1.overlaps?(shift2), "Failed with args: #{c}"
88
+ end
52
89
  end
53
90
 
54
91
  it "is true when shifts touch with inclusive end" do
@@ -62,6 +99,49 @@ describe "Shift" do
62
99
  shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12), true)
63
100
  refute shift1.overlaps?(shift2)
64
101
  end
102
+
103
+ it "copes correctly with mixed shifts" do
104
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5))
105
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12), true)
106
+ assert shift1.overlaps?(shift2)
107
+ assert shift2.overlaps?(shift1)
108
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(1), Tod::TimeOfDay.new(5), true)
109
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(5), Tod::TimeOfDay.new(12))
110
+ refute shift1.overlaps?(shift2)
111
+ refute shift2.overlaps?(shift1)
112
+ end
113
+
114
+ it "copes correctly with zero length inclusive end shifts" do
115
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17))
116
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(10))
117
+ shift3 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(9))
118
+ shift4 = Tod::Shift.new(Tod::TimeOfDay.new(17), Tod::TimeOfDay.new(17))
119
+ assert shift1.overlaps?(shift2)
120
+ assert shift2.overlaps?(shift1)
121
+
122
+ assert shift1.overlaps?(shift3)
123
+ assert shift3.overlaps?(shift1)
124
+
125
+ assert shift1.overlaps?(shift4)
126
+ assert shift4.overlaps?(shift1)
127
+
128
+ end
129
+
130
+ it "copes correctly with zero length exclusive end shifts" do
131
+ shift1 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(17), true)
132
+ shift2 = Tod::Shift.new(Tod::TimeOfDay.new(10), Tod::TimeOfDay.new(10), true)
133
+ shift3 = Tod::Shift.new(Tod::TimeOfDay.new(9), Tod::TimeOfDay.new(9), true)
134
+ shift4 = Tod::Shift.new(Tod::TimeOfDay.new(17), Tod::TimeOfDay.new(17), true)
135
+ assert shift1.overlaps?(shift2)
136
+ assert shift2.overlaps?(shift1)
137
+
138
+ refute shift1.overlaps?(shift3)
139
+ refute shift3.overlaps?(shift1)
140
+
141
+ refute shift1.overlaps?(shift4)
142
+ refute shift4.overlaps?(shift1)
143
+
144
+ end
65
145
  end
66
146
 
67
147
  describe "contains?" do
@@ -166,4 +246,153 @@ describe "Shift" do
166
246
  assert shift.include?(value)
167
247
  end
168
248
  end
249
+
250
+ describe "#==" do
251
+ it "is true when the beginning time, end time, and exclude end are the same" do
252
+ tod1 = Tod::TimeOfDay.new 8,30
253
+ tod2 = Tod::TimeOfDay.new 13,00,30
254
+ shift1 = Tod::Shift.new tod1, tod2
255
+ shift2 = Tod::Shift.new tod1, tod2
256
+ assert shift1 == shift2
257
+ end
258
+
259
+ it "is false when the beginning time is different" do
260
+ tod1 = Tod::TimeOfDay.new 8,30
261
+ tod2 = Tod::TimeOfDay.new 13,00,30
262
+ shift1 = Tod::Shift.new tod1, tod2
263
+ shift2 = Tod::Shift.new tod1, Tod::TimeOfDay.new(14,00)
264
+ assert !(shift1 == shift2)
265
+ end
266
+
267
+ it "is false when the ending time is different" do
268
+ tod1 = Tod::TimeOfDay.new 8,30
269
+ tod2 = Tod::TimeOfDay.new 13,00,30
270
+ shift1 = Tod::Shift.new tod1, tod2
271
+ shift2 = Tod::Shift.new Tod::TimeOfDay.new(9,30), tod2
272
+ assert !(shift1 == shift2)
273
+ end
274
+
275
+ it "is false when exclude end is different" do
276
+ tod1 = Tod::TimeOfDay.new 8,30
277
+ tod2 = Tod::TimeOfDay.new 13,00,30
278
+ shift1 = Tod::Shift.new tod1, tod2
279
+ shift2 = Tod::Shift.new tod1, tod2, true
280
+ assert !(shift1 == shift2)
281
+ end
282
+ end
283
+
284
+ describe "#eql?" do
285
+ it "is true when the beginning time, end time, and exclude end are the same" do
286
+ tod1 = Tod::TimeOfDay.new 8,30
287
+ tod2 = Tod::TimeOfDay.new 13,00,30
288
+ shift1 = Tod::Shift.new tod1, tod2
289
+ shift2 = Tod::Shift.new tod1, tod2
290
+ assert shift1.eql?(shift2)
291
+ end
292
+
293
+ it "is false when the beginning time is different" do
294
+ tod1 = Tod::TimeOfDay.new 8,30
295
+ tod2 = Tod::TimeOfDay.new 13,00,30
296
+ shift1 = Tod::Shift.new tod1, tod2
297
+ shift2 = Tod::Shift.new tod1, Tod::TimeOfDay.new(14,00)
298
+ assert !shift1.eql?(shift2)
299
+ end
300
+
301
+ it "is false when the ending time is different" do
302
+ tod1 = Tod::TimeOfDay.new 8,30
303
+ tod2 = Tod::TimeOfDay.new 13,00,30
304
+ shift1 = Tod::Shift.new tod1, tod2
305
+ shift2 = Tod::Shift.new Tod::TimeOfDay.new(9,30), tod2
306
+ assert !shift1.eql?(shift2)
307
+ end
308
+
309
+ it "is false when exclude end is different" do
310
+ tod1 = Tod::TimeOfDay.new 8,30
311
+ tod2 = Tod::TimeOfDay.new 13,00,30
312
+ shift1 = Tod::Shift.new tod1, tod2
313
+ shift2 = Tod::Shift.new tod1, tod2, true
314
+ assert !shift1.eql?(shift2)
315
+ end
316
+ end
317
+
318
+ describe "#hash" do
319
+ it "is the same when the beginning time, end time, and exclude end are the same" do
320
+ tod1 = Tod::TimeOfDay.new 8,30
321
+ tod2 = Tod::TimeOfDay.new 13,00,30
322
+ shift1 = Tod::Shift.new tod1, tod2
323
+ shift2 = Tod::Shift.new tod1, tod2
324
+ assert_equal shift1.hash, shift2.hash
325
+ end
326
+
327
+ it "is usually different when the beginning time is different" do
328
+ tod1 = Tod::TimeOfDay.new 8,30
329
+ tod2 = Tod::TimeOfDay.new 13,00,30
330
+ shift1 = Tod::Shift.new tod1, tod2
331
+ shift2 = Tod::Shift.new tod1, Tod::TimeOfDay.new(14,00)
332
+ assert shift1.hash != shift2.hash
333
+ end
334
+
335
+ it "is usually different when the ending time is different" do
336
+ tod1 = Tod::TimeOfDay.new 8,30
337
+ tod2 = Tod::TimeOfDay.new 13,00,30
338
+ shift1 = Tod::Shift.new tod1, tod2
339
+ shift2 = Tod::Shift.new Tod::TimeOfDay.new(9,30), tod2
340
+ assert shift1.hash != shift2.hash
341
+ end
342
+
343
+ it "is usually different when exclude end is different" do
344
+ tod1 = Tod::TimeOfDay.new 8,30
345
+ tod2 = Tod::TimeOfDay.new 13,00,30
346
+ shift1 = Tod::Shift.new tod1, tod2
347
+ shift2 = Tod::Shift.new tod1, tod2, true
348
+ assert shift1.hash != shift2.hash
349
+ end
350
+ end
351
+
352
+ describe "slide" do
353
+ it "handles positive numbers" do
354
+ slide = 30 * 60 # 30 minutes in seconds
355
+
356
+ beginning_expected = Tod::TimeOfDay.new 10, 30
357
+ ending_expected = Tod::TimeOfDay.new 16, 30
358
+
359
+ beginning = Tod::TimeOfDay.new 10
360
+ ending = Tod::TimeOfDay.new 16
361
+ shift = Tod::Shift.new(beginning, ending, false).slide(slide)
362
+
363
+ assert_equal beginning_expected, shift.beginning
364
+ assert_equal ending_expected, shift.ending
365
+ refute shift.exclude_end?
366
+ end
367
+
368
+ it "handles negative numbers" do
369
+ slide = -30 * 60 # -30 minutes in seconds
370
+
371
+ beginning_expected = Tod::TimeOfDay.new 9, 30
372
+ ending_expected = Tod::TimeOfDay.new 15, 30
373
+
374
+ beginning = Tod::TimeOfDay.new 10
375
+ ending = Tod::TimeOfDay.new 16
376
+ shift = Tod::Shift.new(beginning, ending, false).slide(slide)
377
+
378
+ assert_equal beginning_expected, shift.beginning
379
+ assert_equal ending_expected, shift.ending
380
+ refute shift.exclude_end?
381
+ end
382
+
383
+ it "handles ActiveSupport::Duration" do
384
+ slide = 30.minutes
385
+
386
+ beginning_expected = Tod::TimeOfDay.new 10, 30
387
+ ending_expected = Tod::TimeOfDay.new 16, 30
388
+
389
+ beginning = Tod::TimeOfDay.new 10
390
+ ending = Tod::TimeOfDay.new 16
391
+ shift = Tod::Shift.new(beginning, ending, false).slide(slide)
392
+
393
+ assert_equal beginning_expected, shift.beginning
394
+ assert_equal ending_expected, shift.ending
395
+ refute shift.exclude_end?
396
+ end
397
+ end
169
398
  end
@@ -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
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
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 -1 }
7
- assert_raises(ArgumentError) { Tod::TimeOfDay.new 24 }
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
- assert_equal nil, Tod::TimeOfDay.try_parse(parse_string)
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
- assert_equal nil, Tod::TimeOfDay.try_parse(nil)
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 -1, Tod::TimeOfDay.new(8,0,0) <=> Tod::TimeOfDay.new(9,0,0)
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,48 @@ 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 "formats to HH:MM:SS" do
124
- assert_equal "08:15:30", Tod::TimeOfDay.new(8,15,30).to_s
125
- assert_equal "22:10:45", Tod::TimeOfDay.new(22,10,45).to_s
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
126
190
  end
127
191
  end
128
192
 
@@ -151,6 +215,12 @@ describe "TimeOfDay" do
151
215
  result = original + 15
152
216
  refute_equal original.object_id, result.object_id
153
217
  end
218
+
219
+ it "handles ActiveSupport::Duration" do
220
+ original = Tod::TimeOfDay.new(8,0,0)
221
+ result = original + 10.minutes
222
+ assert_equal Tod::TimeOfDay.new(8,10,0), result
223
+ end
154
224
  end
155
225
 
156
226
  describe "subtraction" do
@@ -171,6 +241,19 @@ describe "TimeOfDay" do
171
241
  result = original - 15
172
242
  refute_equal original.object_id, result.object_id
173
243
  end
244
+
245
+ it "handles ActiveSupport::Duration" do
246
+ original = Tod::TimeOfDay.new(8,0,0)
247
+ result = original - 10.minutes
248
+ assert_equal Tod::TimeOfDay.new(7,50,0), result
249
+ end
250
+
251
+ it "subtracts Tod::TimeOfDay object" do
252
+ right_side = Tod::TimeOfDay.new(10,0,0)
253
+ left_side = Tod::TimeOfDay.new(12,0,30)
254
+ result = right_side - left_side
255
+ assert_equal Tod::TimeOfDay.new(21,59,30), result
256
+ end
174
257
  end
175
258
 
176
259
  describe "from_second_of_day" do
@@ -182,7 +265,7 @@ describe "TimeOfDay" do
182
265
  end
183
266
 
184
267
  it "handles positive numbers a day or more away" do
185
- assert_equal Tod::TimeOfDay.new(0,0,0), Tod::TimeOfDay.from_second_of_day(86400)
268
+ assert_equal Tod::TimeOfDay.new(24,0,0), Tod::TimeOfDay.from_second_of_day(86400)
186
269
  assert_equal Tod::TimeOfDay.new(0,0,30), Tod::TimeOfDay.from_second_of_day(86430)
187
270
  assert_equal Tod::TimeOfDay.new(0,1,30), Tod::TimeOfDay.from_second_of_day(86490)
188
271
  assert_equal Tod::TimeOfDay.new(1,1,5), Tod::TimeOfDay.from_second_of_day(90065)
@@ -200,6 +283,10 @@ describe "TimeOfDay" do
200
283
  it "has alias from_i" do
201
284
  assert_equal Tod::TimeOfDay.method(:from_second_of_day), Tod::TimeOfDay.method(:from_i)
202
285
  end
286
+
287
+ it "handles floats" do
288
+ assert_equal Tod::TimeOfDay.new(15,30,0), Tod::TimeOfDay.from_second_of_day(55800.0)
289
+ end
203
290
  end
204
291
 
205
292
  describe "on" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe "TimeOfDay with ActiveSupport" do
4
4
  describe ".time_zone" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__),'..','test_helper'))
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe "Time extensions" do
4
4
  describe "#to_time_of_day" do
data/tod.gemspec CHANGED
@@ -16,9 +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", ">= 3.0.0"
19
+ s.add_development_dependency "activerecord", ">= 6.0.0"
20
20
  s.add_development_dependency "sqlite3"
21
- s.add_development_dependency "pry"
21
+ s.add_development_dependency "pry-byebug"
22
22
 
23
23
  s.files = `git ls-files`.split("\n")
24
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: 2.0.1
4
+ version: 3.0.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: 2015-05-08 00:00:00.000000000 Z
11
+ date: 2021-03-06 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: 3.0.0
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: 3.0.0
68
+ version: 6.0.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: pry
84
+ name: pry-byebug
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -110,25 +110,23 @@ files:
110
110
  - MIT-LICENSE
111
111
  - README.markdown
112
112
  - Rakefile
113
- - gemfiles/3.2.gemfile
114
- - gemfiles/4.0.gemfile
115
- - gemfiles/4.1.gemfile
116
- - gemfiles/4.2.gemfile
117
113
  - lib/tod.rb
118
114
  - lib/tod/conversions.rb
119
115
  - lib/tod/core_extensions.rb
120
116
  - lib/tod/date_extensions.rb
121
117
  - lib/tod/mongoization.rb
118
+ - lib/tod/railtie.rb
122
119
  - lib/tod/shift.rb
123
120
  - lib/tod/time_extensions.rb
124
121
  - lib/tod/time_of_day.rb
122
+ - lib/tod/time_of_day_type.rb
125
123
  - lib/tod/version.rb
126
124
  - test/support/active_record.rb
127
125
  - test/test_helper.rb
128
126
  - test/tod/conversion_test.rb
129
127
  - test/tod/date_test.rb
130
128
  - test/tod/shift_test.rb
131
- - test/tod/time_of_day_serializable_attribute_test.rb
129
+ - test/tod/time_of_day_attribute_test.rb
132
130
  - test/tod/time_of_day_test.rb
133
131
  - test/tod/time_of_day_time_zone_with_active_support_test.rb
134
132
  - test/tod/time_test.rb
@@ -137,7 +135,7 @@ homepage: https://github.com/JackC/tod
137
135
  licenses:
138
136
  - MIT
139
137
  metadata: {}
140
- post_install_message:
138
+ post_install_message:
141
139
  rdoc_options: []
142
140
  require_paths:
143
141
  - lib
@@ -152,9 +150,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
150
  - !ruby/object:Gem::Version
153
151
  version: '0'
154
152
  requirements: []
155
- rubyforge_project:
156
- rubygems_version: 2.4.5
157
- signing_key:
153
+ rubygems_version: 3.0.6
154
+ signing_key:
158
155
  specification_version: 4
159
156
  summary: Supplies TimeOfDay and Shift class
160
157
  test_files:
@@ -163,7 +160,7 @@ test_files:
163
160
  - test/tod/conversion_test.rb
164
161
  - test/tod/date_test.rb
165
162
  - test/tod/shift_test.rb
166
- - test/tod/time_of_day_serializable_attribute_test.rb
163
+ - test/tod/time_of_day_attribute_test.rb
167
164
  - test/tod/time_of_day_test.rb
168
165
  - test/tod/time_of_day_time_zone_with_active_support_test.rb
169
166
  - test/tod/time_test.rb
data/gemfiles/3.2.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "~> 3.2.13"
4
-
5
- gemspec :path=>"../"
data/gemfiles/4.0.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "4.0.0"
4
-
5
- gemspec :path=>"../"
data/gemfiles/4.1.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "~> 4.1.8"
4
-
5
- gemspec :path=>"../"
data/gemfiles/4.2.gemfile DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "activerecord", "~> 4.2.0"
4
-
5
- gemspec :path=>"../"
@@ -1,31 +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
- assert_equal order.time, time_of_day
24
- end
25
-
26
- it "returns nil if time is not set" do
27
- order = Order.create(time: nil)
28
- assert_equal order.time, nil
29
- end
30
- end
31
- end