Class: TimeRange

Inherits:
Range show all
Defined in:
lib/time_range.rb,
lib/time_range/version.rb

Overview

An enhanced, Range-type class that provides useful methods that apply to time-based objects.

Since:

  • 0.0.1

Constant Summary collapse

VERSION =

Since:

  • 0.0.1

'0.1.0'

Instance Method Summary collapse

Methods inherited from Range

#to_time_range

Constructor Details

#initialize(b, e, exclude_end = false) ⇒ TimeRange

Returns a new instance of TimeRange.

Raises:

  • (TypeError)

Since:

  • 0.0.1



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/time_range.rb', line 11

def initialize(b, e, exclude_end = false)
  raise TypeError unless [b, e].all? { |arg| arg.is_a?(Time) }

  valid_time = if exclude_end
                 (e - 1) >= b
               else
                 e >= b
               end

  raise ArgumentError unless valid_time

  super
end

Instance Method Details

#==(other) ⇒ Boolean Also known as: eql?

Reimplementation of Range#== to account for time ranges excluding end being one second shorter than their end implies.

Parameters:

  • time_range (TimeRange)

    time range to compare for equality

Returns:

  • (Boolean)

    whether contents of two TimeRanges match

Since:

  • 0.0.1



30
31
32
33
34
35
36
37
38
# File 'lib/time_range.rb', line 30

def ==(other)
  return false unless other.is_a?(self.class)

  if exclude_end? || other.exclude_end?
    return self.begin == other.begin && max == other.max
  end

  super
end

#datesRange

Returns the dates in the current TimeRange as a Range of Dates.

Returns:

  • (Range)

    the dates in the current time range

Since:

  • 0.0.1



116
117
118
119
120
121
# File 'lib/time_range.rb', line 116

def dates
  b_date = Date.civil(self.begin.year, self.begin.month, self.begin.day)
  e_date = Date.civil(max.year, max.month, max.day)

  b_date..e_date
end

#durationFloat

The duration of the time range in seconds.

Returns:

  • (Float)

    the number of seconds in the time range

Since:

  • 0.0.1



61
62
63
# File 'lib/time_range.rb', line 61

def duration
  max - self.begin
end

#encapsulated_by?(time_range) ⇒ Boolean

Reverse of #encapsulates?, checks if the current time range is encapsulated by another.

Parameters:

  • time_range (TimeRange)

    time range to compare against encapsulation

Returns:

  • (Boolean)

    whether the target range encapsulates this one

Raises:

  • (TypeError)

Since:

  • 0.0.1



94
95
96
97
98
# File 'lib/time_range.rb', line 94

def encapsulated_by?(time_range)
  raise TypeError unless time_range.is_a?(TimeRange)

  time_range.encapsulates?(self)
end

#encapsulates?(time_range) ⇒ Boolean

Compares another time range for complete encapsulation. A time range is considered encapsulated if it begins and ends within this one, including if the ranges match exactly.

Parameters:

  • time_range (TimeRange)

    time range to compare for encapsulation

Returns:

  • (Boolean)

    whether the target range is encapsulated

Raises:

  • (TypeError)

Since:

  • 0.0.1



83
84
85
86
87
# File 'lib/time_range.rb', line 83

def encapsulates?(time_range)
  raise TypeError unless time_range.is_a?(TimeRange)

  self.begin <= time_range.begin && max >= time_range.max
end

#maxTime

Reimplementation of Range#max. TimeRange makes one assumption; that ranges excluding end should be one second shorter than those that don’t.

Normal Ranges simply TypeError when excluding_end is true. However, since Ruby’s Time methods assume seconds anyway, it is reasonable to use seconds here.

Doing so enables the implementation of a number of useful TimeRange methods.

Returns:

  • (Time)

    the highest time included in the range

Since:

  • 0.0.1



52
53
54
55
56
# File 'lib/time_range.rb', line 52

def max
  return self.end - 1 if exclude_end?

  super
end

#overlap_with(time_range) ⇒ TimeRange?

Returns the overlap between this and the argument as a new time range.

Parameters:

  • time_range (TimeRange)

    time range to compare for encapsulation

Returns:

  • (TimeRange, nil)

    the overlap in a TimeRange or nil if none occurs

Raises:

  • (TypeError)

Since:

  • 0.0.1



104
105
106
107
108
109
110
111
# File 'lib/time_range.rb', line 104

def overlap_with(time_range)
  raise TypeError unless time_range.is_a?(TimeRange)

  self.class.new(
    [self.begin, time_range.begin].max,
    [max, time_range.max].min
  ) if overlaps?(time_range)
end

#overlaps?(time_range) ⇒ Boolean

Compares another time range for any kind of overlap; partial or complete.

Parameters:

  • time_range (TimeRange)

    time range to compare for overlap

Returns:

  • (Boolean)

    whether contents of two TimeRanges overlap

Raises:

  • (TypeError)

Since:

  • 0.0.1



69
70
71
72
73
74
75
# File 'lib/time_range.rb', line 69

def overlaps?(time_range)
  raise TypeError unless time_range.is_a?(TimeRange)

  %w(begins_within? ends_within? encapsulates?).any? do |condition|
    send(condition, time_range)
  end
end