Class: TimeIntervals::Collection
- Inherits:
-
Object
- Object
- TimeIntervals::Collection
- Extended by:
- Forwardable
- Includes:
- Enumerable
- Defined in:
- lib/time_intervals/collection.rb
Constant Summary collapse
- ONE_HOUR_IN_SECONDS =
60 * 60
Instance Attribute Summary collapse
-
#time_intervals ⇒ Object
readonly
Returns the value of attribute time_intervals.
Class Method Summary collapse
Instance Method Summary collapse
- #==(other) ⇒ Object (also: #eql?)
-
#all_intervals_within?(bounding_interval) ⇒ Boolean
Returns true if all of the contained TimeIntervals::Intervals are wholly contained within the bounding interval.
-
#coalesce ⇒ Object
Returns a new coalesced collection of TimeIntervals::Intervals where any that overlap or are adjacent are combined into a single TimeIntervals::Interval.
-
#has_overlapping_intervals? ⇒ Boolean
Returns true if any of the contained TimeIntervals::Intervals overlap.
-
#initialize(time_intervals = []) ⇒ Collection
constructor
A new instance of Collection.
-
#intersect(intersections) ⇒ Object
Returns a new collection of TimeIntervals::Intervals that contains only intersections with the specified intersections: either a nil, a single TimeIntervals::Interval, or a TimeIntervals::Collection.
-
#intersect_count(intersections) ⇒ Object
Counts the number of TimeIntervals::Intervals that intersect with the given collection of TimeIntervals::Intervals.
-
#length_in_hours ⇒ Object
The sum of the lengths of the TimeIntervals::Intervals in the collection as hours.
-
#length_in_seconds ⇒ Object
The sum of the lengths of the TimeIntervals::Intervals in the collection as seconds.
-
#partition ⇒ Object
Returns a new collection of TimeIntervals::Intervals that are partitions of the original collection.
- #partition_count ⇒ Object
Constructor Details
#initialize(time_intervals = []) ⇒ Collection
22 23 24 |
# File 'lib/time_intervals/collection.rb', line 22 def initialize(time_intervals = []) @time_intervals = Array(time_intervals).sort end |
Instance Attribute Details
#time_intervals ⇒ Object (readonly)
Returns the value of attribute time_intervals.
15 16 17 |
# File 'lib/time_intervals/collection.rb', line 15 def time_intervals @time_intervals end |
Class Method Details
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
155 156 157 |
# File 'lib/time_intervals/collection.rb', line 155 def ==(other) other.class == self.class && other.time_intervals == time_intervals end |
#all_intervals_within?(bounding_interval) ⇒ Boolean
Returns true if all of the contained TimeIntervals::Intervals are wholly contained within the bounding interval.
28 29 30 |
# File 'lib/time_intervals/collection.rb', line 28 def all_intervals_within?(bounding_interval) length_in_seconds == intersect(bounding_interval).length_in_seconds end |
#coalesce ⇒ Object
Returns a new coalesced collection of TimeIntervals::Intervals where any that overlap or are adjacent are combined into a single TimeIntervals::Interval.
Given these TimeIntervals::Intervals in the collection:
[——–)
[------)
[-----) [-------)
[-------)
Calling #coalesce returns a TimeIntervals::Collection containing these TimeIntervals::Intervals:
[——————) [————)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/time_intervals/collection.rb', line 52 def coalesce return self if empty? coalescing = Interval.create(first) result = each_with_object([]) do |current, memo| if coalescing.ended_at < current.started_at memo << coalescing coalescing = Interval.create(current) else coalescing = Interval.new( coalescing.started_at, [coalescing.ended_at, current.ended_at].max ) end end result << Interval.create(coalescing) Collection.new(result) end |
#has_overlapping_intervals? ⇒ Boolean
Returns true if any of the contained TimeIntervals::Intervals overlap.
33 34 35 |
# File 'lib/time_intervals/collection.rb', line 33 def has_overlapping_intervals? length_in_seconds != coalesce.length_in_seconds end |
#intersect(intersections) ⇒ Object
Returns a new collection of TimeIntervals::Intervals that contains only intersections with the specified intersections: either a nil, a single TimeIntervals::Interval, or a TimeIntervals::Collection.
Note: the intersections are assumed to be disjoint. That is, none of the TimeIntervals::Intervals in intersections overlap.
Given these TimeIntervals::Intervals in the collection:
[——–)
[------)
[-----) [-------)
[-------)
Calling #intersect with these TimeIntervals::Intervals
[--------------) [------)
returns a TimeIntervals::Collection containing these TimeIntervals::Intervals:
[--)
[-----) [-) [---)
[-----)
98 99 100 101 102 103 104 |
# File 'lib/time_intervals/collection.rb', line 98 def intersect(intersections) result = Array(intersections).each_with_object([]) do |intersection, memo| memo.concat(intersect_with_time_interval(intersection)) end Collection.new(result) end |
#intersect_count(intersections) ⇒ Object
Counts the number of TimeIntervals::Intervals that intersect with the given collection of TimeIntervals::Intervals.
Returns a list of [TimeIntervals::Interval, count] tuples. The TimeIntervals::Intervals in the result are the TimeIntervals::Intervals from the argument.
138 139 140 141 |
# File 'lib/time_intervals/collection.rb', line 138 def intersect_count(intersections) counts = intersections.map { |slice| intersect_with_time_interval(slice).length } intersections.zip(counts) end |
#length_in_hours ⇒ Object
The sum of the lengths of the TimeIntervals::Intervals in the collection as hours.
145 146 147 |
# File 'lib/time_intervals/collection.rb', line 145 def length_in_hours length_in_seconds.to_f / ONE_HOUR_IN_SECONDS end |
#length_in_seconds ⇒ Object
The sum of the lengths of the TimeIntervals::Intervals in the collection as seconds.
151 152 153 |
# File 'lib/time_intervals/collection.rb', line 151 def length_in_seconds time_intervals.reduce(0) { |total, time_intervals| total + time_intervals.length_in_seconds } end |
#partition ⇒ Object
Returns a new collection of TimeIntervals::Intervals that are partitions of the original collection.
Given the upper TimeIntervals::Intervals, #partition returns the lower TimeIntervals::Intervals:
[——–) [—–) [—) | [——) | | | | | | [—-) | | | | | | | | | | | | | | | | | | | | | [—–) [-) [–) [—) |
[--) [-) [--) [---)
125 126 127 128 129 130 131 |
# File 'lib/time_intervals/collection.rb', line 125 def partition time_points = @time_intervals.flat_map { |i| [i.started_at, i.ended_at] }.uniq.sort start_time_points = time_points[0..-2] end_time_points = time_points[1..-1] raw_intervals = start_time_points.zip(end_time_points) Collection.new(raw_intervals.map { |r| Interval.new(*r) }) end |
#partition_count ⇒ Object
106 107 108 109 110 |
# File 'lib/time_intervals/collection.rb', line 106 def partition_count partition_intervals = partition intersect_count(partition_intervals) end |