class Timely::DateChooser

Constants

INTERVALS

Where is this used… so far only in one place, _date_range.html.haml May be good to refactor this as well, after the class behaviour is refactored.

Attributes

dates[RW]
from[RW]
interval[RW]
multiple_dates[RW]
select[RW]
to[RW]
weekdays[RW]

Public Class Methods

new(options) click to toggle source
# File lib/timely/date_chooser.rb, line 17
def initialize(options)
  @multiple_dates = options[:multiple_dates] || false
  @from     = process_date(options[:from])
  @to       = process_date(options[:to])
  @select   = options[:select]
  @dates    = options[:dates]
  @specific_dates = options[:specific_dates]
  @interval = options[:interval]
  @weekdays = WeekDays.new(options[:weekdays]) if @select == 'weekdays'
  validate
end

Public Instance Methods

choose_dates() click to toggle source

Chooses a set of dates from a date range, based on conditions. date_info - A hash with conditions and date information

:from     - The start of the date range
:to       - The end of the date range

You can either specify specific dates to be chosen each month:

:dates          - A comma separated string of days of the month, e.g. 1,16
:specific_dates - A comma separated string of dates, e.g. 26-10-2012, 03-11-2012, 01-01-2013

or you can specify how to select the dates

:day      - A hash of days, the index being the wday, e.g. 0 = sunday, and the value being 1 if chosen
:interval - A hash of information about the interval
  :level  - The level/multiplier of the interval unit
  :unit   - The unit of the interval, e.g. w for week, mow for month of week
  e.g. :level => 2, :unit => w would try to select the days of the week every fortnight,
       so every friday and saturday each fornight
# File lib/timely/date_chooser.rb, line 54
def choose_dates
  # Not multiple dates - just return the From date.
  return [@from] unless @multiple_dates

  # Multiple dates - return the array, adjusted as per input
  all_days = (@from..@to).to_a

  case @select
  when 'days'
    days = @dates.gsub(/\s/, '').split(',')
    all_days.select { |date| days.include?(date.mday.to_s) }
  when 'specific_days'
    days = @specific_dates.gsub(/\s/, '').split(',')
    days.map(&:to_date)
  when 'weekdays'
    raise DateChooserException, 'No days of the week selected' if @weekdays.weekdays.empty?
    raise DateChooserException, 'No weekly interval selected' if @interval&.empty?

    all_days.select do |date|
      next unless @weekdays.has_day?(date.wday)

      case @interval[:unit]
      when 'week'
        # 0 = first week, 1 = second week, 2 = third week, etc.
        nth_week = (date - @from).to_i / 7
        # true every 2nd week (0, 2, 4, 6, etc.)
        (nth_week % @interval[:level].to_i).zero?
      when 'week_of_month'
        week = @interval[:level].to_i
        (date.mday > (week - 1) * 7 && date.mday <= week * 7)
      end
    end
  else
    all_days
  end
end
process_date(date) click to toggle source
# File lib/timely/date_chooser.rb, line 29
def process_date(date)
  case date
  when Date then date
  when NilClass then nil
  when String
    date !~ /[^[:space:]]/ ? nil : date.to_date
  end
end

Private Instance Methods

validate() click to toggle source
# File lib/timely/date_chooser.rb, line 93
def validate
  raise DateChooserException, 'A Start Date is required' unless @from
  raise DateChooserException, 'Start Date is after End Date' if @multiple_dates && @to && @from > @to

  @to ||= @from if @multiple_dates
end