Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions src/holidata/holiday.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import datetime
from dataclasses import dataclass
from typing import Iterator, Callable, Union, Dict, List

import dateutil

from holidata.plugin import PluginMount
from holidata.utils import SmartDayArrow, date
from holidata.utils import SmartDayArrow


@dataclass
Expand All @@ -15,7 +14,7 @@ class Holiday:
"""
locale: str
region: str
date: datetime.date
date: SmartDayArrow
description: str
flags: str = ""
notes: str = ""
Expand All @@ -37,10 +36,10 @@ def __init__(self, country_id: str, default_lang: str):
self.notes: str = ""
self.regions: List[str] = [""]
self.flags: str = ""
self.date: callable = None
self.date: Callable[[int], SmartDayArrow]
self.country_id: str = country_id
self.default_lang: str = default_lang
self.filters: List[callable] = []
self.filters: List[Callable[[int], bool]] = []

def with_name(self, name: str, lang: str = None) -> 'HolidayGenerator':
lang = self.default_lang if lang is None else lang
Expand All @@ -51,10 +50,8 @@ def with_names(self, name_dict: Dict[str, str]) -> 'HolidayGenerator':
self.name_dict = name_dict
return self

def on(self, date_func: callable = None, month: int = None, day: int = None) -> 'HolidayGenerator':
if month is not None and day is not None:
self.date = date(month, day)
elif callable(date_func):
def on(self, date_func: Callable[[int], SmartDayArrow] = None) -> 'HolidayGenerator':
if callable(date_func):
self.date = date_func
else:
raise ValueError("Invalid reference date")
Expand Down Expand Up @@ -105,7 +102,7 @@ def reference_does_not_contain(year: int) -> bool:
self.filters.append(reference_does_not_contain)
return self

def on_condition(self, condition: callable) -> 'HolidayGenerator':
def on_condition(self, condition: Callable[[int], bool]) -> 'HolidayGenerator':
self.filters.append(condition)
return self

Expand All @@ -115,13 +112,13 @@ def build_for_year_and_lang(self, year: int, lang: str) -> Iterator[Holiday]:
return []

for region in self.regions:
date = self.date(year)
if date is None:
holiday_date = self.date(year)
if holiday_date is None:
continue
yield Holiday(
locale=f"{lang}-{self.country_id}",
region=region,
date=date,
date=holiday_date,
description=self.name_dict[lang],
flags=self.flags,
notes=self.notes,
Expand Down
36 changes: 18 additions & 18 deletions src/holidata/holidays/AT/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dateutil.easter import EASTER_WESTERN

from holidata.holiday import Country
from holidata.utils import day
from holidata.utils import day, date

__all__ = [
"AT",
Expand All @@ -19,93 +19,93 @@ def __init__(self):

self.define_holiday() \
.with_name("Neujahr") \
.on(month=1, day=1) \
.on(date(month=1, day=1)) \
.with_flags("NF")

self.define_holiday() \
.with_name("Heilige drei Könige") \
.on(month=1, day=6) \
.on(date(month=1, day=6)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Josef") \
.in_regions(["2", "6", "7", "8"]) \
.on(month=3, day=19) \
.on(date(month=3, day=19)) \
.with_flags("RF")

self.define_holiday() \
.with_name("Staatsfeiertag") \
.on(month=5, day=1) \
.on(date(month=5, day=1)) \
.with_flags("NF")

self.define_holiday() \
.with_name("Florian") \
.in_regions(["4"]) \
.on(month=5, day=4) \
.on(date(month=5, day=4)) \
.with_flags("F")

self.define_holiday() \
.with_name("Mariä Himmelfahrt") \
.on(month=8, day=15) \
.on(date(month=8, day=15)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Rupert") \
.in_regions(["5"]) \
.on(month=9, day=24) \
.on(date(month=9, day=24)) \
.with_flags("F")

self.define_holiday() \
.with_name("Tag der Volksabstimmung") \
.in_regions(["2"]) \
.on(month=10, day=10) \
.on(date(month=10, day=10)) \
.with_flags("F")

self.define_holiday() \
.with_name("Nationalfeiertag") \
.on(month=10, day=26) \
.on(date(month=10, day=26)) \
.with_flags("NF")

self.define_holiday() \
.with_name("Allerheiligen") \
.on(month=11, day=1) \
.on(date(month=11, day=1)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Martin") \
.in_regions(["1"]) \
.on(month=11, day=11) \
.on(date(month=11, day=11)) \
.with_flags("F")

self.define_holiday() \
.with_name("Leopold") \
.in_regions(["9", "3"]) \
.on(month=11, day=15) \
.on(date(month=11, day=15)) \
.with_flags("F")

self.define_holiday() \
.with_name("Mariä Empfängnis") \
.on(month=12, day=8) \
.on(date(month=12, day=8)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Heiliger Abend") \
.on(month=12, day=24) \
.on(date(month=12, day=24)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Christtag") \
.on(month=12, day=25) \
.on(date(month=12, day=25)) \
.with_flags("NRF")

self.define_holiday() \
.with_name("Stefanitag") \
.on(month=12, day=26) \
.on(date(month=12, day=26)) \
.with_flags("NF")

self.define_holiday() \
.with_name("Silvester") \
.on(month=12, day=31) \
.on(date(month=12, day=31)) \
.with_flags("NF")

self.define_holiday() \
Expand Down
93 changes: 31 additions & 62 deletions src/holidata/holidays/AU/ACT.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from holidata.holiday import Region
from holidata.utils import SmartDayArrow, first, second, day
from holidata.utils import first, second, day, date


class ACT(Region):
Expand All @@ -13,14 +13,14 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("New Year's Day") \
.on(month=1, day=1) \
.on(date(month=1, day=1)) \
.with_flags("F")

self.define_holiday() \
.with_name("New Year's Day (observed)") \
.on(first("monday").after(month=1, day=1)) \
.on(first("monday").after(date(month=1, day=1))) \
.with_flags("V") \
.on_condition(ACT.date_is_on_weekend(month=1, day=1))
.on_condition(date(month=1, day=1).is_one_of(["saturday", "sunday"]))

"""
Australia Day
Expand All @@ -29,7 +29,14 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("Australia Day") \
.on(self.mon_to_fri_on_or_following(month=1, day=26)) \
.on(date(month=1, day=26)) \
.on_condition(date(month=1, day=26).is_none_of(["saturday", "sunday"])) \
.with_flags("V")

