class BusinessCalendar::Calendar
Constants
- DEFAULT_TIME_TO_LIVE
Attributes
Public Class Methods
@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
@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
@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
@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
@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
@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
@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
@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
Private Instance Methods
# File lib/business_calendar/calendar.rb, line 122 def clear_cache @last_cleared = Time.now @holiday_cache = {} end
# 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
# 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