Class: Tod::Shift
- Inherits:
-
Object
- Object
- Tod::Shift
- Defined in:
- lib/tod/shift.rb
Overview
Shift is a range-like class that handles wrapping around midnight. For example, the Shift of 2300 to 0200 would include 0100.
Instance Attribute Summary collapse
-
#beginning ⇒ Object
readonly
Returns the value of attribute beginning.
-
#ending ⇒ Object
readonly
Returns the value of attribute ending.
-
#range ⇒ Object
readonly
Returns the value of attribute range.
Instance Method Summary collapse
- #==(other) ⇒ Object
- #contains?(shift) ⇒ Boolean
-
#duration ⇒ Object
Return shift duration in seconds.
- #eql?(other) ⇒ Boolean
- #exclude_end? ⇒ Boolean
- #hash ⇒ Object
-
#include?(tod) ⇒ Boolean
Returns true if the time of day is inside the shift, false otherwise.
-
#initialize(beginning, ending, exclude_end = false) ⇒ Shift
constructor
A new instance of Shift.
-
#overlaps?(other) ⇒ Boolean
Returns true if ranges overlap, false otherwise.
-
#slide(seconds) ⇒ Object
Move start and end by a number of seconds and return new shift.
Constructor Details
#initialize(beginning, ending, exclude_end = false) ⇒ Shift
Returns a new instance of Shift.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/tod/shift.rb', line 8 def initialize(beginning, ending, exclude_end=false) raise ArgumentError, "beginning can not be nil" unless beginning raise ArgumentError, "ending can not be nil" unless ending unless [true, false].include? exclude_end raise ArgumentError, "exclude_end must be true or false" end @beginning = beginning @ending = ending @exclude_end = exclude_end normalized_ending = ending.to_i normalized_ending += TimeOfDay::NUM_SECONDS_IN_DAY if normalized_ending < beginning.to_i @range = Range.new(beginning.to_i, normalized_ending, @exclude_end) freeze # Shift instances are value objects end |
Instance Attribute Details
#beginning ⇒ Object (readonly)
Returns the value of attribute beginning.
6 7 8 |
# File 'lib/tod/shift.rb', line 6 def beginning @beginning end |
#ending ⇒ Object (readonly)
Returns the value of attribute ending.
6 7 8 |
# File 'lib/tod/shift.rb', line 6 def ending @ending end |
#range ⇒ Object (readonly)
Returns the value of attribute range.
6 7 8 |
# File 'lib/tod/shift.rb', line 6 def range @range end |
Instance Method Details
#==(other) ⇒ Object
86 87 88 |
# File 'lib/tod/shift.rb', line 86 def ==(other) @range == other.range end |
#contains?(shift) ⇒ Boolean
72 73 74 |
# File 'lib/tod/shift.rb', line 72 def contains?(shift) self.include?(shift.beginning) && self.include?(shift.ending) end |
#duration ⇒ Object
Return shift duration in seconds. if ending is lower than beginning this method will calculate the duration as the ending time is from the following day
78 79 80 |
# File 'lib/tod/shift.rb', line 78 def duration @range.last - @range.first end |
#eql?(other) ⇒ Boolean
90 91 92 |
# File 'lib/tod/shift.rb', line 90 def eql?(other) @range.eql?(other.range) end |
#exclude_end? ⇒ Boolean
82 83 84 |
# File 'lib/tod/shift.rb', line 82 def exclude_end? @exclude_end end |
#hash ⇒ Object
94 95 96 |
# File 'lib/tod/shift.rb', line 94 def hash @range.hash end |
#include?(tod) ⇒ Boolean
Returns true if the time of day is inside the shift, false otherwise.
28 29 30 31 32 |
# File 'lib/tod/shift.rb', line 28 def include?(tod) second = tod.to_i second += TimeOfDay::NUM_SECONDS_IN_DAY if second < @range.first @range.cover?(second) end |
#overlaps?(other) ⇒ Boolean
Returns true if ranges overlap, false otherwise.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/tod/shift.rb', line 35 def overlaps?(other) a, b = [self, other].map(&:range) # # Although a Shift which passes through midnight is stored # internally as lasting more than TimeOfDay::NUM_SECONDS_IN_DAY # seconds from midnight, that's not how it is meant to be # handled. Rather, it consists of two chunks: # # range.first => Midnight # Midnight => range.last # # The second one is *before* the first. None of it is more than # TimeOfDay::NUM_SECONDS_IN_DAY after midnight. We thus need to shift # each of our ranges to cover all overlapping possibilities. # one_day = TimeOfDay::NUM_SECONDS_IN_DAY ashifted = Range.new(a.first + one_day, a.last + one_day, a.exclude_end?) bshifted = Range.new(b.first + one_day, b.last + one_day, b.exclude_end?) # # For exclusive ranges we need: # # a.ending > b.beginning && b.ending > a.beginning # # and for inclusive we need: # # a.ending >= b.beginning && b.ending >= a.beginning # aop = a.exclude_end? ? :> : :>= bop = b.exclude_end? ? :> : :>= # (a.last.send(aop, b.first) && b.last.send(bop, a.first)) || (ashifted.last.send(aop, b.first) && b.last.send(bop, ashifted.first)) || (a.last.send(aop, bshifted.first) && bshifted.last.send(bop, a.first)) end |
#slide(seconds) ⇒ Object
Move start and end by a number of seconds and return new shift.
99 100 101 |
# File 'lib/tod/shift.rb', line 99 def (seconds) self.class.new(beginning + seconds, ending + seconds, exclude_end?) end |