Detecting a US Holiday
Asked Answered
H

7

39

What's the simplest way to determine if a date is a U.S. bank holiday in Python? There seem to be various calendars and webservices listing holidays for various countries, but I haven't found anything specific to banks in the U.S.

Heiskell answered 6/3, 2010 at 21:55 Comment(5)
@krosenvold: That's the point, these bank holidays typically extend the weekend and folks call these holidays. Vacations longer than a week fall into the sabbatical category.Tilney
How far in advance do you need to know them?Proverbial
@krosenvold: It's a damn shame, but I can't deny it.Tryparsamide
This varies by US State. There is no master list of all US bank holidays, since some states have different holidays than others. Not all Federal holidays are observed by businesses.Iridium
I use workalendar from github, see my reply in another similar thread https://mcmap.net/q/409149/-holiday-files-for-g20-countries-closed.Longhand
D
7

Some general comments:

I don't think that @ast4 really means "nth day of nth week of nth month algorithm". The notion of "nth week in nth month" is mind-snapping (like the "ISO calendar"). I've never seen a holiday defined in terms of "nth week". Martin Luther King Day is an example of the"Nth weekday in month" type of holiday:

MONDAY, ...., SATURDAY = range(7)
JAN, ....., DEC = range(1, 12)

Holiday("Martin L King's Birthday", type='floating',
    ordinal=3, weekday=MON, month=JAN)
Holiday("Memorial Day", type='floating',
    ordinal=-1, weekday=MON, month=MAY)

The USA doesn't have Easter-related holidays. Definition is not difficult:

Holiday("Good Friday", type='moveable',
    base='gregorian_easter', delta_days=-2)
Holiday("Easter Monday", etc, delta_days=1)
# Some states in Australia used to have Easter Tuesday (no kidding)
Holiday("Easter Tuesday", etc, delta_days=2)

The 'base' idea can be used to cater for lunar new year, in fact any holiday that is an offset from a base date that needs a special procedure to calculate it.

The so-called "static" holidays are not fixed when the "fixed" date is a Saturday or Sunday and may even vanish (no alternative day off work):

# Americans will get a day off on Friday 31 Dec 2010
# because 1 Jan 2011 is a Saturday.
Holiday("New Year's Day", type='fixed',
    day=1, month=JAN, sat_adj=-1, sun_adj=????)

# Australia observes ANZAC Day on the day, with no day off
# if the fixed date falls on a weekend.
Holiday("ANZAC Day", type='fixed', day=25, month=APR, sat_adj=0, sun_adj=0)

# Two consecutive "fixed" holidays is OK; three would need re-thinking.
# Australia again:
Holiday("Christmas Day", type='fixed', day=25, month=DEC, sat_adj=2, sun_adj=1)
Holiday("Boxing Day",    type='fixed', day=26, month=DEC, sat_adj=2, sun_adj=2)

I'm sure there are ways of specifying holidays that aren't catered for by the above rules ... any such news is welcome.

Distracted answered 7/3, 2010 at 0:23 Comment(3)
What is this Holiday class you are using?Clino
@Gringo Suave: It's just a notation for showing most of the weird ways that holidays can be be defined.Distracted
I realize this is old but still a valid question; the Holiday class John references is pandas.tseries.holiday.HolidayInescutcheon
P
56

The Pandas package provides a convenient solution for this:

from pandas.tseries.holiday import USFederalHolidayCalendar
cal = USFederalHolidayCalendar()
holidays = cal.holidays(start='2014-01-01', end='2014-12-31').to_pydatetime()
if datetime.datetime(2014,01,01) in holidays:
    print True 
Puddle answered 9/7, 2014 at 4:58 Comment(0)
C
32

Use the holiday library in python.

pip install holidays

For USA holiday:

1. To check a date holiday or not.

from datetime import date
import holidays

# Select country
us_holidays = holidays.US()

# If it is a holidays then it returns True else False
print('01-01-2018' in us_holidays)
print('02-01-2018' in us_holidays)

# What holidays is it?
print(us_holidays.get('01-01-2018'))
print(us_holidays.get('02-01-2018'))

2. To list out all holidays in US:

from datetime import date
import holidays

# Select country
us_holidays = holidays.US()

# Print all the holidays in US in year 2018
for ptr in holidays.US(years = 2018).items():
    print(ptr)

You can find holidays for any country you like the list of countries listed on my Blog. My Blog on Holidays

Github Link of Holidays Python

Coastland answered 22/7, 2018 at 18:56 Comment(2)
Great Answer! Thanks for your comment #2. I'll just add that it is also possible to input the name of the state, in case some states don't observe some holidays.Lemire
Not sure why 'date' is imported here? Is it required by the holidays package?Diestock
D
7

Some general comments:

I don't think that @ast4 really means "nth day of nth week of nth month algorithm". The notion of "nth week in nth month" is mind-snapping (like the "ISO calendar"). I've never seen a holiday defined in terms of "nth week". Martin Luther King Day is an example of the"Nth weekday in month" type of holiday:

MONDAY, ...., SATURDAY = range(7)
JAN, ....., DEC = range(1, 12)

