Holidays

Anyone else out there ever run into the need for a simple little list of holidays? I do a fair amount of stuff that involves questions like "Are we off on such and such a day?" where you have to figure out, "When is Easter this year anyway?" That's pretty easy if you look it up on a calendar. Now try doing that in code.

At any rate, I wrote a tiny little class to provide some basic holidays out. Help yourself to the code, it's not complicated, just annoying. The biggest trick is finding the information in the first place. This is US-oriented, but I'd be glad to extended it if someone wants some other days in there. It would be helpful if you could provide the holiday information you're interested in though (i.e., My Personal Holiday is the 3rd Tuesday of May or whatever). Oh, one last caveat. If the date doesn't appear (like Inauguration day), the DateTime will be a 0. That's fine for comparisons, but if you just do a dump of the dates, it gives you 1899.



unit holidayDateTime;

interface

uses sysutils;

type
THolidayClass = class
public
YearIs : word;
NewYears : TDateTime;
MLKJr : TDateTime;
Inauguration : TDateTime;
Washington : TDateTime;
ArmedForces : TDateTime;
Memorial : TDateTime;
FlagDay : TDateTime;
Independence : TDateTime;
Labor : TDateTime;
Columbus : TDateTime;
Veterans : TDateTime;
Thanksgiving : TDateTime;
Christmas : TDateTime;
Secretaries : TDateTime;
AprilFools : TDateTime;
Earth : TDateTime;
Fathers : TDateTime;
Groundhog : TDateTime;
Halloween : TDateTime;
Lincoln : TDateTime;
Mothers : TDateTime;
StPatty : TDateTime;
UnitedNations: TDateTime;
Valentines : TDateTime;
Election : TDateTime;
Flag : TDateTime;
Easter : TDateTime;
constructor Create(aYear:word);
procedure changeYear(aYear:word);
function getEaster:TDateTime;
class procedure SafeMonth(var month, y:word);
class function getDOW(year, month, dow, weekNum:word):TDateTime;
class function getLastDOW(year, month, dow:word):TDateTime;
end;

implementation

class procedure THolidayClass.SafeMonth(var month, y:word);
begin
while month>12 do
begin
dec(month,12);
inc(y);
end;
end;

class function THolidayClass.getDOW(year, month, dow, weekNum:word):TDateTime;
var i:word;
begin
result:=EncodeDate(year, month, 1);
for i:=0 to 7 do
if DayOfWeek(result+i)=dow then
begin
result:=result+i;
result:=result+((weeknum-1)*7); //move to the correct week, 1st week is inc of 0
break;
end;
end;

class function THolidayClass.getLastdow(year, month, dow:word):TDateTime;
var i:word;
begin
//Year has to be on the stack, SafeMonth could change year
inc(month);
SafeMonth(month,year);
result:=EncodeDate(year,month,1)-1;
for i:=0 to 7 do
if DayOfWeek(result-i)=dow then
begin
result:=result-i;
break;
end;
end;

constructor THolidayClass.Create(aYear:word);
begin
ChangeYear(aYear);
end;

function THolidayClass.getEaster:TDateTime;
var a,b,c,d,e,f,g,h,i,k,l,m,p : integer;
Easter_Month, Easter_Day : integer;
begin
a:=yearis mod 19;
b:=yearis div 100;
c:=yearis mod 100;
d:=b div 4;
e:=b mod 4;
f:=(b+8) div 25;
g:=(b-f+1) div 3;
h:=(19*a+b-d-g+15) mod 30;
i:=c div 4;
k:=c mod 4;
l:=(32+2*e+2*i-h-k) mod 7;
m:=(a+11*h+22*l) div 451;
Easter_Month :=(h+l-7*m+114) div 31; //[3=March, 4=April]
p:=(h+l-7*m+114) mod 31;
Easter_Day:=p+1; //(day in Easter Month)
result:=EncodeDate(YearIs,Easter_Month,Easter_Day);
end;


procedure THolidayClass.ChangeYear(aYear:word);
const
DayOfWeek_Sunday = 1;
DayOfWeek_Monday = 2;
DayOfWeek_Tuesday = 3;
DayOfWeek_Wednesday = 4;
DayOfWeek_Thursday = 5;
DayOfWeek_Friday = 6;
DayOfWeek_Saturday = 7;

begin
YearIs := aYear;
Easter := getEaster;
NewYears := EncodeDate(YearIs,1,1);
MLKJr := getdow(YearIs, 1, DayOfWeek_Monday, 3);
if (YearIs - 1937) mod 4 = 0 then
Inauguration := EncodeDate(YearIs, 1, 20)
else
Inauguration := 0;
Election := 0;
Flag := EncodeDate(YearIs,6,14);
Washington := getdow(YearIs, 2, DayOfWeek_Monday, 3);
ArmedForces := getdow(YearIs, 5, DayOfWeek_Saturday, 3);
Memorial := getLastdow(YearIs, 5, DayOfWeek_Monday);
FlagDay := EncodeDate(YearIs,6,14);
Independence := EncodeDate(YearIs,7,4);
Labor := getdow(YearIs, 9, DayOfWeek_Monday,1);
Columbus := getdow(YearIs, 10, DayOfWeek_Monday,2);
Veterans := EncodeDate(YearIs,11,11);
Thanksgiving := getdow(YearIs, 11, DayOfWeek_Thursday,4);
Christmas := EncodeDate(YearIs,12,25);
Secretaries := getLastdow(YearIs, 5, DayOfWeek_Saturday) - 3; //wednesday before last saturday in april
AprilFools := EncodeDate(YearIs,4,1);

Earth := EncodeDate(YearIs,4,22);
Fathers := getdow(YearIs, 6, DayOfWeek_Sunday,3);
Groundhog := EncodeDate(YearIs,2,2);
Halloween := EncodeDate(YearIs,10,31);
Lincoln := EncodeDate(YearIs,2,12);
Mothers := getdow(YearIs, 5, DayOfWeek_Sunday,2);
StPatty := EncodeDate(YearIs,3,17);
UnitedNations:= EncodeDate(YearIs,10,24);
Valentines := EncodeDate(YearIs,2,14);
end;

end.