class BankingCalendar::Calendar
Constants
- DEFAULT_BANKING_DAYS
- DEFAULT_BANKING_HOURS
- VALID_BANKING_HOURS_KEYS
- VALID_CALENDAR_KEYS
- VALID_DAYS
Attributes
additional_load_paths[RW]
Public Class Methods
load(calendar)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 10 def load(calendar) file_name = "#{calendar}.yml" directory = calendars.find do |d| File.exist?(File.join(d, file_name)) end raise "Cannot find calendar #{calendar}" unless directory yaml = YAML.load_file( File.join(directory, file_name) ).transform_keys(&:to_sym) new(yaml) end
load_calendar(calendar)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 25 def load_calendar(calendar) @semaphore.synchronize do @cached_calendars ||= {} unless @cached_calendars.include?(calendar) @cached_calendars[calendar] = load(calendar) end @cached_calendars[calendar] end end
new(config)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 55 def initialize(config) @config = config validate_config end
Private Class Methods
calendars()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 37 def calendars (@additional_load_paths || []) + [File.join(File.dirname(__FILE__), 'data')] end
Public Instance Methods
after_banking_hours?(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 150 def after_banking_hours?(date) time_or_datetime? date return true unless banking_day?(date) date.hour > banking_hours.max end
banking_day?(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 122 def banking_day?(date) date = date.to_date day = date.strftime('%a').downcase return false if bank_holidays.include?(date) return false unless banking_days.include?(day) true end
banking_days_after(date, interval)
click to toggle source
Given a date, add interval number of banking days.
If the given date is not a banking day, counting starts from the next banking day.
If banking hours are provided, returned date and time will be normalized to the end of banking day. If given date falls after banking hours, counting starts from the next banking day.
# File lib/banking_calendar/calendar.rb, line 92 def banking_days_after(date, interval) date = normalize_date(date, :after) if with_banking_hours? date = next_banking_day(date) unless banking_day?(date) interval.times do date = next_banking_day(date) end date end
banking_days_before(date, interval)
click to toggle source
Given a date, subtract interval number of banking days.
If the given date is not a banking day, counting starts from the previous banking day.
If banking hours are provided, returned date and time will be normalized to the end of banking day. If given date falls before banking hours, counting starts from the prior banking day.
# File lib/banking_calendar/calendar.rb, line 111 def banking_days_before(date, interval) date = normalize_date(date, :before) if with_banking_hours? date = previous_banking_day(date) unless banking_day?(date) interval.times do date = previous_banking_day(date) end date end
banking_hour?(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 132 def banking_hour?(date) time_or_datetime?(date) hour = date.hour return false unless banking_day?(date) return false unless banking_hours.include?(hour) true end
before_banking_hours?(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 143 def before_banking_hours?(date) time_or_datetime? date return false unless banking_day?(date) date.hour < banking_hours.min end
end_of_banking_day(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 157 def end_of_banking_day(date) date.class.new( date.year, date.month, date.day, banking_hours.max + 1, 0 ) end
next_banking_day(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 66 def next_banking_day(date) loop do date += duration_for(date) break if banking_day?(date) end date end
previous_banking_day(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 75 def previous_banking_day(date) loop do date -= duration_for(date) break if banking_day?(date) end date end
validate_config()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 60 def validate_config unless (@config.keys - VALID_CALENDAR_KEYS).empty? raise "Only the following keys are valid: #{VALID_CALENDAR_KEYS.join(', ')}" end end
Private Instance Methods
bank_holidays()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 235 def bank_holidays @bank_holidays ||= parse_dates(@config[:bank_holidays]) end
banking_days()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 227 def banking_days @banking_days ||= (@config[:banking_days] || DEFAULT_BANKING_DAYS).map do |day| day.downcase.strip[0..2].tap do |shortened_day| raise "#{day} is an invalid day." unless VALID_DAYS.include?(shortened_day) end end end
banking_hours()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 215 def banking_hours @banking_hours ||= (@config[:banking_hours] || DEFAULT_BANKING_HOURS).map do |hour| hour.tap do |h| raise "#{h} is an invalid hour." if h > 24 || h.negative? end end end
duration_for(date, interval = 1)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 169 def duration_for(date, interval = 1) date.is_a?(Date) ? interval : 3600 * 24 * interval end
normalize_date(date, rollover)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 202 def normalize_date(date, rollover) time_or_datetime? date if rollover == :after date = roll_forward(date) elsif rollover == :before date = roll_backward(date) end date = end_of_banking_day(date) date end
parse_dates(dates)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 173 def parse_dates(dates) (dates || []).map do |date| date.is_a?(Date) ? date : Date.parse(date) end end
roll_backward(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 194 def roll_backward(date) if banking_day?(date) && before_banking_hours?(date) date = previous_banking_day(date) end date end
roll_forward(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 186 def roll_forward(date) if banking_day?(date) && after_banking_hours?(date) date = next_banking_day(date) end date end
time_or_datetime?(date)
click to toggle source
# File lib/banking_calendar/calendar.rb, line 179 def time_or_datetime?(date) unless date.is_a?(Time) || date.is_a?(DateTime) raise "#{date} is #{date.class}. " \ 'Must be Time or DateTime if accounting for banking hours.' end end
with_banking_hours?()
click to toggle source
# File lib/banking_calendar/calendar.rb, line 223 def with_banking_hours? @config.key?(:banking_hours) end