File: weekly_rule.rb

package info (click to toggle)
ruby-ice-cube 0.16.4-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 800 kB
  • sloc: ruby: 7,823; makefile: 6
file content (63 lines) | stat: -rw-r--r-- 2,215 bytes parent folder | download | duplicates (2)
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