Class: SayWhen::DaysOfWeekCronValue

Inherits:
CronValue
  • Object
show all
Defined in:
lib/say_when/cron_expression.rb

Constant Summary collapse

DAYS =
Date::ABBR_DAYNAMES.map { |a| a.upcase }

Instance Attribute Summary collapse

Attributes inherited from CronValue

#expression, #max, #min, #part, #values

Instance Method Summary collapse

Methods inherited from CronValue

parse_number

Constructor Details

#initialize(exp) ⇒ DaysOfWeekCronValue

Returns a new instance of DaysOfWeekCronValue.



404
405
406
407
# File 'lib/say_when/cron_expression.rb', line 404

def initialize(exp)
  self.is_last = false
  super(:wday, 1, 7, exp)
end

Instance Attribute Details

#is_lastObject

Returns the value of attribute is_last.



402
403
404
# File 'lib/say_when/cron_expression.rb', line 402

def is_last
  @is_last
end

#is_specifiedObject

Returns the value of attribute is_specified.



402
403
404
# File 'lib/say_when/cron_expression.rb', line 402

def is_specified
  @is_specified
end

#nth_dayObject

Returns the value of attribute nth_day.



402
403
404
# File 'lib/say_when/cron_expression.rb', line 402

def nth_day
  @nth_day
end

Instance Method Details

#include?(date) ⇒ Boolean

Returns:

  • (Boolean)


423
424
425
426
427
428
429
430
431
432
433
# File 'lib/say_when/cron_expression.rb', line 423

def include?(date)
  return true unless is_specified
  if is_last
    last = last_wday(date, values.first).to_date
    date.to_date == last
  elsif nth_day
    date.to_date == nth_wday(nth_day, values.first, date.month, date.year).to_date
  else
    values.include?(date.wday + 1)
  end
end

#last(date) ⇒ Object



435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/say_when/cron_expression.rb', line 435

def last(date)
  last_dow = if !is_specified
    date
  elsif is_last
    last = last_wday(date, values.first)
    if last.to_date > date.to_date
      last = last_wday(1.month.ago(date).change(day: 1), values.first)
    end
    last
  elsif nth_day
    nth = nth_wday(nth_day, values.first, date.month, date.year)
    if nth.to_date > date.to_date
      nth = 1.month.ago(date).change(day: 1)
      nth = nth_wday(nth_day, values.first, nth.month, nth.year)
    end
    nth
  else
    n = values.detect { |v| v > date.wday }
    n = values[0] if n.blank?
    base = (n < (date.wday + 1)) ? 7 : 0
    days_forward = n + (base - (date.wday + 1))
    days_forward.days.since(date)
  end
  last_dow.change(hour: 23, min: 59, sec: 59)
end

#last_wday(date, aWday) ⇒ Object



487
488
489
490
491
492
493
494
495
496
497
# File 'lib/say_when/cron_expression.rb', line 487

def last_wday(date, aWday)
  wday = aWday - 1
  eom = date.end_of_month
  if eom.wday == wday
    eom
  elsif eom.wday > wday
    (eom.wday - wday).days.ago(eom)
  else
    ((7 - wday) + eom.wday).days.ago(eom)
  end
end

#next(date) ⇒ Object



461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
# File 'lib/say_when/cron_expression.rb', line 461

def next(date)
  next_dow = if !is_specified
    date
  elsif is_last
    last = last_wday(date, values.first)
    if last.to_date <= date.to_date
      last = last_wday(1.month.since(date).change(day: 1), values.first)
    end
    last
  elsif nth_day
    nth = nth_wday(nth_day, values.first, date.month, date.year)
    if nth.to_date <= date.to_date
      date = 1.month.since(date)
      nth = nth_wday(nth_day, values.first, date.month, date.year)
    end
    nth
  else
    n = values.detect { |v| v > date.wday }
    n = values[0] if n.blank?
    base = (n < (date.wday + 1)) ? 7 : 0
    days_forward = n + (base - (date.wday + 1))
    days_forward.days.since(date)
  end
  next_dow.change(hour: 0)
end

#nth_wday(n, aWday, month, year) ⇒ Object

compliments of the ruby way



500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
# File 'lib/say_when/cron_expression.rb', line 500

def nth_wday(n, aWday, month, year)
  wday = aWday - 1
  if (!n.between? 1,5) or
     (!wday.between? 0,6) or
     (!month.between? 1,12)
    raise ArgumentError
  end
  t = Time.zone.local year, month, 1
  first = t.wday
  if first == wday
    fwd = 1
  elsif first < wday
    fwd = wday - first + 1
  elsif first > wday
    fwd = (wday+7) - first + 1
  end
  target = fwd + (n-1)*7
  begin
    t2 = Time.zone.local year, month, target
  rescue ArgumentError
    return nil
  end
  if t2.mday == target
    t2
  else
    nil
  end
end

#parse(exp) ⇒ Object



409
410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/say_when/cron_expression.rb', line 409

def parse(exp)
  if self.is_specified = !(expression =~ /\?/)
    if exp =~ /[A-Z]+/
      DAYS.each_with_index { |day, index| exp = exp.gsub(day, (index + 1).to_s) }
    end
    case exp
      when /^L$/ then values << max
      when /^(\d+)L$/ then self.is_last = true; values << $1.to_i
      when /^(\d+)#(\d+)/ then self.values << $1.to_i; self.nth_day = $2.to_i
      else super(exp)
    end
  end
end

#to_sObject



529
530
531
# File 'lib/say_when/cron_expression.rb', line 529

def to_s
  "[e:#{expression}, v:#{values.inspect}, is:#{is_specified}, il:#{is_last}, nd:#{nth_day}]\n"
end