class IceCube::Schedule
Attributes
Get the end time
Get the start time
Public Class Methods
Source
# File lib/ice_cube/schedule.rb, line 399 def self.dump(schedule) return schedule if schedule.nil? || schedule == "" schedule.to_yaml end
Source
# File lib/ice_cube/schedule.rb, line 373 def self.from_hash(original_hash, options = {}) HashParser.new(original_hash).to_schedule do |schedule| Deprecated.schedule_options(schedule, options) yield schedule if block_given? end end
Load the schedule from a hash
Source
# File lib/ice_cube/schedule.rb, line 337 def self.from_ical(ical, options = {}) IcalParser.schedule_from_ical(ical, options) end
Load the schedule from ical
Source
# File lib/ice_cube/schedule.rb, line 347 def self.from_yaml(yaml, options = {}) YamlParser.new(yaml).to_schedule do |schedule| Deprecated.schedule_options(schedule, options) yield schedule if block_given? end end
Load the schedule from yaml
Source
# File lib/ice_cube/schedule.rb, line 404 def self.load(yaml) return yaml if yaml.nil? || yaml == "" from_yaml(yaml) end
Source
# File lib/ice_cube/schedule.rb, line 16 def initialize(start_time = nil, options = {}) self.start_time = start_time || TimeUtil.now self.end_time = self.start_time + options[:duration] if options[:duration] self.end_time = options[:end_time] if options[:end_time] @all_recurrence_rules = [] @all_exception_rules = [] yield self if block_given? end
Create a new schedule
Public Instance Methods
Source
# File lib/ice_cube/schedule.rb, line 81 def add_exception_rule(rule) return if rule.nil? @all_exception_rules << rule unless @all_exception_rules.include?(rule) end
Add an exception rule to the schedule
Source
# File lib/ice_cube/schedule.rb, line 57 def add_exception_time(time) return if time.nil? rule = SingleOccurrenceRule.new(time) add_exception_rule rule time end
Add an exception time to the schedule
Source
# File lib/ice_cube/schedule.rb, line 68 def add_recurrence_rule(rule) return if rule.nil? @all_recurrence_rules << rule unless @all_recurrence_rules.include?(rule) end
Add a recurrence rule to the schedule
Source
# File lib/ice_cube/schedule.rb, line 46 def add_recurrence_time(time) return if time.nil? rule = SingleOccurrenceRule.new(time) add_recurrence_rule rule time end
Add a recurrence time to the schedule
Source
# File lib/ice_cube/schedule.rb, line 152 def all_occurrences require_terminating_rules enumerate_occurrences(start_time).to_a end
All of the occurrences
Source
# File lib/ice_cube/schedule.rb, line 158 def all_occurrences_enumerator enumerate_occurrences(start_time) end
Emit an enumerator based on the start time
Source
# File lib/ice_cube/schedule.rb, line 255 def conflicts_with?(other_schedule, closing_time = nil) closing_time = TimeUtil.ensure_time(closing_time) unless terminating? || other_schedule.terminating? || closing_time raise ArgumentError, "One or both schedules must be terminating to use #conflicts_with?" end # Pick the terminating schedule, and other schedule # No need to reverse if terminating? or there is a closing time terminating_schedule = self unless terminating? || closing_time terminating_schedule, other_schedule = other_schedule, terminating_schedule end # Go through each occurrence of the terminating schedule and determine # if the other occurs at that time # last_time = nil terminating_schedule.each_occurrence do |time| if closing_time && time > closing_time last_time = closing_time break end last_time = time return true if other_schedule.occurring_at?(time) end # Due to durations, we need to walk up to the end time, and verify in the # other direction if last_time last_time += terminating_schedule.duration other_schedule.each_occurrence do |time| break if time > last_time return true if terminating_schedule.occurring_at?(time) end end # No conflict, return false false end
Determine if this schedule conflicts with another schedule @param [IceCube::Schedule] other_schedule - The schedule to compare to @param [Time] closing_time - the last time to consider @return [Boolean] whether or not the schedules conflict at all
Source
# File lib/ice_cube/schedule.rb, line 37 def duration end_time ? end_time - start_time : 0 end
Source
# File lib/ice_cube/schedule.rb, line 41 def duration=(seconds) @end_time = start_time + seconds end
Source
# File lib/ice_cube/schedule.rb, line 163 def each_occurrence(&) enumerate_occurrences(start_time, &).to_a self end
Iterate forever
Source
# File lib/ice_cube/schedule.rb, line 342 def encode_with(coder) coder.represent_object nil, to_hash end
Hook for YAML.dump, enables to_yaml
Source
# File lib/ice_cube/schedule.rb, line 32 def end_time=(end_time) @end_time = TimeUtil.ensure_time end_time end
Set end_time
Source
# File lib/ice_cube/schedule.rb, line 394 def eql?(other) hash == other.hash end
Source
# File lib/ice_cube/schedule.rb, line 100 def exception_rules @all_exception_rules.reject { |r| r.is_a?(SingleOccurrenceRule) } end
Get the exception rules
Source
# File lib/ice_cube/schedule.rb, line 126 def exception_times @all_exception_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time) end
Get the exception times that are on the schedule
Source
# File lib/ice_cube/schedule.rb, line 297 def first(n = nil) occurrences = enumerate_occurrences(start_time).take(n || 1) n.nil? ? occurrences.first : occurrences end
Get the first n occurrences, or the first occurrence if n is skipped
Source
# File lib/ice_cube/schedule.rb, line 386 def hash [ TimeUtil.hash(start_time), duration, *@all_recurrence_rules.map(&:hash).sort!, *@all_exception_rules.map(&:hash).sort! ].hash end
Source
# File lib/ice_cube/schedule.rb, line 304 def last(n = nil) require_terminating_rules occurrences = enumerate_occurrences(start_time).to_a n.nil? ? occurrences.last : occurrences[-n..] end
Get the final n occurrences of a terminating schedule or the final one if no n is given
Source
# File lib/ice_cube/schedule.rb, line 175 def next_occurrence(from = nil, options = {}) from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time) enumerate_occurrences(from + 1, nil, options).next rescue StopIteration nil end
The next occurrence after now (overridable)
Source
# File lib/ice_cube/schedule.rb, line 169 def next_occurrences(num, from = nil, options = {}) from = TimeUtil.match_zone(from, start_time) || TimeUtil.now(start_time) enumerate_occurrences(from + 1, nil, options).take(num) end
The next n occurrences after now
Source
# File lib/ice_cube/schedule.rb, line 147 def occurrences(closing_time) enumerate_occurrences(start_time, closing_time).to_a end
Get all of the occurrences from the start_time
up until a given Time
Source
# File lib/ice_cube/schedule.rb, line 211 def occurrences_between(begin_time, closing_time, options = {}) enumerate_occurrences(begin_time, closing_time, options).to_a end
Occurrences between two times
Source
# File lib/ice_cube/schedule.rb, line 241 def occurring_at?(time) time = TimeUtil.match_zone(time, start_time) or raise ArgumentError, "Time required, got #{time.inspect}" if duration > 0 return false if exception_time?(time) occurs_between?(time - duration + 1, time) else occurs_at?(time) end end
Determine if the schedule is occurring at a given time
Source
# File lib/ice_cube/schedule.rb, line 228 def occurring_between?(opening_time, closing_time) occurs_between?(opening_time, closing_time, spans: true) end
Return a boolean indicating if an occurrence is occurring between two times, inclusive of its duration. This counts zero-length occurrences that intersect the start of the range and within the range, but not occurrences at the end of the range since none of their duration intersects the range.
Source
# File lib/ice_cube/schedule.rb, line 292 def occurs_at?(time) occurs_between?(time, time) end
Determine if the schedule occurs at a specific time
Source
# File lib/ice_cube/schedule.rb, line 216 def occurs_between?(begin_time, closing_time, options = {}) enumerate_occurrences(begin_time, closing_time, options).next true rescue StopIteration false end
Return a boolean indicating if an occurrence falls between two times
Source
# File lib/ice_cube/schedule.rb, line 233 def occurs_on?(date) date = TimeUtil.ensure_date(date) begin_time = TimeUtil.beginning_of_date(date, start_time) closing_time = TimeUtil.end_of_date(date, start_time) occurs_between?(begin_time, closing_time) end
Return a boolean indicating if an occurrence falls on a certain date
Source
# File lib/ice_cube/schedule.rb, line 183 def previous_occurrence(from) from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}" return nil if from <= start_time enumerate_occurrences(start_time, from - 1).to_a.last end
The previous occurrence from a given time
Source
# File lib/ice_cube/schedule.rb, line 190 def previous_occurrences(num, from) from = TimeUtil.match_zone(from, start_time) or raise ArgumentError, "Time required, got #{from.inspect}" return [] if from <= start_time a = enumerate_occurrences(start_time, from - 1).to_a (a.size > num) ? a[-1 * num, a.size] : a end
The previous n occurrences before a given time
Source
# File lib/ice_cube/schedule.rb, line 94 def recurrence_rules @all_recurrence_rules.reject { |r| r.is_a?(SingleOccurrenceRule) } end
Get the recurrence rules
Source
# File lib/ice_cube/schedule.rb, line 106 def recurrence_times @all_recurrence_rules.select { |r| r.is_a?(SingleOccurrenceRule) }.map(&:time) end
Get the recurrence times that are on the schedule
Source
# File lib/ice_cube/schedule.rb, line 198 def remaining_occurrences(from = nil, options = {}) require_terminating_rules from ||= TimeUtil.now(@start_time) enumerate_occurrences(from, nil, options).to_a end
The remaining occurrences (same requirements as all_occurrences
)
Source
# File lib/ice_cube/schedule.rb, line 205 def remaining_occurrences_enumerator(from = nil, options = {}) from ||= TimeUtil.now(@start_time) enumerate_occurrences(from, nil, options) end
Returns an enumerator for all remaining occurrences
Source
# File lib/ice_cube/schedule.rb, line 88 def remove_exception_rule(rule) res = @all_exception_rules.delete(rule) res.nil? ? [] : [res] end
Remove an exception rule
Source
# File lib/ice_cube/schedule.rb, line 134 def remove_exception_time(time) found = false @all_exception_rules.delete_if do |rule| found = true if rule.is_a?(SingleOccurrenceRule) && rule.time == time end time if found end
Remove an exception time
Source
# File lib/ice_cube/schedule.rb, line 75 def remove_recurrence_rule(rule) res = @all_recurrence_rules.delete(rule) res.nil? ? [] : [res] end
Remove a recurrence rule
Source
# File lib/ice_cube/schedule.rb, line 114 def remove_recurrence_time(time) found = false @all_recurrence_rules.delete_if do |rule| found = true if rule.is_a?(SingleOccurrenceRule) && rule.time == time end time if found end
Remove a recurrence time
Source
# File lib/ice_cube/schedule.rb, line 26 def start_time=(start_time) @start_time = TimeUtil.ensure_time start_time end
Set start_time
Source
# File lib/ice_cube/schedule.rb, line 382 def terminating? @all_recurrence_rules.all?(&:terminating?) end
Determine if the schedule will end @return [Boolean] true if ending, false if repeating forever
Source
# File lib/ice_cube/schedule.rb, line 355 def to_hash data = {} data[:start_time] = TimeUtil.serialize_time(start_time) data[:start_date] = data[:start_time] if IceCube.compatibility <= 11 data[:end_time] = TimeUtil.serialize_time(end_time) if end_time data[:rrules] = recurrence_rules.map(&:to_hash) data[:exrules] = exception_rules.map(&:to_hash) if exception_rules.any? data[:rtimes] = recurrence_times.map do |rt| TimeUtil.serialize_time(rt) end data[:extimes] = exception_times.map do |et| TimeUtil.serialize_time(et) end data end
Convert the schedule to a hash
Source
# File lib/ice_cube/schedule.rb, line 325 def to_ical(force_utc = false) pieces = [] pieces << "DTSTART#{IcalBuilder.ical_format(start_time, force_utc)}" pieces.concat recurrence_rules.map { |r| "RRULE:#{r.to_ical}" } pieces.concat exception_rules.map { |r| "EXRULE:#{r.to_ical}" } pieces.concat recurrence_times_without_start_time.map { |t| "RDATE#{IcalBuilder.ical_format(t, force_utc)}" } pieces.concat exception_times.map { |t| "EXDATE#{IcalBuilder.ical_format(t, force_utc)}" } pieces << "DTEND#{IcalBuilder.ical_format(end_time, force_utc)}" if end_time pieces.join("\n") end
Serialize this schedule to_ical
Source
# File lib/ice_cube/schedule.rb, line 311 def to_s pieces = [] rd = recurrence_times_with_start_time - extimes pieces.concat rd.sort.map { |t| IceCube::I18n.l(t, format: IceCube.to_s_time_format) } pieces.concat rrules.map { |t| t.to_s } pieces.concat exrules.map { |t| IceCube::I18n.t("ice_cube.not", target: t.to_s) } pieces.concat extimes.sort.map { |t| target = IceCube::I18n.l(t, format: IceCube.to_s_time_format) IceCube::I18n.t("ice_cube.not_on", target: target) } pieces.join(IceCube::I18n.t("ice_cube.pieces_connector")) end
String serialization
Private Instance Methods
Source
# File lib/ice_cube/schedule.rb, line 420 def enumerate_occurrences(opening_time, closing_time = nil, options = {}) opening_time = TimeUtil.match_zone(opening_time, start_time) closing_time = TimeUtil.match_zone(closing_time, start_time) opening_time += TimeUtil.subsec(start_time) - TimeUtil.subsec(opening_time) opening_time = start_time if opening_time < start_time spans = options[:spans] == true && duration != 0 Enumerator.new do |yielder| reset t1 = full_required? ? start_time : opening_time t1 -= duration if spans t1 = start_time if t1 < start_time loop do break unless (t0 = next_time(t1, closing_time)) break if closing_time && t0 > closing_time if spans ? (t0.end_time > opening_time) : (t0 >= opening_time) yielder << (block_given? ? yield(t0) : t0) end t1 = t0 + 1 end end end
Find all of the occurrences for the schedule between opening_time and closing_time Iteration is unrolled in pairs to skip duplicate times in end of DST
Source
# File lib/ice_cube/schedule.rb, line 466 def exception_time?(time) @all_exception_rules.any? do |rule| rule.on?(time, start_time) end end
Return a boolean indicating whether or not a specific time is excluded from the schedule
Source
# File lib/ice_cube/schedule.rb, line 459 def full_required? @all_recurrence_rules.any?(&:full_required?) || @all_exception_rules.any?(&:full_required?) end
Indicate if any rule needs to be run from the start of time If we have rules with counts, we need to walk from the beginning of time
Source
# File lib/ice_cube/schedule.rb, line 478 def implicit_start_occurrence_rule SingleOccurrenceRule.new(start_time) end
Source
# File lib/ice_cube/schedule.rb, line 443 def next_time(time, closing_time) loop do min_time = recurrence_rules_with_implicit_start_occurrence.reduce(nil) do |best_time, rule| new_time = rule.next_time(time, start_time, best_time || closing_time) [best_time, new_time].compact.min rescue StopIteration best_time end break unless min_time next (time = min_time + 1) if exception_time?(min_time) break Occurrence.new(min_time, min_time + duration) end end
Get the next time after (or including) a specific time
Source
# File lib/ice_cube/schedule.rb, line 494 def recurrence_rules_with_implicit_start_occurrence if recurrence_rules.empty? [implicit_start_occurrence_rule].concat @all_recurrence_rules else @all_recurrence_rules end end
Source
# File lib/ice_cube/schedule.rb, line 486 def recurrence_times_with_start_time if recurrence_rules.empty? [start_time].concat recurrence_times_without_start_time else recurrence_times end end
Source
# File lib/ice_cube/schedule.rb, line 482 def recurrence_times_without_start_time recurrence_times.reject { |t| t == start_time } end
Source
# File lib/ice_cube/schedule.rb, line 472 def require_terminating_rules return true if terminating? method_name = caller(1..1).first.split(" ").last raise ArgumentError, "All recurrence rules must specify .until or .count to use #{method_name}" end
Source
# File lib/ice_cube/schedule.rb, line 412 def reset @all_recurrence_rules.each(&:reset) @all_exception_rules.each(&:reset) end
Reset all rules for another run