Holiday("Martin L King's Birthday", type='floating',
    ordinal=3, weekday=MON, month=JAN)
Holiday("Memorial Day", type='floating',
    ordinal=-1, weekday=MON, month=MAY)

The USA doesn't have Easter-related holidays. Definition is not difficult:

Holiday("Good Friday", type='moveable',
    base='gregorian_easter', delta_days=-2)
Holiday("Easter Monday", etc, delta_days=1)
# Some states in Australia used to have Easter Tuesday (no kidding)
Holiday("Easter Tuesday", etc, delta_days=2)

The 'base' idea can be used to cater for lunar new year, in fact any holiday that is an offset from a base date that needs a special procedure to calculate it.

The so-called "static" holidays are not fixed when the "fixed" date is a Saturday or Sunday and may even vanish (no alternative day off work):

# Americans will get a day off on Friday 31 Dec 2010
# because 1 Jan 2011 is a Saturday.
Holiday("New Year's Day", type='fixed',
    day=1, month=JAN, sat_adj=-1, sun_adj=????)

# Australia observes ANZAC Day on the day, with no day off
# if the fixed date falls on a weekend.
Holiday("ANZAC Day", type='fixed', day=25, month=APR, sat_adj=0, sun_adj=0)

# Two consecutive "fixed" holidays is OK; three would need re-thinking.
# Australia again:
Holiday("Christmas Day", type='fixed', day=25, month=DEC, sat_adj=2, sun_adj=1)
Holiday("Boxing Day",    type='fixed', day=26, month=DEC, sat_adj=2, sun_adj=2)

I'm sure there are ways of specifying holidays that aren't catered for by the above rules ... any such news is welcome.

Distracted answered 7/3, 2010 at 0:23 Comment(3)
What is this Holiday class you are using?Clino
@Gringo Suave: It's just a notation for showing most of the weird ways that holidays can be be defined.Distracted
I realize this is old but still a valid question; the Holiday class John references is pandas.tseries.holiday.HolidayInescutcheon
T
3

Make sure date != one of these:

http://www.buyusa.gov/uk/en/us_bank_holidays.html

Trinitrophenol answered 6/3, 2010 at 21:58 Comment(2)
These apply to the US Embassy but may vary for any given bank: for example my bank is open on Columbus Day, which is not a very popular holiday in California.Grandiloquent
@Alex Martelli: Your bank may be open, but the fed is closed, so the ACH network does not iterate on Columbus Day. It's treated like a Saturday.Hypnotist
H
2

I've actually worked recently on a problem much like this one. The static holidays are rather trivial to generate (e.g. New Years Eve - December 31st, (cycle through years)). There are well defined algorithms out there to generate the floating holidays. Essentially you have a starting date (e.g. January 1st, 1900) and work from there. What I ended up implementing was a nth day of nth week of nth month algorithm (e.g. MLK day = 3rd Monday of January). Easter is a bit different to do, but again there are well defined algorithms for that already out there (Good Friday is trivial after you have January).

There's a fairly decent book on this out there you may want to check out: Calendrical Calculations

Hangnail answered 6/3, 2010 at 22:12 Comment(3)
I think you mean to say "Good Friday is trivial after you have Easter", right? That being said, neither Good Friday nor Easter Monday are normally holidays in the US, and Easter is of course always on a Sunday and therefore never a business day anyway.Tryparsamide
Yeah sorry, I was typing much too quickly.Hangnail
Some clarification (thanks John Machin for pointing it out): By nth day I mean: Monday = 1, Tuesday = 2, Wednesday = 3, Thursday = 4, Friday = 5, Saturday = 6, Sunday = 7Hangnail
P
2

I should caution contributors from thinking this is all solvable by an algorithm. Three examples:

  • most Islamic holidays are lunar. The moon is predictable (you need a new month before the month starts, and that affects public holidays like Eid, at the end of Ramadan). Some countries use algorithms to predict the moon, but others explicitly require that the new moon be actually sighted in the country. Some even post people to the tops of tall mountains, tasked to try to spot the new moon. If the night is cloudy, the new moon may not be sighted, so the following day is not a holiday.
  • a committee in China meets around November each year to decide on the number of holidays that will be given for Chinese New Year in mainland China the following February. As an added complication, because there are so many public holidays given for Chinese New Year, the Chinese Government sometimes nominates weekends after the holiday as working days, to boost economic activity.
  • stock exchanges in India sometimes have a very short trading period at a weekend for auspicious religious reasons.

For this reason, there are companies that do this research, get the updates, and publish holidays via an API, for a fee. Users typically query that API every day in case new holidays are announced.

Perichondrium answered 24/12, 2021 at 3:58 Comment(0)
T
0

i used set_index by datetime and below code wasn't work for me:

us_holidays = holidays.US(years=[*range(data_start.year, data_end.year)])
df.loc[:, 'isHoliday'] = data.index.isin(us_holidays)

this results always False but in my case i replace it to below code:

us_holidays = holidays.US(years=[*range(data_start.year, data_end.year)])
df.loc[:, 'isHoliday'] = data.index.map(lambda dt: dt in us_holidays)

note: I used pandas. if you dont use it comment then I recommend you new ways

Tu answered 23/2 at 22:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.