Class: Artic::TimeRange

Inherits:
Range
  • Object
show all
Defined in:
lib/artic/time_range.rb

Overview

Represents a range of two times in the same day (e.g. 09:00-17:00).

Author:

  • Alessandro Desantis

Constant Summary collapse

TIME_REGEX =
/\A^(0\d|1\d|2[0-3]):[0-5]\d$\z/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_time, end_time) ⇒ TimeRange

Initializes a new range.

Parameters:

  • start_time (String)

    the start time (in HH:MM format)

  • end_time (String)

    the end time (in HH:MM format)

Raises:

  • (ArgumentError)

    if the start time or the end time is invalid

  • (ArgumentError)

    if the start time is after the end time



29
30
31
32
# File 'lib/artic/time_range.rb', line 29

def initialize(start_time, end_time)
  super
  validate_range
end

Class Method Details

.build(range) ⇒ TimeRange

Builds a time range from the provided value.

Parameters:

  • range (Range|TimeRange)

    a range of times (e.g. ‘09:00’..‘18:00’ or a TimeRange object)

Returns:

  • (TimeRange)

    the passed time range or a new time range



17
18
19
# File 'lib/artic/time_range.rb', line 17

def build(range)
  range.is_a?(TimeRange) ? range : TimeRange.new(range.begin, range.end)
end

Instance Method Details

#bisect(other) ⇒ Array<TimeRange>

Uses this range to bisect another.

If this range does not overlap the other, returns an array with the original range.

If this range completely covers the other, returns an empty array.

Examples:

range1 = TimeRange.new('10:00'..'12:00')
range2 = TimeRange.new('09:00'..'18:00')
range3 = TimeRange.new('08:00'..'11:00')

range1.bisect(range2)
# => [
#   #<TimeRange 09:00..10:00>,
#   #<TimeRange 12:00..18:00>
# ]

range2.bisect(range1)
# => []

range3.bisect(range2)
# => [
#   #<TimeRange 11:00..18:00>
# ]

range2.bisect(range3)
# => [
#   #<TimeRange 08:00..09:00>
# ]

Parameters:

Returns:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/artic/time_range.rb', line 98

def bisect(other)
  return [other] unless overlaps?(other)
  return [] if covers?(other)

  if self.begin <= other.begin && self.end <= other.end
    [self.end..other.end]
  elsif self.begin >= other.begin && self.end <= other.end
    [
      (other.begin..self.begin),
      (self.end..other.end)
    ]
  elsif self.begin >= other.begin && self.end >= other.end
    [other.begin..self.begin]
  end
end

#covers?(other) ⇒ Boolean

Returns whether this range completely covers the one given.

Parameters:

Returns:

  • (Boolean)


49
50
51
# File 'lib/artic/time_range.rb', line 49

def covers?(other)
  self.begin <= other.begin && self.end >= other.end
end

#overlaps?(other) ⇒ Boolean

Returns whether the two ranges overlap (i.e. whether there’s at least a moment in time that belongs to both ranges).

Parameters:

Returns:

  • (Boolean)


40
41
42
# File 'lib/artic/time_range.rb', line 40

def overlaps?(other)
  self.begin <= other.end && self.end >= other.begin
end

#with_date(date) ⇒ Range

Returns a range of Time objects for this time range.

Parameters:

  • date (Date)

    the date to use for the range

Returns:

  • (Range)


58
59
60
61
62
63
# File 'lib/artic/time_range.rb', line 58

def with_date(date)
  Range.new(
    Time.parse("#{date} #{self.begin}"),
    Time.parse("#{date} #{self.end}")
  )
end