horatio1701d
horatio1701d

Reputation: 9159

Pandas Time Series Holiday Rule Offset

Trying to define a set of rules using pandas.tseries.holidays class but can't figure out how to just create a rule based on another rule. I have the below rule but then want to just create another rule that offsets original rule by one business day:

Thanksgiving:

Holiday("Thanksgiving Day", month=11, day=1, offset=pd.DateOffset(weekday=TH(4))),

Black Friday:

Holiday("Thanksgiving Day", month=11, day=1, 
        offset=pd.DateOffset(weekday=TH(4))) + pd.DateOffset(1),

Similarly trying to create rule for Cyber Monday which would just be the Monday following Thanksgiving. Tried the below but this returns 11-2

Holiday("Thanksgiving Day", month=11, day=1,
        offset=pd.DateOffset(weekday=TH(4)), observance=next_monday)

But above won't work returning

TypeError: unsupported type for add operation

Upvotes: 6

Views: 3406

Answers (4)

WillZ
WillZ

Reputation: 3965

With the latest pandas 0.23.4, it's pretty easy to do this now.

import pandas as pd
from pandas.tseries.offsets import Day
from dateutil.relativedelta import TH

BlackFriday = Holiday("Black Friday", month=11, day=1, 
        offset=[pd.DateOffset(weekday=TH(4)), Day(1)])

Upvotes: 2

uxtechie
uxtechie

Reputation: 844

Nowadays, it's not possible define both offset and observance parameters in the same holiday rule.

I found this issue with the Boxing holiday day in England. The Boxing Day is the next workday after Christmas day.

I coded the solution using the observance parameter pointing to the appropriate rule, in this case: after_nearest_workday

    Holiday('Christmas', month=12, day=25, observance=nearest_workday),
    Holiday('Boxing Day', month=12, day=25, observance=after_nearest_workday)

after_nearest_workday is a function. If you need another observance rule, you can create your own function like the following original Pandas observance functions:

def nearest_workday(dt):
    """
    If holiday falls on Saturday, use day before (Friday) instead;
    if holiday falls on Sunday, use day thereafter (Monday) instead.
    """
    if dt.weekday() == 5:
        return dt - timedelta(1)
    elif dt.weekday() == 6:
        return dt + timedelta(1)
    return dt

def after_nearest_workday(dt):
    """
    returns next workday after nearest workday
    needed for Boxing day or multiple holidays in a series
    """
    return next_workday(nearest_workday(dt))

Upvotes: 2

horatio1701d
horatio1701d

Reputation: 9159

For anyone else who encounters this. Got this help after submitting issue with Pandas which solved my issue. https://github.com/pydata/pandas/issues/10217#issuecomment-106040041

Upvotes: 1

Alexander
Alexander

Reputation: 109528

I don't believe you can specify holidays relative other holidays. However, in your case, we can define holidays that match your requirement. Given that the Thanksgiving is the fourth Thursday, then BlackFriday is the fourth Friday, and CyberMonday is the fourth Saturday (observed on the following Monday). The latest date possible for Thanksgiving is Nov. 28, so that Saturday would be Nov. 30 and the 'holiday' would be observed on Dec. 2.

from pandas.tseries.holiday import Holiday, TH, FR, SA, next_monday

Holiday("Black Friday", month=11, day=1, offset=pd.DateOffset(weekday=FR(4)))
Holiday("CyberMonday", month=11, day=1, offset=pd.DateOffset(weekday=SA(4)), 
        observance=next_monday)

Upvotes: 3

Related Questions