Module: ActsAsBookable::TimeUtils
- Defined in:
- lib/acts_as_bookable/time_utils.rb
Overview
Provide helper functions to manage operations and queries related to times and schedules
Class Method Summary collapse
-
.interval_in_schedule?(schedule, interval_start, interval_end) ⇒ Boolean
Check if there is an occurrence of a schedule that contains a time interval.
-
.subintervals(intervals, &block) ⇒ Object
Returns an array of sub-intervals given another array of intervals, which are the overlapping insersections of each-others.
-
.time_in_interval?(time, interval_start, interval_end) ⇒ Boolean
Check if time is included in a time interval.
-
.time_in_schedule?(schedule, time) ⇒ Boolean
Check if there is an occurrence of a schedule that contains a time.
Class Method Details
.interval_in_schedule?(schedule, interval_start, interval_end) ⇒ Boolean
Check if there is an occurrence of a schedule that contains a time interval
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/acts_as_bookable/time_utils.rb', line 27 def interval_in_schedule?(schedule, interval_start, interval_end) # Check if interval_start and interval_end falls within any occurrence return false if(!time_in_schedule?(schedule,interval_start) || !time_in_schedule?(schedule,interval_end)) # Check if both interval_start and interval_end falls within the SAME occurrence between = schedule.occurrences_between(interval_start, interval_end, true) contains = false between.each do |oc| oc_end = oc + schedule.duration contains = true if (time_in_interval?(interval_start,oc,oc_end) && time_in_interval?(interval_end,oc,oc_end)) break if contains end contains end |
.subintervals(intervals, &block) ⇒ Object
Returns an array of sub-intervals given another array of intervals, which are the overlapping insersections of each-others.
An interval is defined as a hash with at least the following fields: ‘time_from` and `time_end`. An interval may contain more fields. In that case, it’s suggested to give a block with the instructions to correctly merge two intervals when needed.
e.g: given these 7 intervals
|------| |---| |----------|
|---| |--|
|------| |--| |-------------|
the output is an array containing these 8 intervals:
|--| |--| |---| |--| |---| |------|
|---| |------|
the number of subintervals may increase or decrease because some intervals may be split, while
some others may be merged.
If a block is given, it’s called before merging two intervals. The block should provide instructions to merge intervals, and should return the merged fields in a hash
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/acts_as_bookable/time_utils.rb', line 73 def subintervals(intervals, &block) raise ArgumentError.new('intervals must be an array') unless intervals.is_a? Array steps = [] # Steps will be extracted from intervals subintervals = [] # The output last_time = nil last_attrs = nil started_count = 0 # The number of intervals opened inside the cycle # Extract start times and end times from intervals, and create steps intervals.each do |el| begin ts = el[:time_start].to_time te = el[:time_end].to_time rescue NoMethodError raise ArgumentError.new('intervals must define :time_start and :time_end as Time or Date') end attrs = el.clone attrs.delete(:time_start) attrs.delete(:time_end) steps << { opening: 1, time: el[:time_start], attrs: attrs } # Start step steps << { opening: -1, time: el[:time_end], attrs: attrs.clone } # End step end # Sort steps by time (and opening if time is the same) steps.sort! do |a,b| diff = a[:time] <=> b[:time] diff = a[:opening] <=> b[:opening] if (diff == 0) diff end # Iterate over steps steps.each do |step| if (started_count == 0) last_time = step[:time] last_attrs = step[:attrs] else if(step[:time] > last_time) subintervals << ({ time_start: last_time, time_end: step[:time] }.merge(last_attrs)) last_time = step[:time] end if block_given? last_attrs = block.call(last_attrs.clone, step[:attrs],(step[:opening] == 1 ? :open : :close)) else last_attrs = step[:attrs] end end # Update started_count started_count += step[:opening] end subintervals end |
.time_in_interval?(time, interval_start, interval_end) ⇒ Boolean
Check if time is included in a time interval. The ending time is excluded
15 16 17 |
# File 'lib/acts_as_bookable/time_utils.rb', line 15 def time_in_interval? (time, interval_start, interval_end) time >= interval_start && time < interval_end end |
.time_in_schedule?(schedule, time) ⇒ Boolean
Check if there is an occurrence of a schedule that contains a time
49 50 51 |
# File 'lib/acts_as_bookable/time_utils.rb', line 49 def time_in_schedule?(schedule, time) return schedule.occurring_at? time end |