class SayWhen::CronExpression

Based on the extended cron capabilties www.quartz-scheduler.org/documentation/quartz-2.2.x/tutorials/tutorial-lesson-06.html

Attributes

days_of_month[RW]
days_of_week[RW]
expression[R]
hours[RW]
minutes[RW]
months[RW]
seconds[RW]
time_zone[RW]
years[RW]

Public Class Methods

new(expression = {}, time_zone = nil) click to toggle source
# File lib/say_when/cron_expression.rb, line 12
def initialize(expression = {}, time_zone = nil)
  if expression.is_a?(Hash)
    opts = expression

    @expression = if opts[:expression]
      opts[:expression]
    else
      [:days_of_month, :days_of_week].each do |f|
        opts[f] ||= '?'
      end

      [:seconds, :minutes, :hours, :days_of_month, :months, :days_of_week, :years].each do |f|
        opts[f] ||= '*'
      end

      "#{opts[:seconds]} #{opts[:minutes]} #{opts[:hours]} #{opts[:days_of_month]} #{opts[:months]} #{opts[:days_of_week]} #{opts[:years]}"
    end

    @time_zone = opts[:time_zone]
  else
    @expression = expression
  end

  @time_zone ||= time_zone
  if @time_zone.blank?
    @time_zone = Time.zone.try(:name) || "UTC"
  end

  parse
  validate
end

Public Instance Methods

last_fire_at(time=nil) click to toggle source
# File lib/say_when/cron_expression.rb, line 85
def last_fire_at(time=nil)
  Time.zone = time_zone
  before = time.nil? ? Time.zone.now : time.in_time_zone(@time_zone)

  while (true)
    [years, months, days_of_month, days_of_week, hours, minutes, seconds].each do |cron_value|
      before, changed = move_to_last(cron_value, before)
      return if before.nil?
      break if changed
    end

    break if will_fire_on?(before)
  end
  before
end
next_fire_at(time=nil) click to toggle source
# File lib/say_when/cron_expression.rb, line 69
def next_fire_at(time=nil)
  Time.zone = time_zone
  after = time.nil? ? Time.zone.now : time.in_time_zone(@time_zone)

  while (true)
    [years, months, days_of_month, days_of_week, hours, minutes, seconds].each do |cron_value|
      after, changed = move_to_next(cron_value, after)
      return if after.nil?
      break if changed
    end

    break if will_fire_on?(after)
  end
  after
end
parse() click to toggle source
# File lib/say_when/cron_expression.rb, line 44
def parse
  return if expression.blank?
  vals = expression.split.map{ |word| word.upcase.gsub(/\s/, '') }
  self.seconds       = SecondsCronValue.new(vals[0])
  self.minutes       = MinutesCronValue.new(vals[1])
  self.hours         = HoursCronValue.new(vals[2])
  self.days_of_month = DaysOfMonthCronValue.new(vals[3])
  self.months        = MonthsCronValue.new(vals[4])
  self.days_of_week  = DaysOfWeekCronValue.new(vals[5])
  self.years         = YearsCronValue.new(vals[6] || "*")
end
to_s() click to toggle source
# File lib/say_when/cron_expression.rb, line 61
def to_s
  "s:#{seconds}m:#{minutes}h:#{hours}dom:#{days_of_month}m:#{months}dow:#{days_of_week}y:#{years}"
end
validate() click to toggle source
# File lib/say_when/cron_expression.rb, line 56
def validate
  return if expression.blank?
  raise "days_of_week or days_of_month needs to be ?" if (days_of_month.is_specified && days_of_week.is_specified)
end
will_fire_on?(date) click to toggle source
# File lib/say_when/cron_expression.rb, line 65
def will_fire_on?(date)
  [seconds, minutes, hours, days_of_month, months, days_of_week, years].detect { |part| !part.include?(date) }.nil?
end

Protected Instance Methods

move_to_last(cron_value, before) click to toggle source
# File lib/say_when/cron_expression.rb, line 111
def move_to_last(cron_value, before)
  unless cron_value.include?(before)
    before = cron_value.last(before)
    [before, true]
  end
  [before, false]
end
move_to_next(cron_value, after) click to toggle source
# File lib/say_when/cron_expression.rb, line 103
def move_to_next(cron_value, after)
  unless cron_value.include?(after)
    after = cron_value.next(after)
    [after, true]
  end
  [after, false]
end