pythonpython-holidays

How to change observed holidays in holidays module?


I am new to this python holidays library, so I apologize in advance for any trivial questions that I might be asking.

My main problem is that I am not sure how to modify the 'observed' values in holidays. I need a holiday to be observed on a Monday only if it falls on a Sunday. I do not need Friday holidays to be observed on Saturday.

The documentation only seems to have a solution if I want to remove 'observed' holidays completely and not partially. My workaround for this was to create a NewCountrysHolidays class and populate it with the holidays and the observed statuses I wanted. I attached my code for the new class below.

My new problem is the I get the error code: 'datetime.date' object is not callable when I do 1-1-2015 in us_electric_holidays, but it does work with the timestamps with my data. When I use my data I get a new error name 'SUN' is not defined. It seems to not recognize Weekdays ex. SUN, and Months ex. DEC. I am not sure why.

I apologize if this was wordy, but I appreciate and thank you for any assistance with this problem.

Background for the problem: (If interested) I am a Electrical Engineering Ph.D. student who specializes in the Power Grid. One of my tasks is to analyze data from power companies. Power companies define a holiday as:

Holidays are New Year’s Day, President’s Day, Memorial Day, Independence Day, Labor Day, Veterans Day, Thanksgiving Day, and Christmas. When any holiday falls on a Sunday, the following Monday will be recognized as a holiday. However, no change will be made for holidays falling on a Saturday.

For all the data to be labelled correctly, I need to remove Martin Luther King Day and Columbus Day. Then remove the Observed Saturday from a Friday Holiday.

I implemented all this in the code below, but it will not run.

code for the holiday class (it is long, but StackOverflow did not let me attach files):

import holidays
from datetime import date
from dateutil.relativedelta import relativedelta as rd


 class UsElectricHolidays(holidays.HolidayBase):
     def _populate(self, year):
         # New Year's Day
        if year > 1870:
            name = "New Year's Day"
            self[date(year, JAN, 1)] = name
            if self.observed and date(year, JAN, 1).weekday() == SUN:
                self[date(year, JAN, 1) + rd(days=+1)] = name + \
                    " (Observed)"

        # Washington's Birthday
        name = "Washington's Birthday"
        if year > 1970:
            self[date(year, FEB, 1) + rd(weekday=MO(+3))] = name
        elif year >= 1879:
            self[date(year, FEB, 22)] = name

        # Memorial Day
        if year > 1970:
            self[date(year, MAY, 31) + rd(weekday=MO(-1))] = "Memorial Day"
        elif year >= 1888:
            self[date(year, MAY, 30)] = "Memorial Day"

        # Independence Day
        if year > 1870:
            name = "Independence Day"
            self[date(year, JUL, 4)] = name
            if self.observed and date(year, JUL, 4).weekday() == SUN:
                self[date(year, JUL, 4) + rd(days=+1)] = name + " (Observed)"

        # Labor Day
        if year >= 1894:
            self[date(year, SEP, 1) + rd(weekday=MO)] = "Labor Day"

        # Veterans Day
        if year > 1953:
            name = "Veterans Day"
        else:
            name = "Armistice Day"
        if 1978 > year > 1970:
            self[date(year, OCT, 1) + rd(weekday=MO(+4))] = name
        elif year >= 1938:
            self[date(year, NOV, 11)] = name
            if self.observed \
                    and date(year, NOV, 11).weekday() == SUN:
                self[date(year, NOV, 11) + rd(days=+1)] = name + \
                    " (Observed)"

        # Thanksgiving
        if year > 1870:
            self[date(year, NOV, 1) + rd(weekday=TH(+4))] = "Thanksgiving"

        # Christmas Day
        if year > 1870:
            name = "Christmas Day"
            self[date(year, DEC, 25)] = "Christmas Day"
            if self.observed \
                    and date(year, DEC, 25).weekday() == SUN:
                self[date(year, DEC, 25) + rd(days=+1)] = name + \
                    " (Observed)"

 us_electric_holidays = UsElectricHolidays()

Solution

  • I'm working on the same problem (NERC holidays for electric power) and saw your question. Pierre Boutquin's answer to a related question led me to a much faster solution: Just replace nearest_workday with sunday_to_monday and you should have what you need.

    Like so:

    class NERCHolidayCalendar(AbstractHolidayCalendar):
        rules = [
            Holiday('NewYearsDay', month=1, day=1, observance=sunday_to_monday),
            USMemorialDay,
            Holiday('USIndependenceDay', month=7, day=4, observance=sunday_to_monday),
            USLaborDay,
            USThanksgivingDay,
            Holiday('Christmas', month=12, day=25, observance=sunday_to_monday)
        ]