Declaring the New year's Day as a worldwide holiday

To date, there are only two exceptions: Israel & Qatar

refs #511
This commit is contained in:
Bruno Bord 2020-07-03 15:21:36 +02:00
parent b347472334
commit b3d7a11105
No known key found for this signature in database
GPG Key ID: 9499EA6788BF80A1
20 changed files with 88 additions and 70 deletions

View File

@ -3,6 +3,7 @@
## master (unreleased)
- Refactoring the core ``Calendar`` classes / mixins for better understanding. Only one ``Calendar`` subclass should be imported / used in calendar classes, the rest (when possible) should be ``Mixins`` (related to #511).
- Declaring the New year's Day as a worldwide holiday, with only two exceptions (to date): Israel & Qatar (#511).
- Fixed `contributing.md` documentation with the new class/mixin organization.
- Bugfix -- Belarus: removing day after Radonitsa, which is apparently not a holiday.
- Bugfix -- Algeria: assigning the week-end days as FRI+SAT, as it's following a Islamic calendar.

View File

@ -117,7 +117,7 @@ workon WORKALENDAR
pip install tox
```
With the `WesternCalendar` base class you have at least one holiday as a bonus: the New year's day, which is commonly a holiday.
With the `WesternCalendar` base class you have at least one holiday as a bonus: the New Year's day, which is almost a worldwide holiday.
#### Add fixed days

View File

@ -1,9 +1,9 @@
from ..core import IslamicCalendar, NewYearsDayMixin
from ..core import IslamicCalendar
from ..registry_tools import iso_register
@iso_register('DZ')
class Algeria(NewYearsDayMixin, IslamicCalendar):
class Algeria(IslamicCalendar):
"Algeria"
# Islamic holidays
include_prophet_birthday = True
@ -11,8 +11,7 @@ class Algeria(NewYearsDayMixin, IslamicCalendar):
include_day_of_sacrifice = True
include_islamic_new_year = True
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + \
IslamicCalendar.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = IslamicCalendar.FIXED_HOLIDAYS + (
(5, 1, "Labour Day"),
(7, 5, "Independence Day"),
(11, 1, "Anniversary of the revolution"),

View File

@ -1,9 +1,9 @@
from ..core import NewYearsDayMixin, IslamoWesternCalendar, SAT, SUN
from ..core import IslamoWesternCalendar, SAT, SUN
from ..registry_tools import iso_register
@iso_register('BJ')
class Benin(NewYearsDayMixin, IslamoWesternCalendar):
class Benin(IslamoWesternCalendar):
"Benin"
# Christian holidays
include_easter_monday = True
@ -17,7 +17,7 @@ class Benin(NewYearsDayMixin, IslamoWesternCalendar):
include_day_of_sacrifice = True
include_day_of_sacrifice_label = "Tabaski"
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = IslamoWesternCalendar.FIXED_HOLIDAYS + (
(1, 10, "Traditional Day"),
(5, 1, "Labour Day"),
(8, 1, "Independence Day"),
@ -25,5 +25,5 @@ class Benin(NewYearsDayMixin, IslamoWesternCalendar):
(11, 30, "National Day"),
)
# Explicitely assign these WE days, Benin has adopted the western workweek
# Explicitly assign these WE days, Benin has adopted the western workweek
WEEKEND_DAYS = (SAT, SUN)

View File

@ -1,9 +1,9 @@
from ..core import NewYearsDayMixin, IslamoWesternCalendar, SAT, SUN
from ..core import IslamoWesternCalendar, SAT, SUN
from ..registry_tools import iso_register
@iso_register('CI')
class IvoryCoast(NewYearsDayMixin, IslamoWesternCalendar):
class IvoryCoast(IslamoWesternCalendar):
"Ivory Coast"
# Christian holidays
include_easter_monday = True
@ -17,7 +17,7 @@ class IvoryCoast(NewYearsDayMixin, IslamoWesternCalendar):
include_day_of_sacrifice = True
include_day_of_sacrifice_label = "Feast of the Sacrifice"
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = IslamoWesternCalendar.FIXED_HOLIDAYS + (
(5, 1, "Labour Day"),
(8, 7, "Independence Day"),
(11, 15, "National Peace Day"),

View File

@ -1,12 +1,12 @@
from copy import copy
from datetime import timedelta, date
from ..core import NewYearsDayMixin, IslamoWesternCalendar, SAT, SUN
from ..core import IslamoWesternCalendar, SAT, SUN
from ..registry_tools import iso_register
@iso_register('KE')
class Kenya(NewYearsDayMixin, IslamoWesternCalendar):
class Kenya(IslamoWesternCalendar):
"Kenya"
# Christian holidays
include_good_friday = True
@ -16,10 +16,10 @@ class Kenya(NewYearsDayMixin, IslamoWesternCalendar):
include_day_of_sacrifice = True
shift_sunday_holidays = True
# Explicitely assign these WE days, Kenya has adopted the western workweek
# Explicitly assign these WE days, Kenya has adopted the western workweek
WEEKEND_DAYS = (SAT, SUN)
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = IslamoWesternCalendar.FIXED_HOLIDAYS + (
(5, 1, "Labour Day"),
(6, 1, "Madaraka Day"),
(10, 20, "Mashujaa Day"),

View File

@ -1,7 +1,7 @@
from datetime import date
import warnings
from ..core import ChineseNewYearCalendar, NewYearsDayMixin
from ..core import ChineseNewYearCalendar
from ..registry_tools import iso_register
from ..exceptions import CalendarError
@ -56,12 +56,12 @@ workdays = {
@iso_register('CN')
class China(NewYearsDayMixin, ChineseNewYearCalendar):
class China(ChineseNewYearCalendar):
"China"
# WARNING: Support 2018, 2019 currently, need update every year.
# National Days, 10.1 - 10.7
national_days = [(10, i, "National Day") for i in range(1, 8)]
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + tuple(national_days)
FIXED_HOLIDAYS = tuple(national_days)
include_chinese_new_year_eve = True

View File

@ -1,7 +1,7 @@
from datetime import date, timedelta
from ..core import (
ChineseNewYearCalendar, NewYearsDayMixin, WesternMixin,
ChineseNewYearCalendar, WesternMixin,
SUN, SAT
)
from ..astronomy import solar_term
@ -9,7 +9,7 @@ from ..registry_tools import iso_register
@iso_register('HK')
class HongKong(NewYearsDayMixin, WesternMixin, ChineseNewYearCalendar):
class HongKong(WesternMixin, ChineseNewYearCalendar):
"Hong Kong"
include_good_friday = True
include_easter_saturday = True
@ -18,7 +18,7 @@ class HongKong(NewYearsDayMixin, WesternMixin, ChineseNewYearCalendar):
WEEKEND_DAYS = (SUN,)
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = ChineseNewYearCalendar.FIXED_HOLIDAYS + (
(5, 1, "Labour Day"),
(7, 1, "SAR Establishment Day"),
(10, 1, "National Day"),

View File

@ -7,7 +7,7 @@ from ..registry_tools import iso_register
@iso_register("IL")
class Israel(Calendar):
"Israel"
include_new_years_day = False
WEEKEND_DAYS = (SAT, FRI)
def get_variable_days(self, year):

View File

@ -1,18 +1,18 @@
from datetime import date
from ..core import NewYearsDayMixin, Calendar, MON, SAT, SUN
from ..core import Calendar, MON, SAT, SUN
from ..astronomy import calculate_equinoxes
from ..registry_tools import iso_register
@iso_register('JP')
class Japan(NewYearsDayMixin, Calendar):
class Japan(Calendar):
"Japan"
# Japan uses the "western" workweek
WEEKEND_DAYS = (SAT, SUN)
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = Calendar.FIXED_HOLIDAYS + (
(2, 11, "Foundation Day"),
(4, 29, "Showa Day"),
(5, 3, "Constitution Memorial Day"),

View File

@ -1,14 +1,14 @@
from datetime import date
from ..core import (
NewYearsDayMixin, IslamicMixin, ChineseNewYearCalendar,
IslamicMixin, ChineseNewYearCalendar,
SAT, SUN
)
from ..registry_tools import iso_register
@iso_register('MY')
class Malaysia(NewYearsDayMixin, IslamicMixin, ChineseNewYearCalendar):
class Malaysia(IslamicMixin, ChineseNewYearCalendar):
"Malaysia"
include_nuzul_al_quran = True
include_eid_al_fitr = True
@ -23,7 +23,7 @@ class Malaysia(NewYearsDayMixin, IslamicMixin, ChineseNewYearCalendar):
WEEKEND_DAYS = (SAT, SUN)
# TODO: Add calendar exceptions
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = ChineseNewYearCalendar.FIXED_HOLIDAYS + (
(2, 1, "Federal Territory Day"),
(5, 1, "Workers' Day"),
(8, 31, "National Day"),

View File

@ -6,6 +6,8 @@ from ..registry_tools import iso_register
class Qatar(IslamicCalendar):
"Qatar"
include_new_years_day = False
FIXED_HOLIDAYS = (
(12, 18, "National Day"),
)

View File

@ -1,15 +1,14 @@
from datetime import date
from ..core import (
NewYearsDayMixin, WesternMixin, IslamicMixin, ChineseNewYearCalendar,
WesternMixin, IslamicMixin, ChineseNewYearCalendar,
SAT, SUN
)
from ..registry_tools import iso_register
@iso_register('SG')
class Singapore(NewYearsDayMixin, WesternMixin, IslamicMixin,
ChineseNewYearCalendar):
class Singapore(WesternMixin, IslamicMixin, ChineseNewYearCalendar):
"Singapore"
# Christian holiday
include_good_friday = True
@ -20,12 +19,12 @@ class Singapore(NewYearsDayMixin, WesternMixin, IslamicMixin,
include_day_of_sacrifice = True
day_of_sacrifice_label = "Hari Raya Haji"
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = ChineseNewYearCalendar.FIXED_HOLIDAYS + (
(5, 1, "Labour Day"),
(8, 9, "National Day"),
)
# Explicitely assign these WE days, Singapore calendar is too much of a mix
# Explicitly assign these WE days, Singapore calendar is too much of a mix
WEEKEND_DAYS = (SAT, SUN)
# Diwali/Deepavali is sometimes celebrated on a different day to India

View File

@ -1,11 +1,11 @@
from ..core import NewYearsDayMixin, ChineseNewYearCalendar
from ..core import ChineseNewYearCalendar
from ..registry_tools import iso_register
@iso_register('KR')
class SouthKorea(NewYearsDayMixin, ChineseNewYearCalendar):
class SouthKorea(ChineseNewYearCalendar):
"South Korea"
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = ChineseNewYearCalendar.FIXED_HOLIDAYS + (
(3, 1, "Independence Day"),
(5, 5, "Children's Day"),
(6, 6, "Memorial Day"),

View File

@ -1,18 +1,15 @@
from ..core import NewYearsDayMixin, ChineseNewYearCalendar
from ..core import ChineseNewYearCalendar
from ..astronomy import solar_term
from ..registry_tools import iso_register
@iso_register('TW')
class Taiwan(NewYearsDayMixin, ChineseNewYearCalendar):
class Taiwan(ChineseNewYearCalendar):
"Taiwan (Republic of China)"
FIXED_HOLIDAYS = (
NewYearsDayMixin.FIXED_HOLIDAYS +
(
(2, 28, "228 Peace Memorial Day"),
(4, 4, "Combination of Women's Day and Children's Day"),
(10, 10, "National Day/Double Tenth Day"),
)
FIXED_HOLIDAYS = ChineseNewYearCalendar.FIXED_HOLIDAYS + (
(2, 28, "228 Peace Memorial Day"),
(4, 4, "Combination of Women's Day and Children's Day"),
(10, 10, "National Day/Double Tenth Day"),
)
include_chinese_new_year_eve = True
include_chinese_second_day = True

View File

@ -42,24 +42,6 @@ def cleaned_date(day, keep_datetime=False):
return day
class NewYearsDayMixin:
FIXED_HOLIDAYS = (
(1, 1, 'New year'),
)
shift_new_years_day = False
def get_variable_days(self, year):
days = super().get_variable_days(year)
new_year = date(year, 1, 1)
if self.shift_new_years_day:
if new_year.weekday() in self.get_weekend_days():
days.append((
self.find_following_working_day(new_year),
"New Year shift"))
return days
class ChristianMixin:
EASTER_METHOD = None # to be assigned in the inherited mixin
include_epiphany = False
@ -813,16 +795,40 @@ class CoreCalendar:
class Calendar(CoreCalendar):
pass
"""
The cornerstone of Earth calendars.
Take care of the New Years Day, which is almost a worldwide holiday.
"""
include_new_years_day = True
shift_new_years_day = False
def get_fixed_holidays(self, year):
days = super().get_fixed_holidays(year)
if self.include_new_years_day:
days.insert(
0, (date(year, 1, 1), "New year")
)
return days
def get_variable_days(self, year):
days = super().get_variable_days(year)
new_year = date(year, 1, 1)
if self.include_new_years_day and self.shift_new_years_day:
if new_year.weekday() in self.get_weekend_days():
days.append((
self.find_following_working_day(new_year),
"New Year shift"))
return days
class WesternCalendar(NewYearsDayMixin, WesternMixin, Calendar):
class WesternCalendar(WesternMixin, Calendar):
"""
A Christian calendar using Western definition for Easter.
"""
class OrthodoxCalendar(NewYearsDayMixin, OrthodoxMixin, Calendar):
class OrthodoxCalendar(OrthodoxMixin, Calendar):
"""
A Christian calendar using Orthodox definition for Easter.
"""

View File

@ -1,10 +1,10 @@
from datetime import timedelta
from ..core import NewYearsDayMixin, IslamicCalendar, SAT, SUN
from ..core import IslamicCalendar, SAT, SUN
from ..registry_tools import iso_register
@iso_register('TR')
class Turkey(NewYearsDayMixin, IslamicCalendar):
class Turkey(IslamicCalendar):
'Turkey'
shift_new_years_day = True
# Even though they're using an islamic calendar, the work week is MON->FRI
@ -16,7 +16,7 @@ class Turkey(NewYearsDayMixin, IslamicCalendar):
include_eid_al_adha = True
length_eid_al_adha = 4
FIXED_HOLIDAYS = NewYearsDayMixin.FIXED_HOLIDAYS + (
FIXED_HOLIDAYS = IslamicCalendar.FIXED_HOLIDAYS + (
(4, 23, "National Sovereignty and Children's Day"),
(5, 1, "Labor and Solidarity Day"),
(5, 19, "Commemoration of Atatürk, Youth and Sports Day"),

View File

@ -15,6 +15,7 @@ class CoreCalendarTest(TestCase):
class GenericCalendarTest(CoreCalendarTest):
test_include_january_1st = True
def setUp(self):
super().setUp()
@ -28,3 +29,13 @@ class GenericCalendarTest(CoreCalendarTest):
self.cal.get_weekend_days()
except NotImplementedError:
assert False, (self.cal, class_name)
def test_january_1st(self):
class_name = self.cal_class.__name__
if class_name in ('Calendar',):
return
holidays = self.cal.holidays_set(self.year)
if self.test_include_january_1st:
self.assertIn(date(self.year, 1, 1), holidays)
else:
self.assertNotIn(date(self.year, 1, 1), holidays)

View File

@ -440,6 +440,7 @@ class MalaysiaTest(GenericCalendarTest):
class QatarTest(GenericCalendarTest):
cal_class = Qatar
test_include_january_1st = False
def test_year_2013(self):
holidays = self.cal.holidays_set(2013)
@ -580,6 +581,7 @@ class TaiwanTest(GenericCalendarTest):
class IsraelTest(GenericCalendarTest):
cal_class = Israel
test_include_january_1st = False
def test_holidays_2017(self):
calculated_holidays = self.cal.holidays_set(2017)

View File

@ -348,6 +348,7 @@ class OverwriteGetWeekendDaysCalendarTest(CoreCalendarTest):
class NoHolidayCalendar(Calendar):
include_new_years_day = False
WEEKEND_DAYS = (SAT, SUN)