I have an application written in c# that cannot run on a public holiday or a weekend. I\'ve looked around a bit and haven\'t found anywhere (official) that provides all the
To add what other people have already said, putting your own in a table is the only real way of doing it. A classic example is the extra bank holiday for the Queen's golden jubilee. This was only announced a couple of years in advance, and there was no way you could have it fifty years in advance.
Because of this a number of commercial services exist to provide this data in a reliable way. One is GoodBusinessDay.com but I have no experience with it.
Financial institutions will subscribe to services which provide periodic updates to banking calendars for various locales.
Note that there are often differences between banking holidays and ordinary holidays. An example of this in the United States is this passed Independence Day where the federal government recognized the holiday on July 3rd but the Federal Reserve Bank of New York was open.
2009 U.S. Federal Holidays
2009 U.S. Federal Reserve Bank Holidays
If it helps I have a text file that lists the rules for calculating the banking holidays defined for all the major and minor financial centers. The usual way of defining this is by business center, as in London, New York Frankfurt etc. etc, rather than by country. As an example here are the rules and explanations for London and a few others. If any one wants the whole lot let me know. This lot should work from 1990 until 2030 at the earliest. Obviously it won't have any new holidays announced after the fles was put together (2006 I think).
/*
* This file describes holiday calendars in the following way:
* 1. The "n"th "dow" in the month "m", means the 3rd Wednesday in August = "ALWAYS,3,WED,AUG"
* 2. The last etc "dow" in month "m", e.g. the last Monday in June = "LAST,MON,JUN"
* 3. A set date which if on a Sat or Sun is taken on the Monday, eg 13th Aug. = "FWDFROM,13,AUG"
* 4. A set date which if on a Sat is taken on Fri, if Sun on the Mon = "CLOSESTTO,13,AUG"
* 5. A set date which, if on a Sat is unchanged, but if a Sun is taken on the Mon = "FWDFROMSUN,13,AUG"
* 6. A set date which is unchanged if it happens to be on a weekend = "REMAINS,13,AUG"
* 7. The first day on or after day "x" in month "m" e.g. 1st Monday on or after 16th Jan = "FIRSTAFTER,16,MON,JAN"
* 8. A holiday which is a set number of days relative to Easter Sunday, e.g Easter Monday = "EASTER,1"
* 9. A holiday on one specified date only. e.g. 13th Aug 1997 = "ONEOFF,13,AUG,1997"
* 10.A specific date which has been added but is not a holiday and must be removed. = "REMOVE,13,AUG,1997"
* Note REMOVE only works on a date which is already in the calendar: you cannot remove a date which is yet to be added.
* If there is any text after the definition of the holiday it will appear in the date calendar description,
* e.g. you can have "FWDFROM,25,DEC,Christmas Day", if you wish.
*/
LON: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
ALWAYS,1,MON,MAY,Early May Bank Holiday;
LAST,MON,MAY,Spring Bank Holiday;
REMOVE,27,MAY,2002,Spring Bank Holiday;
ONEOFF,3,JUN,2002,Spring Bank Holiday;
ONEOFF,4,JUN,2002,Spring Bank Holiday;
LAST,MON,AUG,Summer Bank Holiday;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
ONEOFF,31,DEC,1999,Millenium;
}
EndDate: 31-Dec-2030;
Name: London;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
HKG: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
ONEOFF,16,FEB,1999,Chinese New Year;
ONEOFF,17,FEB,1999,Chinese New Year;
ONEOFF,18,FEB,1999,Chinese New Year;
FWDFROM,5,FEB,2000,Chinese New Year;
FWDFROM,6,FEB,2000,Chinese New Year;
FWDFROM,7,FEB,2000,Chinese New Year;
CLOSESTTO,5,APR,Ching Ming;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
FWDFROM,1,MAY,Labour Day;
ONEOFF,18,JUN,1999,Dragon Boat Festival;
FWDFROM,1,JUL,SAR Establishment Day;
FWDFROM,1,OCT,National Day;
FWDFROM,2,OCT,National Day;
ONEOFF,25,SEP,1999,Mid Autumn Festival;
ONEOFF,17,OCT,1999,Chung Yeung;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
ONEOFF,4,MAY,1998,May bank holiday;
ONEOFF,25,MAY,1998,May bank holiday;
ONEOFF,3,MAY,1999,May bank holiday;
ONEOFF,31,MAY,1999,May bank holiday;
ONEOFF,1,JUL,1997;
ONEOFF,2,JUL,1997;
}
EndDate: 31-Dec-2030;
Name: Hong Kong;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
MIL: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
REMAINS,6,JAN,Epiphany;
REMAINS,25,APR,Liberation Day;
REMAINS,1,MAY,May Day;
REMAINS,15,AUG,Assumption;
REMAINS,1,NOV,All Saint's;
REMAINS,8,DEC,Immaculate Conception;
EASTER,1,Easter Monday;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Milan;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
FFT: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
REMAINS,1,MAY,Labour Day;
EASTER,39,Ascension Day;
EASTER,50,Whit Monday;
EASTER,60,Corpus Christi;
REMAINS,3,OCT,Day of German Unity;
REMAINS,24,DEC,Christmas Eve;
REMAINS,25,DEC,Christmas Day;
REMAINS,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Frankfurt;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
ZUR: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
REMAINS,2,JAN,New Year's Holiday;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
EASTER,39,Ascension Day;
EASTER,50,Whit Monday;
REMAINS,1,AUG,August Bank Holiday;
REMAINS,1,MAY, LABOUR DAY;
REMAINS,25,DEC,Christmas;
REMAINS,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Zurich;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
NYK: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
ALWAYS,3,MON,JAN,Martin Luther King;
ALWAYS,3,MON,FEB,President's Day;
LAST,MON,MAY,Memorial Day;
CLOSESTTO,4,JUL,Independence Day;
ALWAYS,1,MON,SEP,Labor Day;
ALWAYS,2,MON,OCT,Columbus Day;
REMAINS,11,NOV,Veteran's Day;
ALWAYS,4,THU,NOV,Thanksgiving;
FWDFROMSUN,25,DEC,Christmas Day;
ONEOFF,12,NOV,2001,Veteran's Day;
}
EndDate: 31-Dec-2030;
Name: New York;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
I tried the "answer" and spent time to heavily modify it to be more readable. Really those "-DATEPART" options aren't needed since we are setting the date right before. It worked pretty well but was having issues with MLK day 2020 so my trust in it was shaky.
Additionally I didnt like the fact that it was very difficult to read. I found this and it's much easier to get through. It works very similar to a date dimension table and tested accurately for the 3 years I tried.
https://www.codeproject.com/Tips/1168430/US-Federal-Holidays-SQL
For those having trouble finding the last Thursday of November for Thanksgiving, I start by finding the last day of the month then use a WHILE() loop to minus a day and check the datename until the datename is Thursday:
DECLARE @LastThursday DateTime = DATEADD(s,-1,DATEADD(mm,DATEDIFF(m,0,CONVERT(datetime,CONVERT(varchar,YEAR(GETDATE()))+'-11-01'))+1,0))
WHILE DATENAME(weekday,@LastThursday) <> 'Thursday'
BEGIN
SET @LastThursday = DATEADD(day,DATEDIFF(day,0,@LastThursday)-1,0)
END
SELECT @LastThursday
Let's simplify this:
case
-- New Year's Day
when DATEPART(MM, @DATE) = 1
and DATEPART(DD, @DATE) = 1
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 31
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 1
and DATEPART(DD, @DATE) = 2
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Memorial Day (last Monday in May)
when DATEPART(MM, @DATE) = 5
and DATEPART(DD, @DATE) between 25 and 31
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Independence Day
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 4
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 3
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 5
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Labor Day (first Monday in September)
when DATEPART(MM, @DATE) = 9
and DATEPART(DD, @DATE) between 1 and 7
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Thanksgiving Day (fourth Thursday in November)
when DATEPART(MM, @DATE) = 11
and DATEPART(DD, @DATE) between 22 and 28
and DATEPART(DW, @DATE) = 5 then 'Y'
-- Black Friday (day after Thanksgiving)
when DATEPART(MM, @DATE) = 11
and DATEPART(DD, @DATE) between 23 and 29
and DATEPART(DW, @DATE) = 6 then 'Y'
-- Christmas Day
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 25
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 24
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 26
and DATEPART(DW, @DATE) = 2 then 'Y'
else 'N' end