From 22d9f48a7851b35f6fe52f77d473167ba2429b3b Mon Sep 17 00:00:00 2001 From: ~Jhellico Date: Mon, 22 May 2023 18:07:23 +0300 Subject: [PATCH] Add Belize holidays (#1181) * Add Belize holidays * PR suggestion --- README.rst | 5 +- holidays/countries/__init__.py | 1 + holidays/countries/belize.py | 140 +++++++++++++ holidays/registry.py | 1 + tests/countries/test_belize.py | 346 +++++++++++++++++++++++++++++++++ 5 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 holidays/countries/belize.py create mode 100644 tests/countries/test_belize.py diff --git a/README.rst b/README.rst index 91c5be50d..594c6d17c 100644 --- a/README.rst +++ b/README.rst @@ -107,7 +107,7 @@ Available Countries .. _ISO 3166-1 alpha-2 code: https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes .. _ISO 3166-2 code: https://en.wikipedia.org/wiki/ISO_3166-2 -We currently support 122 country codes. The standard way to refer to a country +We currently support 123 country codes. The standard way to refer to a country is by using its `ISO 3166-1 alpha-2 code`_, the same used for domain names, and for a subdivision its `ISO 3166-2 code`_. The following countries and subdivisions are available: @@ -165,6 +165,9 @@ subdivisions are available: * - Belgium - BE - None + * - Belize + - BZ + - None * - Bolivia - BO - Departments: B, C, H, L, N, O, P, S, T diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py index 4bc50c7d2..1943a5d02 100644 --- a/holidays/countries/__init__.py +++ b/holidays/countries/__init__.py @@ -24,6 +24,7 @@ from .bangladesh import Bangladesh, BD, BGD from .belarus import Belarus, BY, BLR from .belgium import Belgium, BE, BEL +from .belize import Belize, BZ, BLZ from .bolivia import Bolivia, BO, BOL from .bosnia_and_herzegovina import BosniaAndHerzegovina, BA, BIH from .botswana import Botswana, BW, BWA diff --git a/holidays/countries/belize.py b/holidays/countries/belize.py new file mode 100644 index 000000000..ccdb7a4f0 --- /dev/null +++ b/holidays/countries/belize.py @@ -0,0 +1,140 @@ +# python-holidays +# --------------- +# A fast, efficient Python library for generating country, province and state +# specific sets of holidays on the fly. It aims to make determining whether a +# specific date is a holiday as fast and flexible as possible. +# +# Authors: dr-prodigy (c) 2017-2023 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from datetime import date +from datetime import timedelta as td +from typing import Optional + +from holidays.calendars import _get_nth_weekday_from +from holidays.constants import JAN, MAR, MAY, AUG, SEP, OCT, NOV, MON +from holidays.holiday_base import HolidayBase +from holidays.holiday_groups import ChristianHolidays, InternationalHolidays + + +class Belize(HolidayBase, ChristianHolidays, InternationalHolidays): + """ + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Belize + - http://www.belizelaw.org/web/lawadmin/PDF%20files/cap289.pdf + - https://www.pressoffice.gov.bz/public-and-bank-holidays-2022-updated/ + - https://www.pressoffice.gov.bz/government-of-belize-establishes-new-public-and-bank-holidays/ # noqa: E501 + """ + + country = "BZ" + + def __init__(self, *args, **kwargs) -> None: + ChristianHolidays.__init__(self) + InternationalHolidays.__init__(self) + super().__init__(*args, **kwargs) + + def _add_movable_holiday(self, *args) -> None: + # Chapter 289 of the laws of Belize states that if the holiday falls + # on a Sunday or a Friday, the following Monday is observed as public + # holiday; further, if the holiday falls on a Tuesday, Wednesday or + # Thursday, the preceding Monday is observed as public holiday + name, dt = self._parse_holiday(*args) + if self.observed: + if self._is_friday(dt) or self._is_sunday(dt): + dt = _get_nth_weekday_from(1, MON, dt) + name = "%s (Observed)" % name + elif ( + self._is_tuesday(dt) + or self._is_wednesday(dt) + or self._is_thursday(dt) + ): + dt = _get_nth_weekday_from(-1, MON, dt) + name = "%s (Observed)" % name + self._add_holiday(name, dt) + + def _add_holiday(self, *args) -> Optional[date]: + # Chapter 289 of the laws of Belize states that if the holiday falls + # on a Sunday, the following Monday is observed as public holiday + name, dt = self._parse_holiday(*args) + if ( + self.observed + and self._is_sunday(dt) + and dt + td(days=+1) not in self + ): + name = "%s (Observed)" % name + dt += td(days=+1) + return super()._add_holiday(name, dt) + + def _populate(self, year: int) -> None: + # Belize was granted independence on 21.09.1981. + if year <= 1981: + return None + super()._populate(year) + + # New Year's Day. + self._add_new_years_day("New Year's Day") + + if year >= 2021: + # George Price Day. + self._add_holiday("George Price Day", JAN, 15) + + # National Heroes and Benefactors Day. + self._add_movable_holiday( + "National Heroes and Benefactors Day", MAR, 9 + ) + + # Good Friday. + self._add_good_friday("Good Friday") + + # Holy Saturday. + self._add_holy_saturday("Holy Saturday") + + # Easter Monday. + self._add_easter_monday("Easter Monday") + + # Labour Day. + self._add_labor_day("Labour Day") + + if year <= 2021: + # Commonwealth Day. + self._add_movable_holiday("Commonwealth Day", MAY, 24) + + if year >= 2021: + # Emancipation Day. + self._add_movable_holiday("Emancipation Day", AUG, 1) + + # Saint George's Caye Day. + self._add_holiday("Saint George's Caye Day", SEP, 10) + + # Independence Day. + self._add_holiday("Independence Day", SEP, 21) + + # Indigenous Peoples' Resistance Day / Pan American Day. + self._add_movable_holiday( + "Indigenous Peoples' Resistance Day" + if year >= 2021 + else "Pan American Day", + date(year, OCT, 12), + ) + + # Garifuna Settlement Day. + self._add_holiday("Garifuna Settlement Day", NOV, 19) + + # Populated before Christmas for right obvserved Christmas calculation + # (if Christmas falls on Sunday, there should be no observed Christmas + # on Monday) + # Boxing Day. + self._add_christmas_day_two("Boxing Day") + + # Christmas Day. + self._add_christmas_day("Christmas Day") + + +class BZ(Belize): + pass + + +class BLZ(Belize): + pass diff --git a/holidays/registry.py b/holidays/registry.py index 79ff37dfd..be846a8bf 100644 --- a/holidays/registry.py +++ b/holidays/registry.py @@ -32,6 +32,7 @@ "bangladesh": ("Bangladesh", "BD", "BGD"), "belarus": ("Belarus", "BY", "BLR"), "belgium": ("Belgium", "BE", "BEL"), + "belize": ("Belize", "BZ", "BLZ"), "bolivia": ("Bolivia", "BO", "BOL"), "bosnia_and_herzegovina": ("BosniaAndHerzegovina", "BA", "BIH"), "botswana": ("Botswana", "BW", "BWA"), diff --git a/tests/countries/test_belize.py b/tests/countries/test_belize.py new file mode 100644 index 000000000..2e9f5e411 --- /dev/null +++ b/tests/countries/test_belize.py @@ -0,0 +1,346 @@ +# python-holidays +# --------------- +# A fast, efficient Python library for generating country, province and state +# specific sets of holidays on the fly. It aims to make determining whether a +# specific date is a holiday as fast and flexible as possible. +# +# Authors: dr-prodigy (c) 2017-2023 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.belize import Belize, BZ, BLZ +from tests.common import TestCase + + +class TestBelize(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass( + Belize, + years=range(1982, 2050), + years_non_observed=range(1982, 2050), + ) + + def test_country_aliases(self): + self.assertCountryAliases(Belize, BZ, BLZ) + + def test_no_holidays(self): + self.assertNoHolidays(Belize(years=1981)) + + def test_new_years_day(self): + name = "New Year's Day" + years_observed = { + 1984, + 1989, + 1995, + 2006, + 2012, + 2017, + 2023, + 2034, + 2040, + 2045, + } + self.assertHolidaysName( + name, + ( + f"{year}-01-01" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-01-02" for year in years_observed) + ) + + def test_george_price_day(self): + name = "George Price Day" + years_observed = {2023, 2034, 2040, 2045} + self.assertHolidaysName( + name, + ( + f"{year}-01-15" + for year in set(range(2021, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-01-16" for year in years_observed) + ) + self.assertNoHoliday(f"{year}-01-15" for year in range(1982, 2021)) + self.assertNoHolidayNameInYears(name, range(1982, 2021)) + + def test_national_heroes_and_benefactors_day(self): + name = "National Heroes and Benefactors Day" + self.assertHolidaysName( + f"{name} (Observed)", + "1982-03-08", + "1983-03-07", + "1984-03-12", + "1993-03-08", + "2000-03-06", + "2010-03-08", + "2018-03-12", + "2021-03-08", + "2022-03-07", + "2023-03-06", + ) + self.assertNonObservedHolidaysName( + name, (f"{year}-03-09" for year in range(1982, 2050)) + ) + + def test_easter_holidays(self): + self.assertHolidaysName( + "Good Friday", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + "2023-04-07", + ) + + self.assertHolidaysName( + "Holy Saturday", + "2019-04-20", + "2020-04-11", + "2021-04-03", + "2022-04-16", + "2023-04-08", + ) + + self.assertHolidayName( + "Easter Monday", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + "2023-04-10", + ) + + def test_labour_day(self): + name = "Labour Day" + years_observed = { + 1983, + 1988, + 1994, + 2005, + 2011, + 2016, + 2022, + 2033, + 2039, + 2044, + } + self.assertHolidaysName( + name, + ( + f"{year}-05-01" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-05-02" for year in years_observed) + ) + + def test_commonwealth_day(self): + name = "Commonwealth Day" + self.assertHolidaysName( + f"{name} (Observed)", + "1983-05-23", + "1984-05-21", + "1992-05-25", + "2000-05-22", + "2011-05-23", + "2018-05-21", + "2019-05-27", + "2020-05-25", + ) + self.assertNonObservedHolidaysName( + name, (f"{year}-05-24" for year in range(1982, 2022)) + ) + self.assertNoHolidayNameInYears(name, range(2022, 2050)) + + def test_emancipation_day(self): + name = "Emancipation Day" + self.assertHolidaysName( + f"{name} (Observed)", + "2021-08-02", + "2023-07-31", + "2024-07-29", + "2025-08-04", + ) + self.assertNonObservedHolidaysName( + name, (f"{year}-08-01" for year in range(2021, 2050)) + ) + self.assertNoHolidayNameInYears(name, range(1982, 2021)) + + def test_saint_georges_caye_day(self): + name = "Saint George's Caye Day" + years_observed = { + 1989, + 1995, + 2000, + 2006, + 2017, + 2023, + 2028, + 2034, + 2045, + } + self.assertHolidaysName( + name, + ( + f"{year}-09-10" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-09-11" for year in years_observed) + ) + + def test_independence_day(self): + name = "Independence Day" + years_observed = { + 1986, + 1997, + 2003, + 2008, + 2014, + 2025, + 2031, + 2036, + 2042, + } + self.assertHolidaysName( + name, + ( + f"{year}-09-21" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-09-22" for year in years_observed) + ) + + def test_indigenous_peoples_resistance_day(self): + name1 = "Pan American Day" + name2 = "Indigenous Peoples' Resistance Day" + self.assertHolidaysName( + f"{name1} (Observed)", + "1982-10-11", + "1983-10-10", + "1993-10-11", + "2000-10-09", + "2011-10-10", + "2018-10-15", + ) + self.assertHolidaysName( + f"{name2} (Observed)", + "2021-10-11", + "2022-10-10", + "2023-10-09", + "2025-10-13", + "2027-10-11", + ) + self.assertNonObservedHolidaysName( + name1, (f"{year}-10-12" for year in range(1982, 2021)) + ) + self.assertNonObservedHolidaysName( + name2, (f"{year}-10-12" for year in range(2021, 2050)) + ) + self.assertNoHolidayNameInYears(name1, range(2021, 2050)) + self.assertNoHolidayNameInYears(name2, range(1982, 2021)) + + def test_garifuna_settlement_day(self): + name = "Garifuna Settlement Day" + years_observed = { + 1989, + 1995, + 2000, + 2006, + 2017, + 2023, + 2028, + 2034, + 2045, + } + self.assertHolidaysName( + name, + ( + f"{year}-11-19" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-11-20" for year in years_observed) + ) + + def test_christmas_day(self): + self.assertHolidaysName( + "Christmas Day", (f"{year}-12-25" for year in range(1982, 2050)) + ) + + def test_boxing_day(self): + name = "Boxing Day" + years_observed = { + 1982, + 1993, + 1999, + 2004, + 2010, + 2021, + 2027, + 2032, + 2038, + 2049, + } + self.assertHolidaysName( + name, + ( + f"{year}-12-26" + for year in set(range(1982, 2050)).difference(years_observed) + ), + ) + self.assertHolidaysName( + f"{name} (Observed)", (f"{year}-12-27" for year in years_observed) + ) + + def test_2021(self): + # https://www.pressoffice.gov.bz/public-and-bank-holidays-2021-3/ + self.assertHolidays( + Belize(years=2021), + ("2021-01-01", "New Year's Day"), + ("2021-01-15", "George Price Day"), + ("2021-03-08", "National Heroes and Benefactors Day (Observed)"), + ("2021-04-02", "Good Friday"), + ("2021-04-03", "Holy Saturday"), + ("2021-04-05", "Easter Monday"), + ("2021-05-01", "Labour Day"), + ("2021-05-24", "Commonwealth Day"), + ("2021-08-02", "Emancipation Day (Observed)"), + ("2021-09-10", "Saint George's Caye Day"), + ("2021-09-21", "Independence Day"), + ("2021-10-11", "Indigenous Peoples' Resistance Day (Observed)"), + ("2021-11-19", "Garifuna Settlement Day"), + ("2021-12-25", "Christmas Day"), + ("2021-12-27", "Boxing Day (Observed)"), + ) + + def test_2022(self): + # https://www.pressoffice.gov.bz/public-and-bank-holidays-2022-updated/ + self.assertHolidays( + Belize(years=2022), + ("2022-01-01", "New Year's Day"), + ("2022-01-15", "George Price Day"), + ("2022-03-07", "National Heroes and Benefactors Day (Observed)"), + ("2022-04-15", "Good Friday"), + ("2022-04-16", "Holy Saturday"), + ("2022-04-18", "Easter Monday"), + ("2022-05-02", "Labour Day (Observed)"), + ("2022-08-01", "Emancipation Day"), + ("2022-09-10", "Saint George's Caye Day"), + ("2022-09-21", "Independence Day"), + ("2022-10-10", "Indigenous Peoples' Resistance Day (Observed)"), + ("2022-11-19", "Garifuna Settlement Day"), + ("2022-12-25", "Christmas Day"), + ("2022-12-26", "Boxing Day"), + )