111 lines
No EOL
3.7 KiB
Text
111 lines
No EOL
3.7 KiB
Text
== Holiday Gem Definition Syntax
|
|
|
|
All holidays are defined in YAML files in the <tt>data/</tt> directory. These definition files have three main parts: *months*, *methods* and *tests*. Before you start, you may want to look some of the existing files at http://code.dunae.ca/svn/holidays/trunk/data.
|
|
|
|
=== Months
|
|
|
|
Holidays are grouped by month from 1 through 12. Each entry within a month can have several fields.
|
|
|
|
[<tt>name</tt>] The name of the holiday.
|
|
[<tt>regions</tt>] One or more region codes.
|
|
|
|
===== Dates defined by a fixed date (e.g. January 1st)
|
|
|
|
[<tt>wday</tt>] Integer representing day of the month (1 through 31).
|
|
|
|
For example, the following holiday is on the first of January and available in the <tt>ca</tt>, <tt>us</tt> and <tt>au</tt> regions.
|
|
|
|
1:
|
|
- name: New Year's Day
|
|
regions: [ca, us, au]
|
|
mday: 1
|
|
|
|
===== Dates defined by a week number (e.g. first Monday of a month)
|
|
|
|
[<tt>wday</tt>] Integer representing day of the week (0 = Sunday through 6 = Saturday).
|
|
[<tt>week</tt>] Integer representing week number (1 = first week, 3 = third week, -1 = last week),
|
|
|
|
|
|
For example, the following holiday is on the first Monday of September and available in the <tt>ca</tt> region.
|
|
|
|
9:
|
|
- name: Labour Day
|
|
regions: [ca]
|
|
week: 1
|
|
wday: 1
|
|
|
|
=== Calculating dates with methods
|
|
|
|
In addition to defining holidays by day or week, you can create custom methods to calculate a date.
|
|
|
|
For example, Canada celebrates Victoria Day, which falls on the Monday on or before May 24. So, under the <tt>methods</tt> section we could create a custom method that returns a Date object.
|
|
|
|
methods:
|
|
ca_victoria_day: |
|
|
def self.ca_victoria_day(year)
|
|
date = Date.civil(year,5,24)
|
|
if date.wday > 1
|
|
date -= (date.wday - 1)
|
|
elsif date.wday == 0
|
|
date -= 6
|
|
end
|
|
date
|
|
end
|
|
|
|
This would be represented in the <tt>months</tt> section as:
|
|
|
|
5:
|
|
- name: Victoria Day
|
|
regions: [ca]
|
|
function: ca_victoria_day(year)
|
|
|
|
If a holiday can occur in different months (e.g. Easter) it can go in the '0' month.
|
|
|
|
0:
|
|
- name: Easter Monday
|
|
regions: [ca]
|
|
function: easter(year)+1
|
|
|
|
Calculated-date functions take the year (integer) as a parameter and must return either a Date object or an integer representing the day of the month.
|
|
|
|
|
|
=== Calculating observed dates
|
|
|
|
Several built-in methods are available for holidays that are observed on varying dates. For example, for a holiday that is observed on Monday if it falls on a weekend you could write:
|
|
|
|
7:
|
|
- name: Canada Day
|
|
regions: [ca]
|
|
mday: 1
|
|
observed: to_monday_if_weekend(date)
|
|
|
|
Methods included in the Holidays module are:
|
|
|
|
* Holidays#to_monday_if_sunday
|
|
* Holidays#to_monday_if_weekend
|
|
* Holidays#to_weekday_if_boxing_weekend
|
|
* Holidays#to_weekday_if_weekend
|
|
|
|
Observed-date functions take a Date object as a parameter and must return either a Date object or an integer representing the day of the month.
|
|
|
|
|
|
|
|
=== Tests
|
|
|
|
All definition files should have tests included. In the YAML file, tests are just a block of Ruby code.
|
|
|
|
tests: |
|
|
{Date.civil(2008,1,1) => 'New Year\'s Day',
|
|
Date.civil(2008,3,21) => 'Good Friday',
|
|
Date.civil(2008,3,24) => 'Easter Monday',
|
|
Date.civil(2008,9,1) => 'Labour Day',
|
|
Date.civil(2008,12,25) => 'Christmas Day',
|
|
Date.civil(2008,12,26) => 'Boxing Day'}.each do |date, name|
|
|
assert_equal name, Holidays.on(date, :ca, :informal)[0][:name]
|
|
end
|
|
|
|
# Victoria Day
|
|
[Date.civil(2004,5,24), Date.civil(2005,5,23), Date.civil(2006,5,22),
|
|
Date.civil(2007,5,21), Date.civil(2008,5,19)].each do |date|
|
|
assert_equal 'Victoria Day', Holidays.on(date, :ca)[0][:name]
|
|
end |