lib/rufus/sc/cronline.rb in rufus-scheduler-2.0.8 vs lib/rufus/sc/cronline.rb in rufus-scheduler-2.0.9
- old
+ new
@@ -41,10 +41,11 @@
attr_reader :minutes
attr_reader :hours
attr_reader :days
attr_reader :months
attr_reader :weekdays
+ attr_reader :monthdays
attr_reader :timezone
def initialize(line)
super()
@@ -65,11 +66,11 @@
@seconds = offset == 1 ? parse_item(items[0], 0, 59) : [ 0 ]
@minutes = parse_item(items[0 + offset], 0, 59)
@hours = parse_item(items[1 + offset], 0, 24)
@days = parse_item(items[2 + offset], 1, 31)
@months = parse_item(items[3 + offset], 1, 12)
- @weekdays = parse_weekdays(items[4 + offset])
+ @weekdays, @monthdays = parse_weekdays(items[4 + offset])
end
# Returns true if the given time matches this cron line.
#
def matches?(time)
@@ -79,13 +80,11 @@
time = @timezone.utc_to_local(time.getutc) if @timezone
return false unless sub_match?(time.sec, @seconds)
return false unless sub_match?(time.min, @minutes)
return false unless sub_match?(time.hour, @hours)
- return false unless sub_match?(time.day, @days)
- return false unless sub_match?(time.month, @months)
- return false unless sub_match?(time.wday, @weekdays)
+ return false unless date_match?(time)
true
end
# Returns the next time that this cron line is supposed to 'fire'
#
@@ -162,30 +161,51 @@
@minutes,
@hours,
@days,
@months,
@weekdays,
+ @monthdays,
@timezone ? @timezone.name : nil
]
end
private
- WDS = %w[ sun mon tue wed thu fri sat ]
- # used by parse_weekday()
+ WEEKDAYS = %w[ sun mon tue wed thu fri sat ]
def parse_weekdays(item)
- item = item.downcase
+ return nil if item == '*'
- WDS.each_with_index { |day, index| item = item.gsub(day, index.to_s) }
+ items = item.downcase.split(',')
- r = parse_item(item, 0, 7)
+ weekdays = nil
+ monthdays = nil
- r.is_a?(Array) ?
- r.collect { |e| e == 7 ? 0 : e }.uniq :
- r
+ items.each do |it|
+
+ if it.match(/#[12345]$/)
+
+ raise ArgumentError.new(
+ "ranges are not supported for monthdays (#{it})"
+ ) if it.index('-')
+
+ (monthdays ||= []) << it
+ else
+
+ WEEKDAYS.each_with_index { |a, i| it.gsub!(/#{a}/, i.to_s) }
+
+ its = it.index('-') ? parse_range(it, 0, 7) : [ Integer(it) ]
+ its = its.collect { |i| i == 7 ? 0 : i }
+
+ (weekdays ||= []).concat(its)
+ end
+ end
+
+ weekdays = weekdays.uniq if weekdays
+
+ [ weekdays, monthdays ]
end
def parse_item(item, min, max)
return nil if item == '*'
@@ -253,15 +273,38 @@
def sub_match?(value, values)
values.nil? || values.include?(value)
end
+ def monthday_match(monthday, monthdays)
+
+ return true if monthdays == nil
+ return true if monthdays.include?(monthday)
+ end
+
def date_match?(date)
return false unless sub_match?(date.day, @days)
return false unless sub_match?(date.month, @months)
return false unless sub_match?(date.wday, @weekdays)
+ return false unless sub_match?(CronLine.monthday(date), @monthdays)
true
+ end
+
+ DAY_IN_SECONDS = 7 * 24 * 3600
+
+ def self.monthday(date)
+
+ count = 1
+ date2 = date.dup
+
+ loop do
+ date2 = date2 - DAY_IN_SECONDS
+ break if date2.month != date.month
+ count = count + 1
+ end
+
+ "#{WEEKDAYS[date.wday]}##{count}"
end
end
end