Methods
Constants
LeapYearMonthDays = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
CommonYearMonthDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Attributes
[R] cron_expr
[R] day
[R] hour
[R] min
[R] month
[R] sec
[R] wday
[R] year
Public Class methods
new(expr)
   # File server/cron_trigger.rb, line 6
6:     def initialize(expr)
7:       self.cron_expr = expr
8:     end
Public Instance methods
cron_expr=(expr)
    # File server/cron_trigger.rb, line 10
10:     def cron_expr=(expr)
11:       @cron_expr = expr
12:       self.sec, self.min, self.hour, self.day, self.month, self.wday, self.year = @cron_expr.split(' ')
13:       # puts inspect
14:     end
day=(day)
     # File server/cron_trigger.rb, line 184
184:     def day=(day)
185:       @day = parse_part(day, 1 .. 31)
186:     end
day_restricted?()
     # File server/cron_trigger.rb, line 163
163:     def day_restricted?
164:       return !@day.eql?(1..31)
165:     end
fire_time_after(time)
     # File server/cron_trigger.rb, line 16
 16:     def fire_time_after(time)
 17:       sec, min, hour, day, month, year, wday, yday, isdst, zone = time.to_a
 18: 
 19:       loop do
 20:         # year
 21:         unless @year.nil? or @year.include?(year)
 22:           return nil  if year > @year.max
 23:           year = @year.detect do |y| y > year end  # next allowable year
 24:         end
 25: 
 26:         # month
 27:         unless @month.include?(month)
 28:           # next allowable month
 29:           next_month = @month.detect(lambda { @month.min }) do |m| m > month end
 30:           # reset everything lower
 31:           day, hour, min, sec = @day.min, @hour.min, @min.min, @sec.min
 32:           # carry case
 33:           if next_month < month
 34:             month = next_month
 35:             year += 1
 36:             retry
 37:           end
 38:           month = next_month
 39:         end
 40: 
 41:         # according to crontab(5):
 42:         # Note: The day of a command’s execution can be specified by two fields — day of month, and day of week.
 43:         # If both fields are restricted (i.e., aren’t *), the command  will  be  run  when  either
 44:         # field matches the current time.  For example, ‘‘30 4 1,15 * 5’’ would cause a command to be
 45:         # run at 4:30 am on the 1st and 15th of each month, plus every Friday.
 46:         if !day_restricted? and wday_restricted?
 47:           # unrestricted day, restricted wday. go by wday
 48:           unless @wday.include?(wday)
 49:             next_wday = @wday.detect(lambda { @wday.min }) do |w| w > wday end
 50:             hour, min, sec = @hour.min, @min.min, @sec.min
 51:             if next_wday < wday
 52:               # next week.
 53:               day += + 7 - (wday - next_wday)
 54:               if day > month_days(year, month)
 55:                 day -= month_days(year, month)
 56:                 month += 1
 57:               end
 58:               wday = next_wday              
 59:               retry
 60:             end
 61:             
 62:             day += (next_wday - wday)
 63:             wday = next_wday
 64:           end
 65:         elsif !wday_restricted? and day_restricted?
 66:           # unrestricted wday, restricted day. go by day
 67:           month_days = (1 .. month_days(year, month))
 68:           days = @day.select do |d| month_days === d end
 69:           unless days.include?(day)
 70:             next_day = days.detect(lambda { days.min }) do |d| d > day end
 71:             hour, min, sec = @hour.min, @min.min, @sec.min
 72:             if next_day.nil? or next_day < day
 73:               day = next_day.nil? ? @day.min : next_day
 74:               month += 1
 75:               retry
 76:             end
 77:             day = next_day
 78:           end
 79:         else        
 80:           # both @day and @wday are restricted, or unrestricted
 81:           month_days = (1 .. month_days(year, month))
 82:           days = @day.select do |d| month_days === d end
 83:           unless days.include?(day) || @wday.include?(wday)
 84:             next_day = days.detect(lambda { days.min }) do |d| d > day end
 85:             next_wday = @wday.detect(lambda { @wday.min }) do |w| w > wday end
 86:             hour, min, sec = @hour.min, @min.min, @sec.min
 87:             
 88:             # which is less? next_day or next_wday?
 89:             # just calculate how many days from 'day' they both are.
 90: 
 91:             if next_day.nil? or next_day < day
 92:               next_by_mday = month_days(year, month) - day + (next_day.nil? ? @day.min : next_day)
 93:             else
 94:               next_by_mday = next_day - day              
 95:             end
 96:             
 97:             if next_wday.nil? or next_wday < wday
 98:               next_by_wday = 7 - wday + (next_wday.nil? ? @day.min : next_wday)
 99:             else
100:               next_by_wday = next_wday - wday
101:             end
102:             
103:             next_day = [next_by_wday, next_by_mday].min
104:             if next_day + day > month_days(year, month)
105:               # next fire lands on next month
106:               day += next_day - month_days(year, month)
107:               wday += next_day % 7
108:               wday -= 7 if wday > 6
109:               month += 1
110:               if month > 12
111:                 year += 1
112:                 month = 1
113:               end
114:               retry
115:             end
116:             day += next_day
117:           end
118:         end
119: 
120:         
121:         
122:         # hour
123:         unless @hour.include?(hour)
124:           next_hour = @hour.detect(lambda { @hour.min }) do |h| h > hour end
125:           min, sec = @min.min, @sec.min
126:           if next_hour < hour
127:             hour = next_hour
128:             day += 1
129:             retry
130:           end
131:           hour = next_hour
132:         end
133: 
134:         # min
135:         unless @min.include?(min)
136:           next_min = @min.detect(lambda { @min.min }) do |m| m > min end
137:           sec = @sec.min
138:           if next_min < min
139:             min = next_min
140:             hour += 1
141:             retry
142:           end
143:           min = next_min
144:         end
145: 
146:         # sec
147:         unless @sec.include?(sec)
148:           next_sec = @sec.detect(lambda { @sec.min }) do |s| s > sec end
149:           if next_sec < sec
150:             sec = next_sec
151:             min += 1
152:             retry
153:           end
154:           sec = next_sec
155:         end
156: 
157:         break
158:       end
159: 
160:       Time.local sec, min, hour, day, month, year, wday, yday, isdst, zone
161:     end
hour=(hour)
     # File server/cron_trigger.rb, line 180
180:     def hour=(hour)
181:       @hour = parse_part(hour, 0 .. 23)
182:     end
min=(min)
     # File server/cron_trigger.rb, line 176
176:     def min=(min)
177:       @min = parse_part(min, 0 .. 59)
178:     end
month=(month)
     # File server/cron_trigger.rb, line 188
188:     def month=(month)
189:       @month = parse_part(month, 1 .. 12)
190:     end
sec=(sec)

TODO: mimic attr_reader to define all of these

     # File server/cron_trigger.rb, line 172
172:     def sec=(sec)
173:       @sec = parse_part(sec, 0 .. 59)
174:     end
wday=(wday)
     # File server/cron_trigger.rb, line 196
196:     def wday=(wday)
197:       @wday = parse_part(wday, 0 .. 6)
198:     end
wday_restricted?()
     # File server/cron_trigger.rb, line 167
167:     def wday_restricted?
168:       return !@wday.eql?(0..6)
169:     end
year=(year)
     # File server/cron_trigger.rb, line 192
192:     def year=(year)
193:       @year = parse_part(year)
194:     end