drPete
drPete

Reputation: 13

Pandas Holiday Calendar Rule for US Election day

In using the Pandas Holiday class to create holiday calendars, I am unable to determine the proper rule for creating a calendar for US Election Days. A US Election Day is defined as the Tuesday following the first Monday of November, occuring every even numbered year. Using a Holiday class defined:

class USElectionCalendar(AbstractHolidayCalendar):
"""        
Federal Presidential  and Congressional election day.
Tuesday following the first Monday, 2 to 8 November every two even numbered years.
Election Days can only occur from November 2nd through 8th inclusive.
"""

rules = [
    Holiday("Election Day",month=11, day=2, offset=pd.DateOffset(weekday=TU(1))),
]

with

start_date = '20160108'
end_date   = '20261231'

into function

def holidays_between_dates(calendar, start_date, end_date):

    cal = calendar
    dates = cal.holidays(start_date, end_date, return_name=True)

    return dates

returns

2016-11-08    Election Day
2017-11-07    Election Day
2018-11-06    Election Day
2019-11-05    Election Day
2020-11-03    Election Day
2021-11-02    Election Day
2022-11-08    Election Day
2023-11-07    Election Day
2024-11-05    Election Day
2025-11-04    Election Day
2026-11-03    Election Day

all well and good except for the odd-numbered years. I've tried incorporating two offsets as discussed in this issue. Adding a 2 year offset to the rule

Holiday("Election Day", month=11, day=2, offset=[ pd.DateOffset(weekday=TU(1)), pd.DateOffset(years=2) ])

simply moves the first occurrence 2 years into the future. I am unsure of whether the desired time series is possible. So to the question:

Is it possible to construct this calendar directly, or will I need to remove the odd-numbered years from the Pandas calendar object with a second function?

Upvotes: 1

Views: 771

Answers (1)

Colin
Colin

Reputation: 2137

You can use observance instead of offset when making the Holiday and have it return None on odd years:

def election_observance(dt):
    if dt.year % 2 == 1:
        return None
    else:
        return dt + pd.DateOffset(weekday=TU(1))


class USElectionCalendar(AbstractHolidayCalendar):
    """
    Federal Presidential  and Congressional election day.
    Tuesday following the first Monday, 2 to 8 November every two even numbered years.
    Election Days can only occur from November 2nd through 8th inclusive.
    """

    rules = [
        Holiday('Election Day', month=11, day=2, observance=election_observance)
    ]


cal = USElectionCalendar()

start_date = '20160108'
end_date = '20261231'

print cal.holidays(start_date, end_date, return_name=True)

Output:

2016-11-08    Election Day
2018-11-06    Election Day
2020-11-03    Election Day
2022-11-08    Election Day
2024-11-05    Election Day
2026-11-03    Election Day
dtype: object

Note that you do not want to use BOTH offset and observance when constructing a Holiday and trying to do so will raise an exception in more recent pandas versions.

Upvotes: 2

Related Questions