self.define_holiday() \
.with_name("Australia Day") \
.on(first("monday").after(date(month=1, day=26))) \
.on_condition(date(month=1, day=26).is_one_of(["saturday", "sunday"])) \
.with_flags("V")

"""
Expand Down Expand Up @@ -85,7 +92,14 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("Anzac Day") \
.on(self.mon_to_sat_on_or_following(month=4, day=25)) \
.on(date(month=4, day=25)) \
.on_condition(date(month=4, day=25).is_not_a("sunday")) \
.with_flags("V")

self.define_holiday() \
.with_name("Anzac Day") \
.on(first("monday").after(date(month=4, day=25))) \
.on_condition(date(month=4, day=25).is_a("sunday")) \
.with_flags("V")

"""
Expand All @@ -95,7 +109,7 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("Reconciliation Day") \
.on(first("monday").after(month=5, day=26, including=True)) \
.on(first("monday").after(date(month=5, day=26), including=True)) \
.with_flags("V")

"""
Expand Down Expand Up @@ -142,20 +156,20 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("Christmas Day") \
.on(month=12, day=25) \
.on(date(month=12, day=25)) \
.with_flags("RF")

self.define_holiday() \
.with_name("Christmas Day (observed)") \
.on(first("monday").after(month=12, day=25)) \
.on(first("monday").after(date(month=12, day=25))) \
.with_flags("RV") \
.on_condition(ACT.date_is_saturday(month=12, day=25))
.on_condition(date(month=12, day=25).is_a("saturday"))

self.define_holiday() \
.with_name("Christmas Day (observed)") \
.on(first("tuesday").after(month=12, day=25)) \
.on(first("tuesday").after(date(month=12, day=25))) \
.with_flags("RV") \
.on_condition(ACT.date_is_sunday(month=12, day=25))
.on_condition(date(month=12, day=25).is_a("sunday"))

"""
Boxing Day
Expand All @@ -164,62 +178,17 @@ def __init__(self, country):
"""
self.define_holiday() \
.with_name("Boxing Day") \
.on(month=12, day=26) \
.on(date(month=12, day=26)) \
.with_flags("RF")

self.define_holiday() \
.with_name("Boxing Day (observed)") \
.on(first("monday").after(month=12, day=26)) \
.on(first("monday").after(date(month=12, day=26))) \
.with_flags("RV") \
.on_condition(ACT.date_is_saturday(month=12, day=26))
.on_condition(date(month=12, day=26).is_a("saturday"))

self.define_holiday() \
.with_name("Boxing Day (observed)") \
.on(first("tuesday").after(month=12, day=26)) \
.on(first("tuesday").after(date(month=12, day=26))) \
.with_flags("RV") \
.on_condition(ACT.date_is_sunday(month=12, day=26))

@staticmethod
def date_is_on_weekend(month, day):
def wrapper(year):
return SmartDayArrow(year, month, day).weekday() in ["saturday", "sunday"]

return wrapper

@staticmethod
def date_is_saturday(month, day):
def wrapper(year):
return SmartDayArrow(year, month, day).weekday() == "saturday"

return wrapper

@staticmethod
def date_is_sunday(month, day):
def wrapper(year):
return SmartDayArrow(year, month, day).weekday() == "sunday"

return wrapper

@staticmethod
def mon_to_fri_on_or_following(month, day):
def wrapper(year):
date = SmartDayArrow(year, month, day)

if date.weekday() in ["saturday", "sunday"]:
return date.shift_to_weekday("monday", including=True)

return date

return wrapper

@staticmethod
def mon_to_sat_on_or_following(month, day):
def wrapper(year):
date = SmartDayArrow(year, month, day)

if date.weekday() == "sunday":
return date.shift_to_weekday("monday", including=True)

return date

return wrapper
.on_condition(date(month=12, day=26).is_a("sunday"))
Loading