The year 2006 approaches, with a new set of statutory holidays.

The idea of having to annually dig up the list of holidays for next year, and encode them statically into a file filled me with disgust. So I saved myself 5 minutes of work by spending 30 minutes piecing together some remind rules for calculating Canadian Statutory holidays.

These rules are derived (copied, mostly) from the examples/defs.rem distributed with remind.

Some common rules

SET Sunday    0
SET Monday    1
SET Tuesday   2
SET Wednesday 3
SET Thursday  4
SET Friday    5
SET Saturday  6

SET Sun 0
SET Mon 1
SET Tue 2
SET Wed 3
SET Thu 4
SET Fri 5
SET Sat 6

SET Jan 1
SET Feb 2
SET Mar 3
SET Apr 4
SET May 5
SET Jun 6
SET Jul 7
SET Aug 8
SET Sep 9
SET Oct 10
SET Nov 11
SET Dec 12

SET January   1
SET February  2
SET March     3
SET April     4
SET May       5
SET June      6
SET July      7
SET August    8
SET September 9
SET October   10
SET November  11
SET December  12

SET  Week_1              1
SET  Week_2              8
SET  Week_3             15
SET  Week_4             22

FSET _last(mo)          "1 " + MON((mo%12)+1)+" --7"
FSET _trig()            TRIGGER(TRIGDATE())
FSET _trig2(days)       TRIGGER(TRIGDATE()+days)
FSET _back(days)        TRIGGER(TODAY()-days)

The Holidays

# Federal Holidays
#      http://www.pch.gc.ca/progs/cpsc-ccsp/jfa-ha/index_e.cfm

SET easter EASTERDATE(YEAR(TODAY()))
REM  [TRIGGER(easter-46)] MSG Ash Wednesday
REM  [TRIGGER(easter-7)]  MSG Palm Sunday
OMIT [TRIGGER(easter-2)]  MSG Good Friday
OMIT [TRIGGER(easter)]    MSG Easter Sunday
OMIT [TRIGGER(easter+1)]  MSG Easter Monday
REM  [TRIGGER(easter+39)] MSG Ascension Day
REM  [TRIGGER(easter+49)] MSG Pentecost

OMIT     Jan  1         MSG New Year's Day
REM      Feb 15         MSG National Flag of Canada Day
REM      Mar 17         MSG St. Patrick's Day
REM  Mon May 18         SCANFROM [_back(7)] SATISFY 1
		        OMIT [_trig()]    MSG Victoria Day
			# Victoria Day is the Monday Preceeding May 25
REM      Jul  1		SCANFROM [_back(7)] SATISFY 1
			IF WKDAYNUM(TRIGDATE()) == Sun
			    OMIT [_trig2(+1)] MSG Canada day
			ELSE
			    OMIT [_trig()]    MSG Canada day
			ENDIF
			# Jul 2 is Canada DAY when Jul 1 is a Sunday 
REM  Mon Sep [Week_1]   SCANFROM [_back(7)] SATISFY 1
                        OMIT [_trig()] MSG Labor Day
REM      Nov 11         MSG Remembrance Day
REM  Mon Oct [Week_2]   SCANFROM [_back(7)] SATISFY 1
                        OMIT [_trig()] MSG Thanksgiving Day
OMIT     Dec 25         MSG Christmas Day
OMIT     Dec 26         MSG Boxing Day

# Provincial Holidays
#      http://www.pch.gc.ca/progs/cpsc-ccsp/jfa-ha/prov_e.cfm

REM  Mon Feb [Week_3]   MSG Family Day (Alberta)
#REM      Jun 24         MSG National Day (Quebec)
REM  Mon Aug [Week_1]   MSG BC Day
REM  Mon Aug [Week_1]   MSG New Brunswick Day
REM  Mon Aug [Week_1]   MSG Heritage Day (Alberta)
REM  Mon Aug [Week_1]   MSG Civic Holida (Manitoba,Saskatchewan,Ontario)

# Misc
REM      Feb  2         MSG Ground Hog Day
REM      Feb 14         MSG Valentine's Day
REM      Apr  1         MSG April Fool's Day
REM  Sun May [Week_2]   MSG Mother's Day
REM  Sun Jun [Week_3]   MSG Father's Day
REM      Oct 31         MSG Halloween

# Daylight Savings time.
REM  Sun Apr  1         MSG Daylight Savings Time starts (loose an hour)
REM  Sun [_last(Oct)]   MSG Daylight Savings Time over (gain an hour)