344 lines
10 KiB
Python
344 lines
10 KiB
Python
from datetime import date
|
|
|
|
from ..core import WesternCalendar, SUN, MON, SAT
|
|
from ..registry_tools import iso_register
|
|
|
|
|
|
@iso_register('CA')
|
|
class Canada(WesternCalendar):
|
|
"Canada"
|
|
FIXED_HOLIDAYS = WesternCalendar.FIXED_HOLIDAYS + (
|
|
(7, 1, "Canada Day"),
|
|
)
|
|
shift_new_years_day = True
|
|
|
|
def get_variable_days(self, year):
|
|
# usual variable days
|
|
days = super().get_variable_days(year)
|
|
days.append(
|
|
(Canada.get_nth_weekday_in_month(year, 9, MON, 1), "Labor Day")
|
|
)
|
|
# Canada day
|
|
canadaday = date(year, 7, 1)
|
|
if canadaday.weekday() in self.get_weekend_days():
|
|
shift = self.find_following_working_day(canadaday)
|
|
days.append((shift, "Canada Day Shift"))
|
|
christmas = date(year, 12, 25)
|
|
if christmas.weekday() in self.get_weekend_days():
|
|
shift = self.find_following_working_day(christmas)
|
|
days.append((shift, "Christmas Shift"))
|
|
return days
|
|
|
|
|
|
class LateFamilyDayMixin:
|
|
"3rd Monday of February"
|
|
|
|
def get_family_day(self, year, label="Family Day"):
|
|
return (self.get_nth_weekday_in_month(year, 2, MON, 3), label)
|
|
|
|
|
|
class VictoriaDayMixin:
|
|
"Monday preceding the 25th of May"
|
|
|
|
def get_victoria_day(self, year):
|
|
for day in range(18, 25):
|
|
if date(year, 5, day).weekday() == MON:
|
|
return (date(year, 5, day), "Victoria Day")
|
|
|
|
|
|
class AugustCivicHolidayMixin:
|
|
"1st Monday of August; different names depending on location"
|
|
|
|
def get_civic_holiday(self, year, label="Civic Holiday"):
|
|
return (self.get_nth_weekday_in_month(year, 8, MON), label)
|
|
|
|
|
|
class ThanksgivingMixin:
|
|
"2nd Monday of October"
|
|
|
|
def get_thanksgiving(self, year):
|
|
thanksgiving = self.get_nth_weekday_in_month(year, 10, MON, 2)
|
|
return (thanksgiving, "Thanksgiving")
|
|
|
|
|
|
class BoxingDayMixin:
|
|
"26th of December; shift to next working day"
|
|
|
|
def get_boxing_day(self, year):
|
|
boxingday = date(year, 12, 26)
|
|
if boxingday.weekday() == MON:
|
|
days = [(boxingday, "Boxing Day"), (date(year, 12, 27),
|
|
"Boxing Day (Shift)")]
|
|
elif boxingday.weekday() == SAT or boxingday.weekday() == SUN:
|
|
days = [(boxingday, "Boxing Day"), (date(year, 12, 28),
|
|
"Boxing Day (Shift)")]
|
|
else:
|
|
days = [(boxingday, "Boxing Day")]
|
|
return days
|
|
|
|
|
|
class StJeanBaptisteMixin:
|
|
"24th of June; shift to next working day"
|
|
|
|
def get_st_jean(self, year):
|
|
stjean = date(year, 6, 24)
|
|
if stjean.weekday() in self.get_weekend_days():
|
|
days = [(stjean, "St Jean Baptiste"),
|
|
(self.find_following_working_day(stjean),
|
|
"St Jean Baptiste (Shift)")]
|
|
else:
|
|
days = [(stjean, "St Jean Baptiste")]
|
|
return days
|
|
|
|
|
|
class RemembranceDayShiftMixin:
|
|
"11th of November; shift to next day"
|
|
def get_remembrance_day(self, year):
|
|
remembranceday = date(year, 11, 11)
|
|
if remembranceday.weekday() in self.get_weekend_days():
|
|
days = [(remembranceday, "Remembrance Day"),
|
|
(self.find_following_working_day(remembranceday),
|
|
"Remembrance Day (Shift)")]
|
|
else:
|
|
days = [(remembranceday, "Remembrance Day")]
|
|
return days
|
|
|
|
|
|
@iso_register('CA-ON')
|
|
class Ontario(BoxingDayMixin, ThanksgivingMixin, VictoriaDayMixin,
|
|
LateFamilyDayMixin, AugustCivicHolidayMixin,
|
|
Canada):
|
|
"Ontario"
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_family_day(year)),
|
|
(self.get_victoria_day(year)),
|
|
(self.get_civic_holiday(year, "Civic Holiday (Not for all)")),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
days.extend(self.get_boxing_day(year))
|
|
|
|
return days
|
|
|
|
|
|
@iso_register('CA-QC')
|
|
class Quebec(VictoriaDayMixin, StJeanBaptisteMixin, ThanksgivingMixin, Canada):
|
|
"Quebec"
|
|
include_easter_monday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_victoria_day(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
days.extend(self.get_st_jean(year))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-BC')
|
|
class BritishColumbia(VictoriaDayMixin, AugustCivicHolidayMixin,
|
|
ThanksgivingMixin, Canada):
|
|
"British Columbia"
|
|
|
|
include_good_friday = True
|
|
|
|
FIXED_HOLIDAYS = Canada.FIXED_HOLIDAYS + (
|
|
(11, 11, "Remembrance Day"),
|
|
)
|
|
|
|
def get_family_day(self, year):
|
|
"""
|
|
Return Family Day for British Columbia.
|
|
|
|
From 2013 to 2018, Family Day was on 2nd MON of February
|
|
As of 2019, Family Day happens on 3rd MON of February
|
|
"""
|
|
label = "Family Day"
|
|
if year >= 2019:
|
|
return (self.get_nth_weekday_in_month(year, 2, MON, 3), label)
|
|
return (self.get_nth_weekday_in_month(year, 2, MON, 2), label)
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
if year >= 2013:
|
|
days.append(self.get_family_day(year))
|
|
|
|
days.extend([
|
|
(self.get_victoria_day(year)),
|
|
(self.get_civic_holiday(year, "British Columbia Day")),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
return days
|
|
|
|
|
|
@iso_register('CA-AB')
|
|
class Alberta(LateFamilyDayMixin, VictoriaDayMixin, ThanksgivingMixin, Canada):
|
|
"Alberta"
|
|
include_good_friday = True
|
|
|
|
FIXED_HOLIDAYS = Canada.FIXED_HOLIDAYS + (
|
|
(11, 11, "Remembrance Day"),
|
|
)
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_family_day(year)),
|
|
(self.get_victoria_day(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
return days
|
|
|
|
|
|
@iso_register('CA-SK')
|
|
class Saskatchewan(LateFamilyDayMixin, VictoriaDayMixin,
|
|
RemembranceDayShiftMixin, AugustCivicHolidayMixin,
|
|
ThanksgivingMixin, Canada):
|
|
"Saskatchewan"
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_family_day(year)),
|
|
(self.get_victoria_day(year)),
|
|
(self.get_civic_holiday(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
days.extend(self.get_remembrance_day(year))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-MB')
|
|
class Manitoba(LateFamilyDayMixin, VictoriaDayMixin,
|
|
AugustCivicHolidayMixin, ThanksgivingMixin,
|
|
Canada):
|
|
"Manitoba"
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_family_day(year, "Louis Riel Day")),
|
|
(self.get_victoria_day(year)),
|
|
(self.get_civic_holiday(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
return days
|
|
|
|
|
|
@iso_register('CA-NB')
|
|
class NewBrunswick(AugustCivicHolidayMixin, Canada):
|
|
"New Brunswick"
|
|
|
|
FIXED_HOLIDAYS = Canada.FIXED_HOLIDAYS + (
|
|
(11, 11, "Remembrance Day"),
|
|
)
|
|
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.append(self.get_civic_holiday(year))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-NS')
|
|
class NovaScotia(RemembranceDayShiftMixin, LateFamilyDayMixin, Canada):
|
|
"Nova Scotia"
|
|
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend(self.get_remembrance_day(year))
|
|
if year >= 2015:
|
|
days.append(self.get_family_day(year, "Viola Desmond Day"))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-PE')
|
|
class PrinceEdwardIsland(LateFamilyDayMixin, RemembranceDayShiftMixin, Canada):
|
|
"Prince Edward Island"
|
|
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.append((self.get_family_day(year, "Islander Day")))
|
|
days.extend(self.get_remembrance_day(year))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-NL')
|
|
class Newfoundland(Canada):
|
|
"Newfoundland and Labrador"
|
|
include_good_friday = True
|
|
|
|
|
|
@iso_register('CA-YT')
|
|
class Yukon(VictoriaDayMixin, ThanksgivingMixin, Canada):
|
|
"Yukon"
|
|
|
|
FIXED_HOLIDAYS = Canada.FIXED_HOLIDAYS + (
|
|
(11, 11, "Remembrance Day"),
|
|
)
|
|
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_nth_weekday_in_month(year, 8, MON, 3), "Discovery Day"),
|
|
(self.get_victoria_day(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
return days
|
|
|
|
|
|
@iso_register('CA-NT')
|
|
class NorthwestTerritories(RemembranceDayShiftMixin, VictoriaDayMixin,
|
|
ThanksgivingMixin, Canada):
|
|
"Northwest Territories"
|
|
|
|
FIXED_HOLIDAYS = Canada.FIXED_HOLIDAYS + (
|
|
(6, 21, "National Aboriginal Day"),
|
|
)
|
|
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_victoria_day(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
days.extend(self.get_remembrance_day(year))
|
|
return days
|
|
|
|
|
|
@iso_register('CA-NU')
|
|
class Nunavut(VictoriaDayMixin, ThanksgivingMixin, RemembranceDayShiftMixin,
|
|
Canada):
|
|
"Nunavut"
|
|
include_good_friday = True
|
|
|
|
def get_variable_days(self, year):
|
|
days = super().get_variable_days(year)
|
|
days.extend([
|
|
(self.get_victoria_day(year)),
|
|
(self.get_thanksgiving(year)),
|
|
])
|
|
|
|
days.extend(self.get_remembrance_day(year))
|
|
|
|
nuvanutday = date(year, 7, 9)
|
|
days.append((nuvanutday, "Nuvanut Day"))
|
|
if nuvanutday.weekday() == SUN:
|
|
days.append((date(year, 7, 10), "Nuvanut Day (Shift)"))
|
|
return days
|