# ------------------------------------------------------------------------------
# Joyous Holidays
# ------------------------------------------------------------------------------
import datetime as dt
from itertools import chain
from collections import defaultdict, OrderedDict
from django.conf import settings
from .parser import parseHolidays
[docs]class Holidays:
"""Defines what holidays are celebrated on what dates."""
def __init__(self, holidaySetting="JOYOUS_HOLIDAYS"):
self.setting = holidaySetting
self.simple = {}
self.srcs = [ self.simple ]
self._parseSettings()
def __add__(self, other):
retval = Holidays(None)
for date, value in chain(self.simple.items(), other.simple.items()):
retval.add(date, value)
for src in chain(self.srcs[1:], other.srcs[1:]):
retval.register(src)
return retval
def _parseSettings(self):
if self.setting:
holidaySettings = getattr(settings, self.setting, "")
if holidaySettings:
hols = parseHolidays(holidaySettings)
if hols is not None:
self.register(hols)
[docs] def register(self, src):
"""Register a new source of holiday data."""
self.srcs.append(src)
[docs] def add(self, date, value):
"""Add a holiday to an individual date."""
oldValue = self.simple.get(date)
if oldValue:
if oldValue not in value and value not in oldValue:
self.simple[date] = "{}, {}".format(oldValue, value)
else:
self.simple[date] = value
[docs] def get(self, date):
"""Get all the holidays that are celebrated on this date."""
holidays = []
for src in self.srcs:
# get from python-holidays and other dict type srcs
getHoliday = getattr(src, "get", None)
if not getHoliday:
# get from workalendar srcs
getHoliday = getattr(src, "get_holiday_label")
holiday = getHoliday(date)
if holiday:
holidays.extend(holiday.split(", "))
holidays = list(OrderedDict.fromkeys(holidays)) # remove duplicates
return ", ".join(holidays)
[docs] def names(self):
"""Get a list of all the holiday names, sorted by month-day."""
thisYear = dt.date.today().year
popYears = list(range(thisYear - 1, thisYear + 10))
holidays = defaultdict(list)
for src in self.srcs:
# populate python-holidays calendar
populate = getattr(src, "_populate", None)
if populate:
for year in popYears:
populate(year)
# get from python-holidays and other dict type srcs
items = getattr(src, "items", None)
if items:
for date, names in items():
# holidays may have been concatenated together
for name in names.split(", "):
holidays[name].append(date)
else:
# get from workalendar srcs
getHolidays = getattr(src, "get_calendar_holidays", None)
if getHolidays:
for year in popYears:
for date, name in getHolidays(year):
holidays[name].append(date)
# sort holidays by month-day with a preference for a more recent year
mmddHolidays = []
def moreRecent(date):
delta2 = (date.year - thisYear) * 2
if delta2 < 0:
# slight preference for future years over past years
delta2 = -delta2 + 1
return delta2
for name, dates in holidays.items():
mostRecent = min(dates, key=moreRecent)
mmddHolidays.append(((mostRecent.month, mostRecent.day), name))
mmddHolidays.sort()
retval = [name for mmdd, name in mmddHolidays]
return retval
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------