Browse files

More intuitive structure for calendars

  • Loading branch information...
1 parent 414b853 commit fee4de2738004f48dc80072131bd3ed888221265 @brymck committed Sep 30, 2011
Showing with 102 additions and 49 deletions.
  1. +58 −11 lib/rupee/calendar.rb
  2. +44 −38 lib/rupee/calendar/us.rb
View
69 lib/rupee/calendar.rb
@@ -16,17 +16,17 @@ module Rupee
# MyCalendar.has_weekends_off
#
# # Thanksgiving (fourth Thursday of November
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :thanksgiving do |date|
# date.month == NOVEMBER && date.thursday? && week_of(date) == 4
# end
#
# # Christmas (December 25 or nearest weekday)
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :christmas do |date|
# date.month == DECEMBER && nearest_weekday(date, 25)
# end
#
# # New Year's Day (January 1 or next weekday)
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :new_years do |date|
# date.month == JANUARY && next_weekday(date, 1)
# end
# end
@@ -43,6 +43,35 @@ module Rupee
# # ...then it's back to work
# Rupee::Calendar::MyCalendar.day_off?(Time.new(2011, 12, 27))
# # => false
+ #
+ # You can also inherit from other calendars easily:
+ #
+ # require "rupee/calendar"
+ #
+ # class Rupee::Calendar
+ # # Pirates generally observe the Federal Reserve holiday schedule
+ # Blackbeard = US.copy
+ #
+ # # But they do observer Talk Like a Pirate Day
+ # Blackbeard.has_day_off_on :talk_like_a_pirate_day do |date|
+ # date.month == SEPTEMBER && date.day == 19
+ # end
+ #
+ # # And curse the flag Columbus flew under
+ # Blackbeard.remove_day_off_for :columbus_day
+ # end
+ #
+ # # Talk Like a Pirate Day
+ # Rupee::Calendar::Blackbeard.day_off?(Time.new(2011, 9, 19))
+ # # => true
+ # Rupee::Calendar::US.day_off?(Time.new(2011, 9, 19))
+ # # => false
+ #
+ # # Columbus Day
+ # Rupee::Calendar::Blackbeard.day_off?(Time.new(2011, 10, 10))
+ # # => false
+ # Rupee::Calendar::US.day_off?(Time.new(2011, 10, 10))
+ # # => true
class Calendar
# A constant representing the month of January
JANUARY = 1
@@ -74,11 +103,24 @@ class Calendar
# A description of the calendar
attr :description
+ # Functions used to determine whether a day is off
+ attr :days_off
# Builds a calendar
def initialize(description)
@description = description
- @days_off = []
+ @days_off = {}
+ end
+
+ # Makes a copy of the calendar
+ def copy
+ new_cal = Calendar.new @description.dup
+
+ @days_off.each_pair do |key, day_off|
+ new_cal.days_off[key] = day_off
+ end
+
+ new_cal
end
# Provides a function telling that calendar how to evaluate whether a
@@ -87,36 +129,41 @@ def initialize(description)
# previous_weekday:
#
# # Thanksgiving (fourth Thursday of November
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :thanksgiving do |date|
# date.month == NOVEMBER && date.thursday? && week_of(date) == 4
# end
#
# # Christmas (December 25 or nearest weekday)
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :christmas do |date|
# date.month == DECEMBER && nearest_weekday(date, 25)
# end
#
# # New Year's Day (January 1 or next weekday)
- # MyCalendar.has_day_off_when do |date|
+ # MyCalendar.has_day_off_on :new_years do |date|
# date.month == JANUARY && next_weekday(date, 1)
# end
- def has_day_off_when(&block)
- @days_off << block
+ def has_day_off_on(key, &block)
+ @days_off[key] = block
+ end
+
+ # Removes the day off for the specified key
+ def remove_day_off_for(key)
+ @days_off.delete key
end
# A simple helper method for the commonality among most countries that
# weekends are not workdays or trading days:
#
# MyCalendar.has_weekends_off
def has_weekends_off
- @days_off << Proc.new do |date|
+ @days_off[:weekends] = Proc.new do |date|
date.saturday? || date.sunday?
end
end
# Returns true if the specified date is a holiday or day off
def day_off?(date)
- @days_off.each do |day_off|
+ @days_off.each_value do |day_off|
return true if day_off.call(date)
end
View
82 lib/rupee/calendar/us.rb
@@ -6,48 +6,54 @@ class Calendar
# Weekends
US.has_weekends_off
- # Mondays
- US.has_day_off_when do |date|
- if date.monday?
- case date.month
- when JANUARY, FEBRUARY
- # Martin Luther King, Jr.'s Birthday (third Monday of February)
- # Washington's Birthday (third Monday of February)
- week_of(date) == 3
- when MAY
- # Memorial Day (last Monday of May)
- last_week?(date)
- when SEPTEMBER
- # Labor Day (first Monday of September)
- week_of(date) == 1
- when OCTOBER
- # Columbus Day (second Monday of October)
- week_of(date) == 2
- end
- end
- end
-
- # Fixed holidays
- US.has_day_off_when do |date|
- case date.month
- when JANUARY
- # New Year's Day (January 1)
- next_weekday(date, 1)
- when JULY
- # Independence Day (July 4)
- nearest_weekday(date, 4)
- when NOVEMBER
- # Veterans Day (November 11)
- nearest_weekday(date, 11)
- when DECEMBER
- # Christmas Day (December 25)
- nearest_weekday(date, 25)
- end
+ # New Year's Day (January 1)
+ US.has_day_off_on :new_years do |date|
+ date.month == JANUARY && next_weekday(date, 1)
+ end
+
+ # Martin Luther King, Jr.'s Birthday (third Monday of January)
+ US.has_day_off_on :mlk_day do |date|
+ date.month == JANUARY && date.monday? && week_of(date) == 3
+ end
+
+ # Washington's Birthday (third Monday of February)
+ US.has_day_off_on :washingtons_day do |date|
+ date.month == FEBRUARY && date.monday? && week_of(date) == 3
+ end
+
+ # Memorial Day (last Monday of May)
+ US.has_day_off_on :memorial_day do |date|
+ date.month == MAY && date.monday? && last_week?(date)
+ end
+
+ # Independence Day (July 4)
+ US.has_day_off_on :independence_day do |date|
+ date.month == JULY && nearest_weekday(date, 4)
+ end
+
+ # Labor Day (first Monday of September)
+ US.has_day_off_on :labor_day do |date|
+ date.month == SEPTEMBER && date.monday? && week_of(date) == 1
+ end
+
+ # Columbus Day (second Monday of October)
+ US.has_day_off_on :columbus_day do |date|
+ date.month == OCTOBER && date.monday? && week_of(date) == 2
+ end
+
+ # Veterans Day (November 11)
+ US.has_day_off_on :veterans_day do |date|
+ date.month == NOVEMBER && nearest_weekday(date, 11)
end
# Thanksgiving Day (fourth Thursday of November)
- US.has_day_off_when do |date|
+ US.has_day_off_on :thanksgiving do |date|
date.month == NOVEMBER && date.thursday? && week_of(date) == 4
end
+
+ # Christmas Day (December 25)
+ US.has_day_off_on :christmas do |date|
+ date.month == DECEMBER && nearest_weekday(date, 25)
+ end
end
end

0 comments on commit fee4de2

Please sign in to comment.