class BusinessCalendar::Calendar

Constants

DEFAULT_TIME_TO_LIVE

Attributes

holiday_determiner[R]

Public Class Methods

new(holiday_determiner, options = {}) click to toggle source

@param [Proc[Date -> Boolean]] a proc which returns whether or not a date is a

holiday.
# File lib/business_calendar/calendar.rb, line 7
def initialize(holiday_determiner, options = {})
  ttl = options['ttl']
  @time_to_live = ttl.nil? ? DEFAULT_TIME_TO_LIVE : ttl
  @options = options
  @holiday_cache = {}
  @holiday_determiner = holiday_determiner
end

Public Instance Methods

add_business_day(date_or_dates, num=1, initial_direction = :forward)
Alias for: add_business_days
add_business_days(date_or_dates, num=1, initial_direction = :forward) click to toggle source

@param [Date or Array] date_or_dates The day(s) to start from. @param [Integer] num Number of days to advance. If negative,

this will call `subtract_business_days`.

@param [Symbol] direction Either `:forward` or `:backward`; the

direction to move if today is not a
business day.

@return [Date] The result of adding <num> business days to <date>. @note 'Adding a business day' means moving one full business day from the

start of the given day -- meaning that adding one business day to a
Saturday will return the following Tuesday, not Monday.
# File lib/business_calendar/calendar.rb, line 43
def add_business_days(date_or_dates, num=1, initial_direction = :forward)
  return subtract_business_days(date_or_dates, -num) if num < 0

  with_one_or_many(date_or_dates) do |date|
    d = nearest_business_day(date, initial_direction)
    num.times { d = following_business_day(d) }
    d
  end
end
Also aliased as: add_business_day
following_business_day(date_or_dates) click to toggle source

@param [Date or Array] date_or_dates The day(s) to start from. @return [Date] The nearest (going forward in time) business day from <date>

which is not <date> itself.
# File lib/business_calendar/calendar.rb, line 107
def following_business_day(date_or_dates)
  with_one_or_many(date_or_dates) do |date|
    nearest_business_day(date + 1)
  end
end
is_business_day?(date) click to toggle source

@param [Date] date @return [Boolean] Whether or not banking can be done on <date>.

# File lib/business_calendar/calendar.rb, line 27
def is_business_day?(date)
  return false if !@options['business_weekends'] && (date.saturday? || date.sunday?)
  return false if is_holiday?(date)
  true
end
is_holiday?(date) click to toggle source

@param [Date] date @return [Boolean] Whether or not this calendar's list of holidays includes <date>.

# File lib/business_calendar/calendar.rb, line 17
def is_holiday?(date)
  date = date.send(:to_date) if date.respond_to?(:to_date, true)

  clear_cache if should_clear_cache?

  @holiday_cache[date] ||= holiday_determiner.call(date)
end
nearest_business_day(date_or_dates, direction = :forward) click to toggle source

@param [Date or Array] date_or_dates The day(s) to start from. @param [Symbol] direction Either `:forward` or `:backward`; the

direction to move if today is not a
business day.

@return [Date] The nearest (going <direction> in time) business day from

<date>. If <date> is already a business day, it will be returned.
# File lib/business_calendar/calendar.rb, line 87
def nearest_business_day(date_or_dates, direction = :forward)
  with_one_or_many(date_or_dates) do |date|
    until is_business_day? date
      date += case direction
              when :forward
                1
              when :backward
                -1
              else
                raise ArgumentError, "Invalid direction supplied: '#{direction}' should instead be :forward or :backward"
              end
    end

    date
  end
end
preceding_business_day(date_or_dates) click to toggle source

@param [Date or Array] date_or_dates The day(s) to start from. @return [Date] The business day immediately prior to <date>.

# File lib/business_calendar/calendar.rb, line 71
def preceding_business_day(date_or_dates)
  with_one_or_many(date_or_dates) do |date|
    begin
      date = date - 1
    end until is_business_day? date

    date
  end
end
subtract_business_day(date_or_dates, num=1)
subtract_business_days(date_or_dates, num=1) click to toggle source

@param [Date or Array] date_or_dates The day(s) to start from. @param [Integer] num Number of days to retreat. If negative,

this will call `add_business_days`.

@return [Date] The business date to which adding <num> business dats

would arrive at <date>.
# File lib/business_calendar/calendar.rb, line 59
def subtract_business_days(date_or_dates, num=1)
  return add_business_days(date_or_dates, -num) if num < 0

  with_one_or_many(date_or_dates) do |date|
    num.times { date = preceding_business_day(date) }
    date
  end
end
Also aliased as: subtract_business_day

Private Instance Methods

clear_cache() click to toggle source
# File lib/business_calendar/calendar.rb, line 122
def clear_cache
  @last_cleared = Time.now
  @holiday_cache = {}
end
should_clear_cache?() click to toggle source
# File lib/business_calendar/calendar.rb, line 115
def should_clear_cache?
  return false unless @time_to_live

  # limit size using a heuristic, to prevent cache growing arbitrarily large
  !@last_cleared || (Time.now - @last_cleared) >= @time_to_live || @holiday_cache.size > 365 * 3
end
with_one_or_many(thing_or_things) { |thing| ... } click to toggle source
# File lib/business_calendar/calendar.rb, line 127
def with_one_or_many(thing_or_things)
  if thing_or_things.is_a? Enumerable
    thing_or_things.collect do |thing|
      yield thing
    end
  else
    yield thing_or_things
  end
end