1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
module IceCube
class WeeklyRule < ValidatedRule
include Validations::HourOfDay
include Validations::MinuteOfHour
include Validations::SecondOfMinute
# include Validations::DayOfMonth # n/a
include Validations::DayOfWeek
include Validations::Day
include Validations::MonthOfYear
# include Validations::DayOfYear # n/a
include Validations::WeeklyInterval
attr_reader :week_start
def initialize(interval = 1, week_start = :sunday)
super(interval)
interval(interval, week_start)
schedule_lock(:wday, :hour, :min, :sec)
reset
end
# Move the effective start time to correct for when the schedule has
# validations earlier in the week than the selected start time, e.g.
#
# Schedule.new(wednesday).weekly(2).day(:monday)
#
# The effective start time gets realigned to the second next Monday, jumping
# over the gap week for the interval (2). Without realignment, the correct
# Monday occurrence would be missed when the schedule performs a 7-day jump
# into the next interval week, arriving on the Wednesday. This corrects any
# selections from dates that are misaligned to the schedule interval.
#
def realign(step_time, start_time)
time = TimeUtil::TimeWrapper.new(start_time)
offset = wday_offset(step_time, start_time)
time.add(:day, offset)
super step_time, time.to_time
end
# Calculate how many days to the first wday validation in the correct
# interval week. This may move backwards within the week if starting in an
# interval week with earlier validations.
#
def wday_offset(step_time, start_time)
return 0 if step_time == start_time
wday_validations = other_interval_validations.select { |v| v.type == :wday }
return 0 if wday_validations.none?
days = step_time.to_date - start_time.to_date
interval = base_interval_validation.validate(step_time, start_time).to_i
min_wday = wday_validations.map { |v| TimeUtil.normalize_wday(v.day, week_start) }.min
step_wday = TimeUtil.normalize_wday(step_time.wday, week_start)
days + interval - step_wday + min_wday
end
end
end
|