pythonpandasdatedatetimecalendar

Pandas Holiday Package Black Friday Offset


I am using the holidays package to build a calendar of my calendar holidays and I made an adjustment to account for "Black Friday" (Day after US Thanksgiving. Always a Friday) with a relative delta for the 4th week in November, which works for 2018 and 2020, but this year, it would be the 5th week in November, which would make my setup ineffective

Is there a better way to ensure that this value always falls on the Friday after Thanksgiving? I'm not sure whether it is best to use the holidays package list of holidays and use some pandas magic to offset based on those values and set the holiday or if there is a better date manipulation method to achieve this.

Here is my method:

self.append({datetime.date(datetime(year, 11, 1) + relativedelta(weekday=FR(+4))) : "Black Friday"}) # Adding Black Friday

Here is the full code:

import pandas as pd
import numpy as np
import calendar as cal
from datetime import *
from dateutil.relativedelta import *
import holidays

class CorporateHolidays(holidays.UnitedStates):
    def _populate(self, year):
        print(self)
        # Populate the holiday list with the default US holidays
        holidays.UnitedStates._populate(self, year)
        # Remove Holiday Date(s)
        self.pop(datetime.date(datetime(year, 10, 1) + relativedelta(weekday=MO(+2))), None) # Removing Columbus Day
        # Add Holiday Date(s)
        self.append({datetime.date(datetime(year, 12, 24)) : "Christmas Eve"})
        self.append({datetime.date(datetime(year, 12, 31)) : "New Years Eve"})
        self.append({datetime.date(datetime(year, 11, 1) + relativedelta(weekday=FR(+4))) : "Black Friday"}) # Adding Black Friday

Where print(self) renders a list as such:

{datetime.date(2018, 1, 1): "New Year's Day", datetime.date(2018, 1, 15): 'Martin Luther King, Jr. Day', datetime.date(2018, 2, 19): "Washington's Birthday", datetime.date(2018, 5, 28): 'Memorial Day', datetime.date(2018, 7, 4): 'Independence Day', datetime.date(2018, 9, 3): 'Labor Day', datetime.date(2018, 11, 11): 'Veterans Day', datetime.date(2018, 11, 12): 'Veterans Day (Observed)', datetime.date(2018, 11, 22): 'Thanksgiving', datetime.date(2018, 12, 25): 'Christmas Day', datetime.date(2018, 12, 24): 'Christmas Eve', datetime.date(2018, 12, 31): 'New Years Eve', datetime.date(2018, 11, 23): 'Black Friday'}....

Solution

  • Thanksgiving is (according to Wikipedia) always the forth Thursday in November. This causes a problem for you if the month starts on a Friday. So rather than using the forth Friday try to use the forth Thursday and add a final day to make it Friday. Something like

    datetime.date(datetime(year, 11, 1) + relativedelta(weekday=TH(+4)) + timedelta(days=1))
    
    In [5]: datetime.date(datetime(2018, 11, 1) + relativedelta(weekday=TH(+4)) + timedelta(days=1))                                                                                                            
    Out[5]: datetime.date(2018, 11, 23)
    
    In [6]: datetime.date(datetime(2019, 11, 1) + relativedelta(weekday=TH(+4)) + timedelta(days=1))                                                                                                            
    Out[6]: datetime.date(2019, 11, 29)
    
    

    should do the trick