Created
September 22, 2008 23:33
-
-
Save geoffgarside/12175 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rubygems' | |
require 'chronic' | |
require 'activesupport' | |
class BankHoliday | |
def self.include?(date) | |
@@holidays.include?(date.utc.beginning_of_day) | |
end | |
def self.next_from(date) | |
date = date.utc.beginning_of_day | |
@@holidays.each do |day| | |
return day if day >= date | |
end | |
end | |
def self.next_workday_from(date) | |
return date.utc unless include?(date) | |
next_workday_from(date.tomorrow) | |
end | |
private | |
def self.load_dates! | |
@@holidays = [ | |
Chronic.parse('1st day in January'), # New Years Day (1st of January) | |
easter - 2.days, # Good Friday (Easter Sunday - 2) | |
easter + 1.days, # Easter Monday (Easter Sunday + 1) | |
Chronic.parse('1st Monday in May'), # Easter Bank Holiday (First Monday in May) | |
Chronic.parse('1st Monday in June') - 7.days, # Spring Bank Holiday (Last Monday in May) | |
Chronic.parse('1st Monday in September') - 7.days, # Summer Bank Holiday (Last Monday in August) | |
Chronic.parse('25th day in December'), # Christmas Day (25th of December) | |
Chronic.parse('26th day in December') # Boxing Day (26th of December) | |
].map { |day| day.utc.beginning_of_day }.sort | |
end | |
def self.easter(y = Time.now.year) | |
c = y / 100 | |
n = y - 19 * ( y / 19 ) | |
k = ( c - 17 ) / 25 | |
i = c - c / 4 - ( c - k ) / 3 + 19 * n + 15 | |
i = i - 30 * ( i / 30 ) | |
i = i - ( i / 28 ) * ( 1 - ( i / 28 ) * ( 29 / ( i + 1 ) ) * ( ( 21 - n ) / 11 ) ) | |
j = y + y / 4 + i + 2 - c + c / 4 | |
j = j - 7 * ( j / 7 ) | |
l = i - j | |
m = 3 + ( l + 40 ) / 44 | |
d = l + 28 - 31 * ( m / 4 ) | |
easter_sunday = Time.gm(y, m, d) | |
return easter_sunday < Time.now.utc ? easter(y + 1) : easter_sunday | |
end | |
# Here we load up the holiday dates | |
load_dates! | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'test/unit' | |
require 'bank_holiday' | |
class BankHolidayTests < Test::Unit::TestCase | |
def setup | |
BankHoliday.cattr_reader(:holidays) | |
end | |
def test_includes_bank_holidays | |
BankHoliday.holidays.each do |holiday| | |
assert BankHoliday.include?(holiday) | |
end | |
end | |
def test_next_from_with_holiday_dates | |
BankHoliday.holidays.each do |holiday| | |
assert_equal BankHoliday.next_from(holiday), holiday | |
end | |
end | |
# Here we test all but the last one, the last one will technically | |
# generate a failure as only one years worth (from Time.now) of | |
# bank holidays are generated. | |
def test_next_from_with_holiday_dates_plus_one_day | |
BankHoliday.holidays[0...-1].each_with_index do |holiday, index| | |
assert_equal BankHoliday.next_from(holiday + 1.day), BankHoliday.holidays[index + 1] | |
end | |
end | |
def test_next_workday_from_with_holiday_dates | |
BankHoliday.holidays.each do |holiday| | |
assert BankHoliday.next_workday_from(holiday) > holiday | |
assert ! BankHoliday.include?(BankHoliday.next_workday_from(holiday)) | |
end | |
end | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment