-
Notifications
You must be signed in to change notification settings - Fork 359
Excluding times from schedules
avit edited this page Nov 7, 2014
·
1 revision
IceCube (and the iCalendar spec) provides only a simple way to exclude individual times from a schedule:
schedule.add_exception_time(Time.new(2014, 11, 6, 17, 0, 0))
These exception times must line up with the schedule exactly, which is workable for simple cases, but sometimes a different approach is needed.
If exclusions need to cover a range of time, a more flexible approach could be to store these ranges outside of the schedule itself. Here is an example using a "Vacation" class to store days off and compare them against the schedule:
# A dummy class
Vacation = Struct.new(:first, :last) do
# Convert dates to a range of times based on the schedule's local time
def range(schedule)
Range.new(
IceCube::TimeUtil.beginning_of_date(first, schedule.start_time),
IceCube::TimeUtil.end_of_date(last, schedule.start_time)
)
end
# emulating an ActiveRecord scope:
def self.occurring_between(a, z)
all.select { |v| v.first <= z && v.last >= a }
end
end
# emulating some ActiveRecord data:
def Vacation.all
[
new(Date.new(2010, 1, 1), Date.new(2010, 3, 1)),
new(Date.new(2014, 11, 6), Date.new(2014, 11, 12)),
new(Date.new(2014, 12, 25), Date.new(2015, 1, 2))
]
end
Given that we have a daily schedule and need the occurrences between these two dates:
a = Date.new(2014, 11, 6)
z = Date.new(2015, 1, 6)
schedule = IceCube::Schedule.new { |s| s.rrule(IceCube::Rule.daily) }
We can then fetch all the occurrences and reject the ones within the vacation ranges independently:
vacations = Vacation.occurring_between(a, z)
occurrences = schedule.occurrences_between(a, z).keep_if { |t|
vacations.none? { |vac| vac.range(schedule).cover?(t) }
}