From a30688e5d8d91fabadb107d45ec4a25852dd2306 Mon Sep 17 00:00:00 2001 From: Arkadii Yakovets Date: Thu, 23 Feb 2023 11:51:18 -0800 Subject: [PATCH] v.0.20 (#982) * Replace `relativedelta` with `timedelta` for days offset calculation. * Replace `relativedelta` with `timedelta` for days offset calculation. * update spain.py with changes for year 2023 * update test_spain.py * update test_spain.py * update test_spain.py * update test_spain.py * update spain.py with changes for year 2023 * update spain.py with changes for year 2023 * Import timedelta as td. * Import timedelta as td. * update spain.py with changes for year 2023 * update spain.py with changes for year 2023 * update spain.py with changes for year 2023 * update spain.py with changes for year 2023 * update spain.py with changes for year 2023 * Update holidays/countries/spain.py Co-authored-by: ~Jhellico * Montenegro optimization * Add initial PR template. * Update template. * Update template. * Change the template. * add docstring with reference to Spain * update Spain tests * remove unused constants * Add commnent with reference to Spain * fix Co-authored-by: Arkadii Yakovets * Init v.0.20 beta. * Upgrade dependency: change black version from 22.12.0 to 23.1.0. * Change holiday name separator from ", " to "; ". * Update Australia holidays: fix 2020 QLD holidays. * Jamaica holidays update * Bosnia and Herzegovina holidays update * Simplify if/else statement. * fix Co-authored-by: Arkadii Yakovets * Bolivia holidays update and refactoring * Panama holidays added * Refactor days offset calculation for recently added countries * Change some of common.TestCase methods behavior: - `TestCase::assertHolidayName - `TestCase::assertHolidaysName` - `TestCase::assertNoHolidayName` * Cuba holidays refactoring * Hong Kong fix * Thai Lunar Calendar added, exact start of holidays for historic use, refs, etc. * In-code comment improvements for readability * Add contact info in case future changes are needed * Fixed syntax error * TH Special Holidays code improvements Co-authored-by: ~Jhellico * TH in lieu holiday trigger refactor Co-authored-by: ~Jhellico * TH: turns out <= <= is now a thing Co-Authored-By: ~Jhellico * TH testcases updated Co-Authored-By: ~Jhellico * TH: case switch for standardizaton * TH autoformatting from running `tox` * TH: E266 comment block format adherence * TH: E501 line too long format adherence (except link and Thai date names for now) * TH: E501 cleanups. other final checks (for now) * TH Sort testcase date Co-authored-by: ~Jhellico * Added tests for Thailand * TH fixed Visakha Bucha trigger * TH fixed wording, add missing special election holiday Co-Authored-By: ~Jhellico * TH fixes New Year's Eve (in lieu) Co-Authored-By: ~Jhellico * TH Songkran special in lieu, fixes Queen Sirikit's bday error No, you cannot simply changes your own birthday lmao, but the case is indeed correct for Mother's Day * TH Asarnha-Buddhist Lent Day in lieu fixes * TH: holiday limiter is ; not , (1) Co-authored-by: ~Jhellico * TH: holiday limiter is ; not , (2) Co-authored-by: ~Jhellico * TH: remove redundant function (1) Co-authored-by: ~Jhellico * TH: remove redundant function (2) Co-authored-by: ~Jhellico * TH: remove redundant function (3) Co-authored-by: ~Jhellico * TH: remove redundant function (4) Co-authored-by: ~Jhellico * TH: remove useless recursive call for `add_holiday` Co-authored-by: ~Jhellico * TH: improve test code Co-authored-by: ~Jhellico * TH: remove redundant function (5) Co-Authored-By: ~Jhellico * TH: add missing `self.observed`, remove all defunct codes * TH: further simplify Asarnha Bucha trigger Co-Authored-By: ~Jhellico * TH: improve test code (2) Co-authored-by: ~Jhellico * Burundi holidays refactoring * Fix Islamic holidays calculation - fix for holidays that happen twice in a Gregorian year (primarily islamic New Year) - years range checking more strictly * Update environment: - Add Makefile, wrap common commands - Move all requirements file to `requirements` directory - Move tests from `test` to `tests` directory - Introduce `pytest-xdist`, make pytest running in parallel - Add local pre-push hook for tests - Format ci-cd.yml - Clean up pyproject.toml - Update tox.ini, make tox running in parallel - Update setup.cfg - Update CONTRIBUTION.rst instructions * Add filter warnings comment. * Fix utils tests. * Set Python version for QA job. * Run tests via 'make test'. * TH: no `self.observed` needed if they already have special in-lieus * TH: adjust this for coverall tests * docstring fix * TH: Thai lunar calendar now works up to 1941, all trigger now starts in 1941 * TH: test case refractor + extend checks to 2030 Individual Holiday's test case: - assertNoHoliday 1 year prior - assertHoliday while exists - assertNoHoliday 1 year post - asserNoHoliday for holidays_no_observed for 2010-2030 * TH: Buddhist holiday extended testcases, applying suggestions Co-Authored-By: ~Jhellico * Tests update * Update .pre-commit-config.yaml and tox.ini. * Fix imports. * Botswana observed holidays performance optimization * Burundi observed holidays performance optimization * Ukraine observed holidays performance optimization * TH: remove `_en` suffix, `__init__(self, **kwargs):` * TH: code improvements suggestions from @arkid15r Co-Authored-By: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> * TH: remove financial holiday stubs (this will be its own thing later) * TH: move sources to 2nd row, `_ThaiLuniSolar` is now in util.py * fix Co-authored-by: Arkadii Yakovets * TH: add Atthami Bucha and Ok Phansa support for * TH: fixed double `raeknakhwan` oversight Co-Authored-By: ~Jhellico * TH: `_ThaiLuniSolar` either returns date-type or None * TH: `add_holiday` --> `_add_with_observed` for unified wording * TH: `KJhellico`'s suggestions Co-Authored-By: ~Jhellico * Fix merge issues. * TH: applying `arkid15r` 's suggestions - Simplified __init__ section for Thailand's, removed for _ThaiLuniSolar - Simplified _ThaiLuniSolar holiday codes - _ThaiLuniSolar's comment are now docstrings - Move all Thailand's holiday references to above limitations' section - Remove Thailand's duplicate date checks (with TODO comments instead) - Thailand's In Line comments are also moved to each holiday's header for better readability Co-Authored-By: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> * TH: in-line single instance holidays Co-Authored-By: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> * TH: forgot to re-sort this, oof Co-authored-by: ~Jhellico * TH: fixed duplicate var, other improvements Co-Authored-By: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> * TH: clean up comments * TH: back to `@lru_cache()` again * Simplify test classes setup. Update documentation. * Exclude tests from the MANIFEST.in. * Add Marshall Islands (ISO-3666-1 code MH) * Fix Northern Mariana Islands (ISO-3666-2 code US-MP) * Adds ISO 3166-1 entries for countries that are also ISO 3166-2 subdivisions of the United States * isort fix * add TODO * Lost some pieces on the way... * MH additional testing for coverall * Update holidays/countries/united_states.py Thanks...no idea what's happening with snippets of code! Co-authored-by: ~Jhellico * Add United States Minor Outlying Islands (ISO-3666-2 code US-UM) (#940) * ISO 3166-1 for US subdivisions (#941) * Add Marshall Islands (ISO-3666-1 code MH) * Fix Northern Mariana Islands (ISO-3666-2 code US-MP) * Adds ISO 3166-1 entries for countries that are also ISO 3166-2 subdivisions of the United States * isort fix * add TODO * Lost some pieces on the way... * MH additional testing for coverall * Update holidays/countries/united_states.py Thanks...no idea what's happening with snippets of code! Co-authored-by: ~Jhellico --------- Co-authored-by: ~Jhellico Co-authored-by: dr-prodigy * Add International Women's Day for DE-MV (#936) * Add internationaler Frauentag for DE-MV * Remove trailing whitespace * Remove .gitpod.yml * Add .gitpod.yml to .gitignore * Add tests for Frauentag in DE-MV * CHANGES sync * Return `None` explicitly. (#935) * CHANGES sync * Rework i18n. * Update pre-commit settings. * Fix Thailand related changes coverage decrease. * Fix naming and minor issues in .pot files generator. * Update translations. * Add final fixes. * Add additional cases. * TH: additional testcases for the rest of Thai Lunar Holidays * Fix Ukraine tests * Fix ordering. * Add missing cases. * Rename dev env setup target. * Suppress warnings for tests. * Poland: - added historical holidays - added Ukrainian translation - refactored tests * header fix * Optimize observed holidays for Mozambique, Namibia, Zambia, Zimbabwe * Added test for Ukrainian * Update Albania observed holidays * National Day for Truth and Reconciliation in British Columbia (Canada) * Optimize observed holidays for Angola, Eswatini, Kazakhstan, Kenya, Malawi, Singapore, South Africa * fix Co-authored-by: PPsyrius <19505219+PPsyrius@users.noreply.github.com> * Localize ascii incompatible countries. Add en_US localizatin for: - Armenia - Belarus - Bulgaria - Canada - Cyprus - Ethiopia - Georgia - Greece - Japan - Russia - Serbia Update po generation files script. Update MANIFEST.in. Update README.rst. Fix packaging. * Fix headers. * fix Co-authored-by: Arkadii Yakovets * Fix mo cleanup process. * Fix compatibility issue. * Fix .po files related issues. * Add .mo files generator. Rework `TestCase` base class l10n handling. * Update Makefile. * Re-enable fallback translation. * Fix minor test issues. * Update PR template. * Update CHANGES. * Update version format. * Update CHANGES * Bump mypy version. (#970) * Fix readthedocs.io build: (#973) - Add .readthedocs.yaml. - Update .gitignore. - Update .pre-commit-config.yaml. - Update Makefile. - Update tox.ini. * Update CHANGES. * Update CHANGES * Update .rst files. --------- Co-authored-by: delaosa Co-authored-by: ~Jhellico Co-authored-by: ~Jhellico Co-authored-by: PPsyrius <19505219+PPsyrius@users.noreply.github.com> Co-authored-by: Mike Borsetti Co-authored-by: Mike Borsetti <26698111+mborsetti@users.noreply.github.com> Co-authored-by: dr-prodigy Co-authored-by: Alexander Schulze --- .github/PULL_REQUEST_TEMPLATE.md | 48 ++ .github/workflows/ci-cd.yml | 46 +- .gitignore | 9 +- .pre-commit-config.yaml | 25 +- .readthedocs.yaml | 18 + CHANGES | 51 ++ CONTRIBUTING.rst | 95 ++- MANIFEST.in | 8 +- Makefile | 44 ++ README.rst | 105 ++- holidays/__init__.py | 2 +- holidays/constants.py | 2 + holidays/countries/__init__.py | 23 + holidays/countries/albania.py | 106 ++- holidays/countries/american_samoa.py | 37 + holidays/countries/andorra.py | 10 +- holidays/countries/angola.py | 80 +- holidays/countries/argentina.py | 73 +- holidays/countries/armenia.py | 87 +-- holidays/countries/aruba.py | 20 +- holidays/countries/australia.py | 37 +- holidays/countries/austria.py | 10 +- holidays/countries/azerbaijan.py | 15 +- holidays/countries/bahrain.py | 25 +- holidays/countries/belarus.py | 69 +- holidays/countries/belgium.py | 10 +- holidays/countries/bolivia.py | 120 ++- holidays/countries/bosnia_and_herzegovina.py | 178 +++-- holidays/countries/botswana.py | 102 ++- holidays/countries/brazil.py | 9 +- holidays/countries/bulgaria.py | 79 +- holidays/countries/burundi.py | 93 +-- holidays/countries/canada.py | 199 +++-- holidays/countries/chile.py | 40 +- holidays/countries/china.py | 23 +- holidays/countries/colombia.py | 21 +- holidays/countries/croatia.py | 6 +- holidays/countries/cuba.py | 43 +- holidays/countries/curacao.py | 24 +- holidays/countries/cyprus.py | 82 +- holidays/countries/czechia.py | 6 +- holidays/countries/denmark.py | 33 +- holidays/countries/djibouti.py | 10 +- holidays/countries/dominican_republic.py | 5 +- holidays/countries/egypt.py | 15 +- holidays/countries/estonia.py | 7 +- holidays/countries/eswatini.py | 70 +- holidays/countries/ethiopia.py | 101 +-- holidays/countries/finland.py | 9 +- holidays/countries/france.py | 10 +- holidays/countries/georgia.py | 95 +-- holidays/countries/germany.py | 24 +- holidays/countries/greece.py | 62 +- holidays/countries/guam.py | 37 + holidays/countries/honduras.py | 11 +- holidays/countries/hongkong.py | 111 ++- holidays/countries/hungary.py | 30 +- holidays/countries/iceland.py | 13 +- holidays/countries/india.py | 12 +- holidays/countries/indonesia.py | 10 +- holidays/countries/ireland.py | 10 +- holidays/countries/israel.py | 50 +- holidays/countries/italy.py | 6 +- holidays/countries/jamaica.py | 79 +- holidays/countries/japan.py | 140 ++-- holidays/countries/kazakhstan.py | 96 ++- holidays/countries/kenya.py | 63 +- holidays/countries/kyrgyzstan.py | 5 +- holidays/countries/latvia.py | 6 +- holidays/countries/lesotho.py | 9 +- holidays/countries/liechtenstein.py | 16 +- holidays/countries/lithuania.py | 3 +- holidays/countries/luxembourg.py | 8 +- holidays/countries/madagascar.py | 14 +- holidays/countries/malawi.py | 45 +- holidays/countries/malaysia.py | 46 +- holidays/countries/malta.py | 4 +- holidays/countries/marshall_islands.py | 108 +++ holidays/countries/mexico.py | 18 +- holidays/countries/moldova.py | 6 +- holidays/countries/monaco.py | 20 +- holidays/countries/montenegro.py | 51 +- holidays/countries/morocco.py | 9 +- holidays/countries/mozambique.py | 50 +- holidays/countries/namibia.py | 68 +- holidays/countries/netherlands.py | 22 +- holidays/countries/new_zealand.py | 38 +- holidays/countries/nicaragua.py | 6 +- holidays/countries/nigeria.py | 17 +- holidays/countries/north_macedonia.py | 4 +- .../countries/northern_mariana_islands.py | 37 + holidays/countries/norway.py | 14 +- holidays/countries/pakistan.py | 16 +- holidays/countries/panama.py | 86 ++ holidays/countries/paraguay.py | 6 +- holidays/countries/peru.py | 8 +- holidays/countries/philippines.py | 7 +- holidays/countries/poland.py | 90 ++- holidays/countries/portugal.py | 14 +- holidays/countries/puerto_rico.py | 37 + holidays/countries/romania.py | 6 +- holidays/countries/russia.py | 37 +- holidays/countries/san_marino.py | 6 +- holidays/countries/saudi_arabia.py | 37 +- holidays/countries/serbia.py | 64 +- holidays/countries/singapore.py | 96 +-- holidays/countries/slovakia.py | 6 +- holidays/countries/slovenia.py | 10 +- holidays/countries/south_africa.py | 75 +- holidays/countries/south_korea.py | 21 +- holidays/countries/spain.py | 201 ++--- holidays/countries/sweden.py | 11 +- holidays/countries/switzerland.py | 21 +- holidays/countries/taiwan.py | 13 +- holidays/countries/thailand.py | 734 ++++++++++++++---- holidays/countries/tunisia.py | 13 +- holidays/countries/turkey.py | 13 +- holidays/countries/ukraine.py | 160 ++-- holidays/countries/united_arab_emirates.py | 24 +- holidays/countries/united_kingdom.py | 19 +- holidays/countries/united_states.py | 82 +- .../united_states_minor_outlying_islands.py | 37 + .../countries/united_states_virgin_islands.py | 37 + holidays/countries/uruguay.py | 14 +- holidays/countries/vatican_city.py | 4 +- holidays/countries/venezuela.py | 10 +- holidays/countries/vietnam.py | 9 +- holidays/countries/zambia.py | 47 +- holidays/countries/zimbabwe.py | 58 +- holidays/financial/european_central_bank.py | 6 +- holidays/financial/ny_stock_exchange.py | 19 +- holidays/holiday_base.py | 372 ++++++--- holidays/locale/am/LC_MESSAGES/ET.po | 86 ++ holidays/locale/be/LC_MESSAGES/BY.po | 61 ++ holidays/locale/bg/LC_MESSAGES/BG.po | 85 ++ holidays/locale/da/LC_MESSAGES/DK.po | 64 ++ holidays/locale/el/LC_MESSAGES/CY.po | 96 +++ holidays/locale/el/LC_MESSAGES/GR.po | 76 ++ holidays/locale/en/LC_MESSAGES/CA.po | 150 ++++ holidays/locale/en_US/LC_MESSAGES/AM.po | 92 +++ holidays/locale/en_US/LC_MESSAGES/AR.po | 100 +++ holidays/locale/en_US/LC_MESSAGES/BG.po | 86 ++ holidays/locale/en_US/LC_MESSAGES/BY.po | 61 ++ holidays/locale/en_US/LC_MESSAGES/CA.po | 150 ++++ holidays/locale/en_US/LC_MESSAGES/CY.po | 97 +++ holidays/locale/en_US/LC_MESSAGES/DK.po | 64 ++ holidays/locale/en_US/LC_MESSAGES/ET.po | 87 +++ holidays/locale/en_US/LC_MESSAGES/GE.po | 101 +++ holidays/locale/en_US/LC_MESSAGES/GR.po | 76 ++ holidays/locale/en_US/LC_MESSAGES/JP.po | 127 +++ holidays/locale/en_US/LC_MESSAGES/PL.po | 102 +++ holidays/locale/en_US/LC_MESSAGES/RS.po | 68 ++ holidays/locale/en_US/LC_MESSAGES/RU.po | 62 ++ holidays/locale/en_US/LC_MESSAGES/UA.po | 107 +++ holidays/locale/es/LC_MESSAGES/AR.po | 99 +++ holidays/locale/fr/LC_MESSAGES/CA.po | 146 ++++ holidays/locale/hy/LC_MESSAGES/AM.po | 91 +++ holidays/locale/ja/LC_MESSAGES/JP.po | 127 +++ holidays/locale/ka/LC_MESSAGES/GE.po | 101 +++ holidays/locale/pl/LC_MESSAGES/PL.po | 100 +++ holidays/locale/ru/LC_MESSAGES/RU.po | 61 ++ holidays/locale/sr/LC_MESSAGES/RS.po | 68 ++ holidays/locale/uk/LC_MESSAGES/PL.po | 102 +++ holidays/locale/uk/LC_MESSAGES/UA.po | 104 +++ holidays/utils.py | 490 ++++++++++-- pyproject.toml | 16 +- requirements_dev.txt => requirements/dev.txt | 13 +- .../requirements.txt => requirements/docs.txt | 3 +- scripts/l10n/generate_mo_files.py | 46 ++ scripts/l10n/generate_po_files.py | 119 +++ scripts/l10n/msgfmt.py | 246 ++++++ setup.cfg | 17 +- setup.py | 29 +- test/countries/test_albania.py | 65 -- test/countries/test_bolivia.py | 264 ------- test/countries/test_bosnia_and_herzegovina.py | 295 ------- test/countries/test_botswana.py | 64 -- test/countries/test_burundi.py | 92 --- test/countries/test_cuba.py | 306 -------- test/countries/test_cyprus.py | 132 ---- test/countries/test_denmark.py | 31 - test/countries/test_eswatini.py | 71 -- test/countries/test_jamaica.py | 87 --- test/countries/test_kenya.py | 50 -- test/countries/test_malawi.py | 47 -- test/countries/test_mozambique.py | 54 -- test/countries/test_namibia.py | 63 -- test/countries/test_poland.py | 68 -- test/countries/test_spain.py | 274 ------- test/countries/test_thailand.py | 81 -- test/countries/test_ukraine.py | 263 ------- test/countries/test_zambia.py | 81 -- test/countries/test_zimbabwe.py | 63 -- {test => tests}/__init__.py | 0 {test => tests}/common.py | 49 +- {test => tests}/countries/__init__.py | 0 tests/countries/test_albania.py | 226 ++++++ tests/countries/test_american_samoa.py | 37 + {test => tests}/countries/test_andorra.py | 2 +- {test => tests}/countries/test_angola.py | 81 +- {test => tests}/countries/test_argentina.py | 122 +-- {test => tests}/countries/test_armenia.py | 36 +- {test => tests}/countries/test_aruba.py | 0 {test => tests}/countries/test_australia.py | 33 +- {test => tests}/countries/test_austria.py | 25 +- {test => tests}/countries/test_azerbaijan.py | 2 +- {test => tests}/countries/test_bahrain.py | 6 +- {test => tests}/countries/test_bangladesh.py | 0 {test => tests}/countries/test_belarus.py | 34 +- {test => tests}/countries/test_belgium.py | 0 tests/countries/test_bolivia.py | 276 +++++++ .../countries/test_bosnia_and_herzegovina.py | 290 +++++++ tests/countries/test_botswana.py | 182 +++++ {test => tests}/countries/test_brazil.py | 6 +- {test => tests}/countries/test_bulgaria.py | 49 +- tests/countries/test_burundi.py | 203 +++++ {test => tests}/countries/test_canada.py | 175 +++-- {test => tests}/countries/test_chile.py | 124 ++- {test => tests}/countries/test_china.py | 0 {test => tests}/countries/test_colombia.py | 5 +- {test => tests}/countries/test_croatia.py | 0 tests/countries/test_cuba.py | 273 +++++++ {test => tests}/countries/test_curacao.py | 0 tests/countries/test_cyprus.py | 143 ++++ {test => tests}/countries/test_czechia.py | 0 tests/countries/test_denmark.py | 60 ++ {test => tests}/countries/test_djibouti.py | 3 +- .../countries/test_dominican_republic.py | 2 +- {test => tests}/countries/test_egypt.py | 3 +- {test => tests}/countries/test_estonia.py | 0 tests/countries/test_eswatini.py | 125 +++ {test => tests}/countries/test_ethiopia.py | 43 +- {test => tests}/countries/test_finland.py | 0 {test => tests}/countries/test_france.py | 0 {test => tests}/countries/test_georgia.py | 32 +- {test => tests}/countries/test_germany.py | 45 +- {test => tests}/countries/test_greece.py | 77 +- tests/countries/test_guam.py | 37 + {test => tests}/countries/test_honduras.py | 4 +- {test => tests}/countries/test_hongkong.py | 2 - {test => tests}/countries/test_hungary.py | 0 {test => tests}/countries/test_iceland.py | 0 {test => tests}/countries/test_india.py | 3 +- {test => tests}/countries/test_indonesia.py | 2 +- {test => tests}/countries/test_ireland.py | 13 +- {test => tests}/countries/test_isle_of_man.py | 0 {test => tests}/countries/test_israel.py | 23 +- {test => tests}/countries/test_italy.py | 0 tests/countries/test_jamaica.py | 156 ++++ {test => tests}/countries/test_japan.py | 49 +- {test => tests}/countries/test_kazakhstan.py | 93 ++- tests/countries/test_kenya.py | 165 ++++ {test => tests}/countries/test_kyrgyzstan.py | 2 +- {test => tests}/countries/test_latvia.py | 0 {test => tests}/countries/test_lesotho.py | 0 .../countries/test_liechtenstein.py | 0 {test => tests}/countries/test_lithuania.py | 0 {test => tests}/countries/test_luxembourg.py | 0 {test => tests}/countries/test_madagascar.py | 0 tests/countries/test_malawi.py | 112 +++ {test => tests}/countries/test_malaysia.py | 0 {test => tests}/countries/test_malta.py | 0 tests/countries/test_marshall_islands.py | 65 ++ {test => tests}/countries/test_mexico.py | 35 +- {test => tests}/countries/test_moldova.py | 0 {test => tests}/countries/test_monaco.py | 2 +- {test => tests}/countries/test_montenegro.py | 6 +- {test => tests}/countries/test_morocco.py | 5 +- tests/countries/test_mozambique.py | 87 +++ tests/countries/test_namibia.py | 96 +++ {test => tests}/countries/test_netherlands.py | 0 {test => tests}/countries/test_new_zealand.py | 19 +- {test => tests}/countries/test_nicaragua.py | 0 {test => tests}/countries/test_nigeria.py | 0 .../countries/test_north_macedonia.py | 0 .../test_northern_mariana_islands.py | 41 + {test => tests}/countries/test_norway.py | 2 +- {test => tests}/countries/test_pakistan.py | 15 +- tests/countries/test_panama.py | 117 +++ {test => tests}/countries/test_paraguay.py | 7 +- {test => tests}/countries/test_peru.py | 0 {test => tests}/countries/test_philippines.py | 2 +- tests/countries/test_poland.py | 283 +++++++ {test => tests}/countries/test_portugal.py | 0 tests/countries/test_puerto_rico.py | 37 + {test => tests}/countries/test_romania.py | 0 {test => tests}/countries/test_russia.py | 34 +- {test => tests}/countries/test_san_marino.py | 2 +- .../countries/test_saudi_arabia.py | 0 {test => tests}/countries/test_serbia.py | 39 +- {test => tests}/countries/test_singapore.py | 0 {test => tests}/countries/test_slovakia.py | 0 {test => tests}/countries/test_slovenia.py | 0 .../countries/test_south_africa.py | 0 {test => tests}/countries/test_south_korea.py | 0 tests/countries/test_spain.py | 324 ++++++++ {test => tests}/countries/test_sweden.py | 2 +- {test => tests}/countries/test_switzerland.py | 0 {test => tests}/countries/test_taiwan.py | 0 tests/countries/test_thailand.py | 510 ++++++++++++ {test => tests}/countries/test_tunisia.py | 4 +- {test => tests}/countries/test_turkey.py | 0 tests/countries/test_ukraine.py | 466 +++++++++++ .../countries/test_united_arab_emirates.py | 3 +- .../countries/test_united_kingdom.py | 25 +- .../countries/test_united_states.py | 118 ++- ...st_united_states_minor_outlying_islands.py | 39 + .../test_united_states_virgin_islands.py | 41 + {test => tests}/countries/test_uruguay.py | 31 +- {test => tests}/countries/test_uzbekistan.py | 0 .../countries/test_vatican_city.py | 2 +- {test => tests}/countries/test_venezuela.py | 5 +- {test => tests}/countries/test_vietnam.py | 15 +- tests/countries/test_zambia.py | 147 ++++ tests/countries/test_zimbabwe.py | 119 +++ {test => tests}/financial/__init__.py | 0 .../financial/test_european_central_bank.py | 21 +- .../financial/test_ny_stock_exchange.py | 114 +-- {test => tests}/test_docs.py | 55 +- {test => tests}/test_holiday_base.py | 195 ++--- {test => tests}/test_imports.py | 3 +- tests/test_utils.py | 197 +++++ tox.ini | 29 +- 323 files changed, 13895 insertions(+), 5660 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .readthedocs.yaml create mode 100644 Makefile create mode 100644 holidays/countries/american_samoa.py create mode 100644 holidays/countries/guam.py create mode 100644 holidays/countries/marshall_islands.py create mode 100644 holidays/countries/northern_mariana_islands.py create mode 100644 holidays/countries/panama.py create mode 100644 holidays/countries/puerto_rico.py create mode 100644 holidays/countries/united_states_minor_outlying_islands.py create mode 100644 holidays/countries/united_states_virgin_islands.py create mode 100644 holidays/locale/am/LC_MESSAGES/ET.po create mode 100644 holidays/locale/be/LC_MESSAGES/BY.po create mode 100644 holidays/locale/bg/LC_MESSAGES/BG.po create mode 100644 holidays/locale/da/LC_MESSAGES/DK.po create mode 100644 holidays/locale/el/LC_MESSAGES/CY.po create mode 100644 holidays/locale/el/LC_MESSAGES/GR.po create mode 100644 holidays/locale/en/LC_MESSAGES/CA.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/AM.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/AR.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/BG.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/BY.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/CA.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/CY.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/DK.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/ET.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/GE.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/GR.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/JP.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/PL.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/RS.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/RU.po create mode 100644 holidays/locale/en_US/LC_MESSAGES/UA.po create mode 100644 holidays/locale/es/LC_MESSAGES/AR.po create mode 100644 holidays/locale/fr/LC_MESSAGES/CA.po create mode 100644 holidays/locale/hy/LC_MESSAGES/AM.po create mode 100644 holidays/locale/ja/LC_MESSAGES/JP.po create mode 100644 holidays/locale/ka/LC_MESSAGES/GE.po create mode 100644 holidays/locale/pl/LC_MESSAGES/PL.po create mode 100644 holidays/locale/ru/LC_MESSAGES/RU.po create mode 100644 holidays/locale/sr/LC_MESSAGES/RS.po create mode 100644 holidays/locale/uk/LC_MESSAGES/PL.po create mode 100644 holidays/locale/uk/LC_MESSAGES/UA.po rename requirements_dev.txt => requirements/dev.txt (60%) rename docs/requirements.txt => requirements/docs.txt (55%) create mode 100755 scripts/l10n/generate_mo_files.py create mode 100755 scripts/l10n/generate_po_files.py create mode 100755 scripts/l10n/msgfmt.py delete mode 100644 test/countries/test_albania.py delete mode 100644 test/countries/test_bolivia.py delete mode 100644 test/countries/test_bosnia_and_herzegovina.py delete mode 100644 test/countries/test_botswana.py delete mode 100644 test/countries/test_burundi.py delete mode 100644 test/countries/test_cuba.py delete mode 100644 test/countries/test_cyprus.py delete mode 100644 test/countries/test_denmark.py delete mode 100644 test/countries/test_eswatini.py delete mode 100644 test/countries/test_jamaica.py delete mode 100644 test/countries/test_kenya.py delete mode 100644 test/countries/test_malawi.py delete mode 100644 test/countries/test_mozambique.py delete mode 100644 test/countries/test_namibia.py delete mode 100644 test/countries/test_poland.py delete mode 100644 test/countries/test_spain.py delete mode 100644 test/countries/test_thailand.py delete mode 100644 test/countries/test_ukraine.py delete mode 100644 test/countries/test_zambia.py delete mode 100644 test/countries/test_zimbabwe.py rename {test => tests}/__init__.py (100%) rename {test => tests}/common.py (84%) rename {test => tests}/countries/__init__.py (100%) create mode 100644 tests/countries/test_albania.py create mode 100644 tests/countries/test_american_samoa.py rename {test => tests}/countries/test_andorra.py (99%) rename {test => tests}/countries/test_angola.py (59%) rename {test => tests}/countries/test_argentina.py (73%) rename {test => tests}/countries/test_armenia.py (72%) rename {test => tests}/countries/test_aruba.py (100%) rename {test => tests}/countries/test_australia.py (95%) rename {test => tests}/countries/test_austria.py (77%) rename {test => tests}/countries/test_azerbaijan.py (99%) rename {test => tests}/countries/test_bahrain.py (94%) rename {test => tests}/countries/test_bangladesh.py (100%) rename {test => tests}/countries/test_belarus.py (63%) rename {test => tests}/countries/test_belgium.py (100%) create mode 100644 tests/countries/test_bolivia.py create mode 100644 tests/countries/test_bosnia_and_herzegovina.py create mode 100644 tests/countries/test_botswana.py rename {test => tests}/countries/test_brazil.py (98%) rename {test => tests}/countries/test_bulgaria.py (65%) create mode 100644 tests/countries/test_burundi.py rename {test => tests}/countries/test_canada.py (69%) rename {test => tests}/countries/test_chile.py (79%) rename {test => tests}/countries/test_china.py (100%) rename {test => tests}/countries/test_colombia.py (99%) rename {test => tests}/countries/test_croatia.py (100%) create mode 100644 tests/countries/test_cuba.py rename {test => tests}/countries/test_curacao.py (100%) create mode 100644 tests/countries/test_cyprus.py rename {test => tests}/countries/test_czechia.py (100%) create mode 100644 tests/countries/test_denmark.py rename {test => tests}/countries/test_djibouti.py (93%) rename {test => tests}/countries/test_dominican_republic.py (99%) rename {test => tests}/countries/test_egypt.py (96%) rename {test => tests}/countries/test_estonia.py (100%) create mode 100644 tests/countries/test_eswatini.py rename {test => tests}/countries/test_ethiopia.py (71%) rename {test => tests}/countries/test_finland.py (100%) rename {test => tests}/countries/test_france.py (100%) rename {test => tests}/countries/test_georgia.py (56%) rename {test => tests}/countries/test_germany.py (92%) rename {test => tests}/countries/test_greece.py (52%) create mode 100644 tests/countries/test_guam.py rename {test => tests}/countries/test_honduras.py (96%) rename {test => tests}/countries/test_hongkong.py (99%) rename {test => tests}/countries/test_hungary.py (100%) rename {test => tests}/countries/test_iceland.py (100%) rename {test => tests}/countries/test_india.py (98%) rename {test => tests}/countries/test_indonesia.py (99%) rename {test => tests}/countries/test_ireland.py (89%) rename {test => tests}/countries/test_isle_of_man.py (100%) rename {test => tests}/countries/test_israel.py (83%) rename {test => tests}/countries/test_italy.py (100%) create mode 100644 tests/countries/test_jamaica.py rename {test => tests}/countries/test_japan.py (93%) rename {test => tests}/countries/test_kazakhstan.py (85%) create mode 100644 tests/countries/test_kenya.py rename {test => tests}/countries/test_kyrgyzstan.py (98%) rename {test => tests}/countries/test_latvia.py (100%) rename {test => tests}/countries/test_lesotho.py (100%) rename {test => tests}/countries/test_liechtenstein.py (100%) rename {test => tests}/countries/test_lithuania.py (100%) rename {test => tests}/countries/test_luxembourg.py (100%) rename {test => tests}/countries/test_madagascar.py (100%) create mode 100644 tests/countries/test_malawi.py rename {test => tests}/countries/test_malaysia.py (100%) rename {test => tests}/countries/test_malta.py (100%) create mode 100644 tests/countries/test_marshall_islands.py rename {test => tests}/countries/test_mexico.py (86%) rename {test => tests}/countries/test_moldova.py (100%) rename {test => tests}/countries/test_monaco.py (98%) rename {test => tests}/countries/test_montenegro.py (94%) rename {test => tests}/countries/test_morocco.py (94%) create mode 100644 tests/countries/test_mozambique.py create mode 100644 tests/countries/test_namibia.py rename {test => tests}/countries/test_netherlands.py (100%) rename {test => tests}/countries/test_new_zealand.py (97%) rename {test => tests}/countries/test_nicaragua.py (100%) rename {test => tests}/countries/test_nigeria.py (100%) rename {test => tests}/countries/test_north_macedonia.py (100%) create mode 100644 tests/countries/test_northern_mariana_islands.py rename {test => tests}/countries/test_norway.py (98%) rename {test => tests}/countries/test_pakistan.py (95%) create mode 100644 tests/countries/test_panama.py rename {test => tests}/countries/test_paraguay.py (96%) rename {test => tests}/countries/test_peru.py (100%) rename {test => tests}/countries/test_philippines.py (98%) create mode 100644 tests/countries/test_poland.py rename {test => tests}/countries/test_portugal.py (100%) create mode 100644 tests/countries/test_puerto_rico.py rename {test => tests}/countries/test_romania.py (100%) rename {test => tests}/countries/test_russia.py (51%) rename {test => tests}/countries/test_san_marino.py (98%) rename {test => tests}/countries/test_saudi_arabia.py (100%) rename {test => tests}/countries/test_serbia.py (69%) rename {test => tests}/countries/test_singapore.py (100%) rename {test => tests}/countries/test_slovakia.py (100%) rename {test => tests}/countries/test_slovenia.py (100%) rename {test => tests}/countries/test_south_africa.py (100%) rename {test => tests}/countries/test_south_korea.py (100%) create mode 100644 tests/countries/test_spain.py rename {test => tests}/countries/test_sweden.py (99%) rename {test => tests}/countries/test_switzerland.py (100%) rename {test => tests}/countries/test_taiwan.py (100%) create mode 100644 tests/countries/test_thailand.py rename {test => tests}/countries/test_tunisia.py (92%) rename {test => tests}/countries/test_turkey.py (100%) create mode 100644 tests/countries/test_ukraine.py rename {test => tests}/countries/test_united_arab_emirates.py (95%) rename {test => tests}/countries/test_united_kingdom.py (90%) rename {test => tests}/countries/test_united_states.py (92%) create mode 100644 tests/countries/test_united_states_minor_outlying_islands.py create mode 100644 tests/countries/test_united_states_virgin_islands.py rename {test => tests}/countries/test_uruguay.py (86%) rename {test => tests}/countries/test_uzbekistan.py (100%) rename {test => tests}/countries/test_vatican_city.py (98%) rename {test => tests}/countries/test_venezuela.py (98%) rename {test => tests}/countries/test_vietnam.py (95%) create mode 100644 tests/countries/test_zambia.py create mode 100644 tests/countries/test_zimbabwe.py rename {test => tests}/financial/__init__.py (100%) rename {test => tests}/financial/test_european_central_bank.py (82%) rename {test => tests}/financial/test_ny_stock_exchange.py (80%) rename {test => tests}/test_docs.py (70%) rename {test => tests}/test_holiday_base.py (84%) rename {test => tests}/test_imports.py (97%) create mode 100644 tests/test_utils.py diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..1b182740c --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,48 @@ + + +## Proposed change + + + +Your PR description goes here. + +## Type of change + + + +- [ ] New country holidays support (thank you!) +- [ ] Supported country holidays update (calendar discrepancy fix, localization) +- [ ] Existing code/tests/processes improvement (best practice, refactoring, optimization) +- [ ] Dependency upgrade (version update) +- [ ] Bugfix (non-breaking change which fixes an issue) +- [ ] Breaking change (a code change causing existing functionality to break) +- [ ] New feature (adds functionality to python-holidays in general) + +## Checklist + + + +- [ ] I've followed the [contributing guidelines][contributing-guidelines] +- [ ] This PR is filed against `beta` branch of the repository +- [ ] This PR doesn't contain any merge conflicts +- [ ] The code style looks good (`make pre-commit`) +- [ ] I've added tests to verify that the new code works and all tests pass locally (`make test`) +- [ ] The related [documentation][docs] has been added/updated (check off the box for free if no updates is required) + + + +[contributing-guidelines]: https://github.com/dr-prodigy/python-holidays/blob/beta/CONTRIBUTING.rst +[docs]: https://github.com/dr-prodigy/python-holidays/tree/beta/docs/source diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 409008369..8bbda6fc3 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,4 +1,4 @@ -name: "Tests" +name: Tests on: [push, pull_request, workflow_dispatch] env: @@ -9,38 +9,40 @@ jobs: name: Run Quality Assurance runs-on: ubuntu-latest steps: - - name: Check out repo + - name: Check Out Repository uses: actions/checkout@v3 - - name: Set up Python + - name: Set Up Python uses: actions/setup-python@v4.5.0 + with: + python-version: '3.11' - name: Run pre-commit uses: pre-commit/action@v3.0.0 test: - name: "Test: python=${{ matrix.python-version }} on ${{ matrix.os }}" + name: 'Test: Python=${{ matrix.python-version }} on ${{ matrix.os }}' runs-on: ${{ matrix.os }} needs: [pre-commit] strategy: matrix: os: [ubuntu-latest, windows-latest, macOS-latest] - python-version: ["3.7", "3.8", "3.9", "3.10", "pypy-3.7"] + python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.7'] steps: - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} + - name: Set Up Python ${{ matrix.python-version }} uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.python-version }} cache: pip - cache-dependency-path: requirements_dev.txt - - name: Install dependencies + cache-dependency-path: requirements/dev.txt + - name: Install Dependencies run: | python -m pip install -U pip wheel 'coveralls>=3' - python -m pip install -U -r requirements_dev.txt + python -m pip install -U -r requirements/dev.txt python -m pip install -e . - - name: Run tests + - name: Run Tests run: | - pytest + make test - name: Upload Coverage run: coveralls --service=github env: @@ -54,12 +56,12 @@ jobs: runs-on: ubuntu-latest container: python:3-slim steps: - - name: Finished - run: | - pip3 install -U 'coveralls>=3' - coveralls --finish --service=github - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Finished + run: | + pip3 install -U 'coveralls>=3' + coveralls --finish --service=github + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} deploy: runs-on: ubuntu-latest @@ -67,19 +69,19 @@ jobs: needs: [test] steps: - uses: actions/checkout@v3 - - name: Set up Python 3.9 + - name: Set Up Python uses: actions/setup-python@v4.5.0 with: - python-version: "3.10" - - name: Install dependencies + python-version: '3.11' + - name: Install Dependencies run: | python -m pip install -U pip wheel pip install -U . - - name: Build dist + - name: Build Distribution run: | python setup.py sdist bdist_wheel - - name: Publish package + - name: Publish Package uses: pypa/gh-action-pypi-publish@v1.6.4 with: user: __token__ diff --git a/.gitignore b/.gitignore index 230a6138a..3e318164d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,22 @@ -build/ +build/* dist/ venv/ MANIFEST .coverage *.egg-info +*.mo +*.pot *.pyc *.DS_Store coverage.xml .tox .venv -docs/_build -docs/source/_build +docs/build +holidays/locale/pot # IDE Stuff .idea .vscode/ *.code-workspace Pipfile +.gitpod.yml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6ab43cd59..35aa34989 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,17 +4,19 @@ repos: hooks: - id: check-ast - id: check-builtin-literals + - id: check-yaml - id: end-of-file-fixer - - id: trailing-whitespace - id: fix-encoding-pragma args: [--remove] - id: mixed-line-ending args: [--fix=lf] + - id: trailing-whitespace - repo: https://github.com/python/black - rev: 22.12.0 + rev: 23.1.0 hooks: - id: black + exclude: ^(docs|scripts/l10n/msgfmt.py) language_version: python3 - repo: https://github.com/pycqa/flake8 @@ -24,15 +26,19 @@ repos: additional_dependencies: - flake8-print args: [--max-line-length=79] + exclude: ^(docs|scripts/l10n/msgfmt.py) - repo: https://github.com/pre-commit/mirrors-isort rev: v5.10.1 hooks: - id: isort - exclude: ^docs/ + # holidays/countries/__init__.py is excluded due to a bug whereby + # black and isort don't agree and enter into an infinite fix loop. + # TODO remove this exclusion when isort and black play nice again. + exclude: ^(docs|holidays/countries/__init__.py|scripts/l10n/msgfmt.py) - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.991 + rev: v1.0.1 hooks: - id: mypy additional_dependencies: [types-all] @@ -56,3 +62,14 @@ repos: rev: v2.2.0 hooks: - id: setup-cfg-fmt + + - repo: local + hooks: + - id: tests + always_run: true + entry: make test + language: system + name: run tests + pass_filenames: false + stages: + - push diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..5b45556c8 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,18 @@ +# Read the Docs configuration file. +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details. + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: '3.11' + +python: + install: + - requirements: requirements/docs.txt + +sphinx: + builder: html + configuration: docs/source/conf.py + fail_on_warning: true diff --git a/CHANGES b/CHANGES index 1c8c318c0..e6fc6c852 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,54 @@ +Version 0.20 +============ + +Released February 23, 2023 + +- Add localization support, #827 (@arkid15r, @bkthomps, @dragoon) +- Introduce `HolidayBase::_is_leap_year()`, #886 (@arkid15r) +- Introduce `HolidayBase::_is_monday` - `HolidayBase::_is_sunday` helper methods, #841 (@arkid15r) +- Refactor Burundi holidays, #925 (@KJhellico) +- Refactor Cuba holidays, #927 (@KJhellico) +- Refactor HolidayBase class and utils, #815 (@arkid15r) +- Refactor common.TestCase, #926 (@arkid15r) +- Refactor days offset calculation for recently added countries, #924 (@KJhellico) +- Refactor days offset calculation: replace `relativedelta` with `timedelta` (tests), #901 (@arkid15r) +- Refactor days offset calculation: replace `relativedelta` with `timedelta`, #900 (@arkid15r) +- Refactor implicit returns, #935 (@arkid15r) +- Add Panama holidays, #916 (@KJhellico) +- Localize ascii incompatible countries, #955 (@arkid15r) +- Change holiday name separator from ", " to "; ", #922 (@arkid15r) +- Fix Hong Kong, #928 (@KJhellico) +- Fix Islamic holidays calculation, #914 (@KJhellico) +- Fix Thailand related changes coverage decrease, #942 (@arkid15r, @PPsyrius) +- Fix Ukraine tests, #943 (@KJhellico) +- Fix readthedocs.io build, #973 (@arkid15r) +- Improve Thailand holidays, #929 (@PPsyrius, @arkid15r, @KJhellico) +- Optimize Botswana observed holidays, #932 (@KJhellico) +- Optimize Burundi observed holidays, #933 (@KJhellico) +- Optimize Montenegro: observed holidays, #908 (@KJhellico) +- Optimize Ukraine observed holidays, #934 (@KJhellico) +- Optimize observed holidays, part 1, #949 (@KJhellico) +- Optimize observed holidays, part 2, #952 (@KJhellico) +- Update Albania observed holidays, #950 (@KJhellico) +- Update Australia holidays: fix 2020 QLD holidays, #923 (@arkid15r) +- Update Bolivia holidays, #910 (@KJhellico) +- Update Bosnia and Herzegovina holidays, #909 (@KJhellico) +- Update Canada holidays (add National Day for Truth and Reconciliation in British Columbia), #951 (@KJhellico) +- Update Jamaica holidays, #913 (@KJhellico) +- Update PR template, #960 (@arkid15r) +- Update Poland holidays, add uk localization, #947 (@KJhellico) +- Update dev/test environments, #930 (@arkid15r) +- Upgrade dependency: change black version from 22.12.0 to 23.1.0, #921 (@arkid15r) +- Upgrade pre-commit config: mypy v1.0.1, #970 (@arkid15r) +- Add GitHub pull request template, #911 (@arkid15r) +- Add International Women's Day for DE-MV, #936 (@alexanderschulze) +- Add Marshall Islands (ISO-3666-1 code MH), #937 (@mborsetti) +- Add Northern Mariana Islands (ISO-3666-2 code US-MP), #939 (@mborsetti) +- Add United States Minor Outlying Islands (ISO-3666-2 code US-UM), #940 (@mborsetti) +- ISO 3166-1 for US subdivisions, #941 (@mborsetti, @dr-prodigy) +- Rename dev env setup target, #944 (@arkid15r) +- Suppress warnings for tests, #945 (@arkid15r) + Version 0.19 ============ diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 265411f33..0cb6c3083 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -17,8 +17,9 @@ Basics When contributing with fixes and new features, please start forking/branching from the `beta branch`_ to work on the latest code and reduce merging issues. -Contributed PRs_ are required to include valid test coverage **(95% minimum, -100% whenever possible)** in order to be merged. +Contributed PRs_ are required to include valid test coverage **(the goal is +100% coverage)** in order to be merged. Please don't hesitate to ask for +help if you'read struggling with tests. Thanks a lot for your support. @@ -26,45 +27,91 @@ Thanks a lot for your support. Running tests ------------- -First step is installing all the required dependencies with: +First step is setting up development environment and installing all the required dependencies with: -.. code-block:: bash +.. code-block:: shell - $ pip install -r requirements_dev.txt + $ virtualenv -p python3 venv + $ source venv/bin/activate -The project provides automated tests and coverage checks with tox; just run: + $ make setup -.. code-block:: bash +The project provides automated style, tests and coverage checks: - $ tox +.. code-block:: shell -Alternatively, you can run pytest to run tests and coverage: + $ make check -.. code-block:: bash +You can run them separately: - $ python -m pytest . - # if you want to retrieve uncovered lines too: - $ python -m pytest --cov-report term-missing . +.. code-block:: shell -In addition to pytest, you need to ensure that all staged files are up to -standard. + $ make pre-commit + $ make test -.. _pre-commit: https://github.com/dr-prodigy/python-holidays/issues +If you want to retrieve uncovered lines too: -Install `pre-commit`_ and its git hook script so that the quality assurance -tests will run on all staged files before they are committed: +.. code-block:: shell -.. code-block:: bash + $ make coverage - $ pip install pre-commit - $ pre-commit install +You can specific tests using ``pytest`` command: -To manually run the quality assurance tests on all tracked files: +.. code-block:: shell -.. code-block:: bash + $ pytest tests/countries/test_argentina.py - $ pre-commit run -a +Or even more granular: +.. code-block:: shell + + $ pytest tests/countries/test_argentina.py::TestArgentina::test_country_aliases + +Due to how pytest-xdist is implemented, the -s/--capture=no option +`doesn't work `_. +Use pytest directly if you need ``-s`` option: + +.. code-block:: shell + + $ pytest -s tests/countries/test_argentina.py + + +Localization +-------------------------- +.. _ISO 639-1 codes: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + +In order to add or update existing holiday names translation you'll need to +generate pygettext .pot file first: + +.. code-block:: shell + + $ make l10n + +If the template file is empty make sure that the country/market entity has the +``default_language`` attribute set and all holiday names are wrapped +with ``tr``/``self.tr`` helpers. Use `ISO 639-1 codes`_ when adding new +languages. Copy the generated template to all locale folders you're going to +translate this country holiday names into (e.g., for Argentina: +holidays/locale/en/LC_MESSAGES/AR.po - note the file extension difference here). +Also copy the template to a default country language folder (e.g., for Argentina +holidays/locale/es/LC_MESSAGES) and leave it as is. After copying the .po files +open them with your favorite .po file editor and translate accordingly. Don't +forget to fill in the translation file headers. Finally, update the list of +supported translations for the country in the README.rst. + +If the translation already exists you'll just need to update it with the new +template entries (your .po file editor may help you to do that with no hassle). + +Please also add tests (see already translated countries tests for examples). +The .mo files are generated automatically for the tests and the python-holidays +package so you shouldn't worry about it. Just don't forget to +initialize the ``setUpClass`` properly: + +.. code-block:: python + + @classmethod + def setUpClass(cls): + super().setUpClass(Argentina) Build sphinx documentation -------------------------- diff --git a/MANIFEST.in b/MANIFEST.in index ffcb30b80..6cbbf6938 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,9 @@ +exclude tests/* +include *.mo include *.py +include *.po include *.rst -include LICENSE include CHANGES -include py.typed +include holidays/py.typed +include LICENSE +include scripts/l10n/msgfmt.py diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..19bd62855 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +help: + @echo "Usage: make " + @echo " check run pre-commit and tests" + @echo " coverage identify code not covered with tests" + @echo " help show summary of available commands" + @echo " l10n update .pot and .po files" + @echo " pre-commit run pre-commit against all files" + @echo " setup setup development environment" + @echo " test run tests (in parallel)" + @echo " tox run tox (in parallel)" + +check: + make pre-commit + make doc + make test + +coverage: + pytest --cov=. --cov-config=pyproject.toml --cov-report term-missing --no-cov-on-fail --numprocesses auto + +doc: + sphinx-build -E -T -W -b html -D language=en -j auto -q docs/source docs/build + +l10n: + mkdir -p holidays/locale/pot + scripts/l10n/generate_po_files.py + scripts/l10n/generate_mo_files.py + +pre-commit: + pre-commit run --all-files + +setup: + pip install --upgrade pip + pip install --requirement requirements/dev.txt + pip install --requirement requirements/docs.txt + pre-commit install --hook-type pre-commit + pre-commit install --hook-type pre-push + make l10n + +test: + scripts/l10n/generate_mo_files.py + pytest --cov=. --cov-config=pyproject.toml --cov-report term --cov-report xml --durations 10 --durations-min=0.75 --no-cov-on-fail --numprocesses auto + +tox: + tox --parallel auto diff --git a/README.rst b/README.rst index e354dba0e..f772edfc2 100644 --- a/README.rst +++ b/README.rst @@ -105,10 +105,12 @@ 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 111 countries. The standard way to refer to a country is by -using its `ISO 3166-1 alpha-2 code`_, the same used for domain names. The -following countries and their subdivisions are available: +We currently support 119 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: .. list-table:: :widths: 23 4 83 @@ -121,6 +123,9 @@ following countries and their subdivisions are available: * - Albania - AL - None + * - American Samoa + - AS + - None; Can also be loaded as country US, subdivision AS * - Andorra - AD - Parishes: AD-02, AD-03, AD-04, AD-05, AD-06, AD-07, AD-08 @@ -238,6 +243,9 @@ following countries and their subdivisions are available: * - Greece - GR - None + * - Guam + - GU + - None; Can also be loaded as country US, subdivision GU * - Honduras - HN - None @@ -310,6 +318,9 @@ following countries and their subdivisions are available: * - Malta - MT - None + * - Marshall Islands (the) + - MH + - None * - Mexico - MX - None @@ -343,6 +354,9 @@ following countries and their subdivisions are available: * - Nigeria - NG - None + * - Northern Mariana Islands (the) + - MP + - None; Can also be loaded as country US, subdivision MP * - North Macedonia - MK - None @@ -352,6 +366,9 @@ following countries and their subdivisions are available: * - Pakistan - PK - None + * - Panama + - PA + - None * - Paraguay - PY - None @@ -367,6 +384,9 @@ following countries and their subdivisions are available: * - Portugal - PT - Districts: 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, Ext; Use subdiv='Ext' to include holidays most people have off + * - Puerto Rico + - PR + - None; Can also be loaded as country US, subdivision PR * - Romania - RO - None @@ -427,9 +447,15 @@ following countries and their subdivisions are available: * - United Kingdom - GB - Subdivisions: England, Northern Ireland, Scotland, **UK** (default), Wales; For Isle of Man use country code IM - * - United States + * - United States Minor Outlying Islands + - UM + - None; Can also be loaded as country US, subdivision UM + * - United States of America (the) - US - - States and territories: AL, AK, AS, AZ, AR, CA, CO, CT, DE, DC, FL, GA, GU, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MH, MA, MI, FM, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, MP, OH, OK, OR, PW, PA, PR, RI, SC, SD, TN, TX, UT, VT, VA, VI, WA, WV, WI, WY + - States and territories: AL, AK, AS, AZ, AR, CA, CO, CT, DE, DC, FL, GA, GU, HI, ID, IL, IN, IA, KS, KY, LA, ME, MD, MH, MA, MI, FM, MN, MS, MO, MT, NE, NV, NH, NJ, NM, NY, NC, ND, MP, OH, OK, OR, PW, PA, PR, RI, SC, SD, TN, TX, UM, UT, VT, VA, VI, WA, WV, WI, WY + * - United States Virgin Islands (the) + - + - See Virgin Islands (U.S.) * - Uruguay - UY - None @@ -445,6 +471,9 @@ following countries and their subdivisions are available: * - Vietnam - VN - None + * - Virgin Islands (U.S.) + - VI + - None; Can also be loaded as country US, subdivision VI * - Zambia - ZM - None @@ -478,6 +507,72 @@ following financial markets are available: - NYSE market holidays (used by all other US-exchanges, including NASDAQ, etc.) +Localization +=========================== + +.. _ISO 639-1 code: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes + +Some of the supported entities (country/market) provide more than one +language for holiday names output. The default language is defined by +``default_language`` (optional) attribute for each entity and is used as a fallback +when neither user specified language nor user locale language available. The +default language code is a `ISO 639-1 code`_. + +.. list-table:: + :widths: 23 4 83 + :header-rows: 1 + :class: tight-table + + * - Country + - Default Language + - Supported languages + * - Argentina + - es + - en_US, es + * - Armenia + - hy + - en_US, hy + * - Belarus + - be + - be, en_US + * - Bulgaria + - bg + - bg, en_US + * - Canada + - en + - en, fr + * - Cyprus + - el + - el, en + * - Denmark + - da + - da, en_US + * - Ethiopia + - am + - am, en_US + * - Georgia + - ka + - en_US, ka + * - Greece + - el + - el, en_US + * - Japan + - ja + - en_US, ja + * - Poland + - pl + - en_US, pl, uk + * - Russia + - ru + - en_US, ru + * - Serbia + - sr + - en_US, sr + * - Ukraine + - uk + - en_US, uk + + Beta Version ------------ diff --git a/holidays/__init__.py b/holidays/__init__.py index 6055b3ede..cdc881fd9 100644 --- a/holidays/__init__.py +++ b/holidays/__init__.py @@ -15,4 +15,4 @@ from holidays.holiday_base import * from holidays.utils import * -__version__ = "0.19" +__version__ = "0.20" diff --git a/holidays/constants.py b/holidays/constants.py index 43b490dfe..3e22232b1 100644 --- a/holidays/constants.py +++ b/holidays/constants.py @@ -9,6 +9,8 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) +HOLIDAY_NAME_DELIMITER = "; " # Holiday names separator. + MON, TUE, WED, THU, FRI, SAT, SUN = range(7) WEEKEND = (SAT, SUN) diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py index 2576446b2..96de83b01 100644 --- a/holidays/countries/__init__.py +++ b/holidays/countries/__init__.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from .albania import AL, ALB, Albania +from .american_samoa import AS, ASM, AmericanSamoa, HolidaysAS from .andorra import AD, AND, Andorra from .angola import AO, AGO, Angola from .argentina import AR, ARG, Argentina @@ -49,6 +50,7 @@ from .georgia import GE, GEO, Georgia from .germany import DE, DEU, Germany from .greece import GR, GRC, Greece +from .guam import GU, GUM, Guam, HolidaysGU from .honduras import HN, HND, Honduras from .hongkong import HK, HKG, HongKong from .hungary import HU, HUN, Hungary @@ -73,6 +75,7 @@ from .malawi import MW, MWI, Malawi from .malaysia import MY, MYS, Malaysia from .malta import MT, MLT, Malta +from .marshall_islands import MH, MHL, MarshallIslands, HolidaysMH from .mexico import MX, MEX, Mexico from .moldova import MD, MDA, Moldova from .monaco import MC, MCO, Monaco @@ -85,13 +88,21 @@ from .nicaragua import NI, NIC, Nicaragua from .nigeria import NG, NGA, Nigeria from .north_macedonia import MK, MKD, NorthMacedonia +from .northern_mariana_islands import ( + MP, + MNP, + HolidaysMP, + NorthernMarianaIslands, +) from .norway import NO, NOR, Norway from .pakistan import PK, PAK, Pakistan +from .panama import PA, PAN, Panama from .paraguay import PY, PRY, Paraguay from .peru import PE, PER, Peru from .philippines import PH, PHL, Philippines from .poland import PL, POL, Poland from .portugal import PT, PRT, Portugal +from .puerto_rico import PR, PRI, PuertoRico, HolidaysPR from .romania import RO, ROU, Romania from .russia import RU, RUS, Russia from .san_marino import SM, SMR, SanMarino @@ -113,6 +124,18 @@ from .united_arab_emirates import AE, ARE, UnitedArabEmirates from .united_kingdom import GB, UK, GBR, UnitedKingdom from .united_states import US, USA, UnitedStates +from .united_states_minor_outlying_islands import ( + UM, + UMI, + UnitedStatesMinorOutlyingIslands, + HolidaysUM, +) +from .united_states_virgin_islands import ( + VI, + VIR, + UnitedStatesVirginIslands, + HolidaysVI, +) from .uruguay import UY, URY, Uruguay from .uzbekistan import UZ, UZB, Uzbekistan from .vatican_city import VA, VAT, VaticanCity diff --git a/holidays/countries/albania.py b/holidays/countries/albania.py index a825ee48b..9ba54df24 100644 --- a/holidays/countries/albania.py +++ b/holidays/countries/albania.py @@ -10,12 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td -from dateutil.easter import EASTER_ORTHODOX, EASTER_WESTERN, easter -from dateutil.relativedelta import MO -from dateutil.relativedelta import relativedelta as rd +from dateutil.easter import EASTER_ORTHODOX, easter -from holidays.constants import JAN, MAR, MAY, SEP, NOV, DEC +from holidays.constants import JAN, MAR, MAY, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _islamic_to_gre @@ -27,69 +26,90 @@ class Albania(HolidayBase): """ country = "AL" - - def _add_holiday(self, holiday_date: date, holiday_name: str) -> date: - dt = holiday_date - - self[dt] = holiday_name - if self.observed and self._is_weekend(dt): - dt += rd(weekday=MO(+1)) - while dt.year == holiday_date.year and dt in self: - dt += rd(days=+1) - self[dt] = f"{holiday_name} (Observed)" - - return dt + special_holidays = { + 2022: ((MAR, 21, "Public Holiday"),), + } def _populate(self, year: int) -> None: + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_weekend(hol_date): + self[ + hol_date + + td(days=+2 if self._is_saturday(hol_date) else days) + ] = f"{hol_name} (Observed)" + super()._populate(year) # New Year's Day. name = "New Year's Day" - self._add_holiday(date(year, JAN, 1), name) - self._add_holiday(date(year, JAN, 2), name) + _add_with_observed(date(year, JAN, 1), name, days=+2) + _add_with_observed(date(year, JAN, 2), name, days=+2) # Summer Day. - self[date(year, MAR, 14)] = "Summer Day" + if year >= 2004: + _add_with_observed(date(year, MAR, 14), "Summer Day") # Nevruz. - self[date(year, MAR, 22)] = "Nevruz" + if year >= 1996: + _add_with_observed(date(year, MAR, 22), "Nevruz") # Easter. - easter_holidays_mapping = { - EASTER_ORTHODOX: "Orthodox Easter", - EASTER_WESTERN: "Catholic Easter", - } - for method, holiday_name in easter_holidays_mapping.items(): - self._add_holiday( - easter(year, method=method), # type: ignore[arg-type] - holiday_name, - ) + _add_with_observed( + easter(year), + "Catholic Easter", + days=+2 if year == 2008 else +1, + ) + _add_with_observed( + easter(year, method=EASTER_ORTHODOX), + "Orthodox Easter", + days=+2 + if year in {1989, 2000, 2021, 2027, 2032, 2062, 2073, 2084} + else +1, + ) # May Day. - self._add_holiday(date(year, MAY, 1), "May Day") - - # Eid al-Fitr. - for dt in _islamic_to_gre(year, 10, 1): - self._add_holiday(dt, "Eid al-Fitr* (*estimated)") - - # Eid al-Adha. - for dt in _islamic_to_gre(year, 12, 10): - self._add_holiday(dt, "Eid al-Adha* (*estimated)") + _add_with_observed(date(year, MAY, 1), "May Day") # Mother Teresa Day. - self._add_holiday(date(year, SEP, 5), "Mother Teresa Day") + if 2004 <= year <= 2017: + _add_with_observed( + date(year, OCT, 19), "Mother Teresa Beatification Day" + ) + elif year >= 2018: + _add_with_observed( + date(year, SEP, 5), "Mother Teresa Canonisation Day" + ) # Independence Day. - self._add_holiday(date(year, NOV, 28), "Independence Day") + _add_with_observed(date(year, NOV, 28), "Independence Day", days=+2) # Liberation Day. - self._add_holiday(date(year, NOV, 29), "Liberation Day") + _add_with_observed(date(year, NOV, 29), "Liberation Day", days=+2) # National Youth Day. - self._add_holiday(date(year, DEC, 8), "National Youth Day") + if year >= 2009: + _add_with_observed(date(year, DEC, 8), "National Youth Day") # Christmas Day. - self._add_holiday(date(year, DEC, 25), "Christmas Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day") + + # Eid al-Fitr. + for dt in _islamic_to_gre(year, 10, 1): + _add_with_observed(dt, "Eid al-Fitr* (*estimated)") + + # Eid al-Adha. + for dt in _islamic_to_gre(year, 12, 10): + if year == 2006: + self[dt] = "Eid al-Adha* (*estimated)" + else: + _add_with_observed(dt, "Eid al-Adha* (*estimated)") + + # observed holidays special cases + if self.observed and year == 2007: + self[date(2007, JAN, 3)] = "Eid al-Adha* (*estimated) (Observed)" class AL(Albania): diff --git a/holidays/countries/american_samoa.py b/holidays/countries/american_samoa.py new file mode 100644 index 000000000..045edef5d --- /dev/null +++ b/holidays/countries/american_samoa.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysAS(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "AS" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "AS" + super()._populate(year) + + +class AS(HolidaysAS): + pass + + +class ASM(HolidaysAS): + pass + + +class AmericanSamoa(HolidaysAS): + pass diff --git a/holidays/countries/andorra.py b/holidays/countries/andorra.py index 9c15dc821..5212b8699 100644 --- a/holidays/countries/andorra.py +++ b/holidays/countries/andorra.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, MAY, JUL, AUG, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -47,22 +47,22 @@ def _populate(self, year: int) -> None: easter_sunday = easter(year) # Carnival. - self[easter_sunday + rd(days=-47)] = "Carnival" + self[easter_sunday + td(days=-47)] = "Carnival" # Constitution Day. self[date(year, MAR, 14)] = "Constitution Day" # Good Friday. - self[easter_sunday + rd(days=-2)] = "Good Friday" + self[easter_sunday + td(days=-2)] = "Good Friday" # Easter Sunday. - self[easter_sunday + rd(days=+1)] = "Easter Monday" + self[easter_sunday + td(days=+1)] = "Easter Monday" # Labour Day. self[date(year, MAY, 1)] = "Labour Day" # Whit Monday. - self[easter_sunday + rd(days=+50)] = "Whit Monday" + self[easter_sunday + td(days=+50)] = "Whit Monday" # Assumption Day. self[date(year, AUG, 15)] = "Assumption Day" diff --git a/holidays/countries/angola.py b/holidays/countries/angola.py index 75783b98c..8a05efae2 100644 --- a/holidays/countries/angola.py +++ b/holidays/countries/angola.py @@ -10,12 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAR, APR, MAY, SEP, NOV, DEC, MON -from holidays.constants import TUE, THU, SUN +from holidays.constants import JAN, FEB, MAR, APR, MAY, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -28,58 +27,65 @@ class Angola(HolidayBase): country = "AO" def _populate(self, year: int) -> None: + def _add_with_observed( + hol_date: date, hol_name: str, before: bool = True + ) -> None: + # As of 1995/1/1, whenever a public holiday falls on a Sunday, + # it rolls over to the following Monday + # Since 2018 when a public holiday falls on the Tuesday or Thursday + # the Monday or Friday is also a holiday + self[hol_date] = hol_name + if self.observed and year >= 1995: + if year <= 2017: + if self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + else: + if self._is_tuesday(hol_date) and before: + self[hol_date + td(days=-1)] = f"{hol_name} (Day off)" + elif self._is_thursday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Day off)" + # Observed since 1975 # TODO do more research on history of Angolan holidays if year <= 1974: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "Ano novo" + _add_with_observed(date(year, JAN, 1), "Ano novo", before=False) # Since 2018, if the following year's New Year's Day falls on a # Tuesday, the 31st of the current year is also a holiday. - if year >= 2018: - if self.observed and date(year, DEC, 31).weekday() == MON: - self[date(year, DEC, 31)] = "Ano novo (Day off)" + if ( + self.observed + and self._is_monday(date(year, DEC, 31)) + and year >= 2018 + ): + self[date(year, DEC, 31)] = "Ano novo (Day off)" easter_date = easter(year) - self[(easter_date + rd(days=-2))] = "Sexta-feira Santa" + self[easter_date + td(days=-2)] = "Sexta-feira Santa" # carnival is the Tuesday before Ash Wednesday # which is 40 days before easter excluding sundays - self[(easter_date + rd(days=-47))] = "Carnaval" + _add_with_observed(easter_date + td(days=-47), "Carnaval") - self[date(year, FEB, 4)] = "Dia do Início da Luta Armada" - self[date(year, MAR, 8)] = "Dia Internacional da Mulher" + _add_with_observed(date(year, FEB, 4), "Dia do Início da Luta Armada") + _add_with_observed(date(year, MAR, 8), "Dia Internacional da Mulher") if year >= 2019: - self[date(year, MAR, 23)] = "Dia da Libertação da África Austral" + _add_with_observed( + date(year, MAR, 23), "Dia da Libertação da África Austral" + ) - self[date(year, APR, 4)] = "Dia da Paz e Reconciliação" - self[date(year, MAY, 1)] = "Dia Mundial do Trabalho" + _add_with_observed(date(year, APR, 4), "Dia da Paz e Reconciliação") + _add_with_observed(date(year, MAY, 1), "Dia Mundial do Trabalho") if year >= 1980: - self[date(year, SEP, 17)] = "Dia do Herói Nacional" - - self[date(year, NOV, 2)] = "Dia dos Finados" - self[date(year, NOV, 11)] = "Dia da Independência" - self[date(year, DEC, 25)] = "Dia de Natal e da Família" - - # As of 1995/1/1, whenever a public holiday falls on a Sunday, - # it rolls over to the following Monday - # Since 2018 when a public holiday falls on the Tuesday or Thursday - # the Monday or Friday is also a holiday - if self.observed and year >= 1995: - for k, v in list(self.items()): - if k.year != year: - continue - if year <= 2017: - if k.weekday() == SUN: - self[k + rd(days=+1)] = v + " (Observed)" - else: - if k.weekday() == TUE and k != date(year, JAN, 1): - self[k + rd(days=-1)] = v + " (Day off)" - elif k.weekday() == THU: - self[k + rd(days=+1)] = v + " (Day off)" + _add_with_observed(date(year, SEP, 17), "Dia do Herói Nacional") + + _add_with_observed(date(year, NOV, 2), "Dia dos Finados") + _add_with_observed(date(year, NOV, 11), "Dia da Independência") + _add_with_observed(date(year, DEC, 25), "Dia de Natal e da Família") class AO(Angola): diff --git a/holidays/countries/argentina.py b/holidays/countries/argentina.py index 539752993..76ec0855a 100644 --- a/holidays/countries/argentina.py +++ b/holidays/countries/argentina.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, JUN, JUL, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -29,6 +29,7 @@ class Argentina(HolidayBase): """ country = "AR" + default_language = "es" def _populate(self, year): super()._populate(year) @@ -37,18 +38,17 @@ def _populate(self, year): if not self.observed and self._is_weekend(year, JAN, 1): pass else: - self[date(year, JAN, 1)] = "Año Nuevo [New Year's Day]" + self[date(year, JAN, 1)] = self.tr("Año Nuevo") easter_date = easter(year) # Carnival days - name = "Día de Carnaval [Carnival's Day]" - self[easter_date + rd(days=-48)] = name - self[easter_date + rd(days=-47)] = name + name = self.tr("Día de Carnaval") + self[easter_date + td(days=-48)] = name + self[easter_date + td(days=-47)] = name # Memory's National Day for the Truth and Justice - name = ( - "Día Nacional de la Memoria por la Verdad y la Justicia " - "[Memory's National Day for the Truth and Justice]" + name = self.tr( + "Día Nacional de la Memoria por la Verdad y la Justicia" ) if not self.observed and self._is_weekend(year, MAR, 24): @@ -57,12 +57,12 @@ def _populate(self, year): self[date(year, MAR, 24)] = name # Holy Week - name_thu = "Semana Santa (Jueves Santo) [Holy day (Holy Thursday)]" - name_fri = "Semana Santa (Viernes Santo) [Holy day (Holy Friday)]" - name_easter = "Día de Pascuas [Easter Day]" + name_thu = self.tr("Semana Santa (Jueves Santo)") + name_fri = self.tr("Semana Santa (Viernes Santo)") + name_easter = self.tr("Día de Pascuas") - self[easter_date + rd(days=-3)] = name_thu - self[easter_date + rd(days=-2)] = name_fri + self[easter_date + td(days=-3)] = name_thu + self[easter_date + td(days=-2)] = name_fri if not self.observed and self._is_weekend(easter_date): pass @@ -73,32 +73,27 @@ def _populate(self, year): if not self.observed and self._is_weekend(year, APR, 2): pass else: - self[date(year, APR, 2)] = ( - "Día del Veterano y de los Caidos " - "en la Guerra de Malvinas [Veterans" - " Day and the Fallen in the" - " Malvinas War]" + self[date(year, APR, 2)] = self.tr( + "Día del Veterano y de los Caidos en la Guerra de Malvinas" ) # Labor Day - name = "Día del Trabajo [Labour Day]" + name = self.tr("Día del Trabajo") if not self.observed and self._is_weekend(year, MAY, 1): pass else: self[date(year, MAY, 1)] = name # May Revolution Day - name = "Día de la Revolucion de Mayo [May Revolution Day]" + name = self.tr("Día de la Revolución de Mayo") if not self.observed and self._is_weekend(year, MAY, 25): pass else: self[date(year, MAY, 25)] = name # Day Pass to the Immortality of General Martín Miguel de Güemes. - name = ( - "Día Pase a la Inmortalidad " - "del General Martín Miguel de Güemes [Day Pass " - "to the Immortality of General Martín Miguel de Güemes]" + name = self.tr( + "Día Pase a la Inmortalidad del General Martín Miguel de Güemes" ) if not self.observed and self._is_weekend(year, JUN, 17): pass @@ -106,10 +101,8 @@ def _populate(self, year): self[date(year, JUN, 17)] = name # Day Pass to the Immortality of General D. Manuel Belgrano. - name = ( - "Día Pase a la Inmortalidad " - "del General D. Manuel Belgrano [Day Pass " - "to the Immortality of General D. Manuel Belgrano]" + name = self.tr( + "Día Pase a la Inmortalidad del General D. Manuel Belgrano" ) if not self.observed and self._is_weekend(year, JUN, 20): pass @@ -117,17 +110,15 @@ def _populate(self, year): self[date(year, JUN, 20)] = name # Independence Day - name = "Día de la Independencia [Independence Day]" + name = self.tr("Día de la Independencia") if not self.observed and self._is_weekend(year, JUL, 9): pass else: self[date(year, JUL, 9)] = name # Day Pass to the Immortality of General D. José de San Martin - name = ( - "Día Pase a la Inmortalidad " - "del General D. José de San Martin [Day Pass " - "to the Immortality of General D. José de San Martin]" + name = self.tr( + "Día Pase a la Inmortalidad del General D. José de San Martin" ) if not self.observed and self._is_weekend(year, AUG, 17): pass @@ -138,15 +129,13 @@ def _populate(self, year): if not self.observed and self._is_weekend(year, OCT, 12): pass elif year < 2010: - self[date(year, OCT, 12)] = "Día de la Raza [Columbus day]" + self[date(year, OCT, 12)] = self.tr("Día de la Raza") else: - self[date(year, OCT, 12)] = ( - "Día del Respeto a la Diversidad" - " Cultural [Respect for" - " Cultural Diversity Day]" + self[date(year, OCT, 12)] = self.tr( + "Día del Respeto a la Diversidad Cultural" ) # National Sovereignty Day - name = "Día Nacional de la Soberanía [National Sovereignty Day]" + name = self.tr("Día Nacional de la Soberanía") if not self.observed and self._is_weekend(year, NOV, 20): pass elif year >= 2010: @@ -156,12 +145,10 @@ def _populate(self, year): if not self.observed and self._is_weekend(year, DEC, 8): pass else: - self[ - date(year, DEC, 8) - ] = "La Inmaculada Concepción [Immaculate Conception]" + self[date(year, DEC, 8)] = self.tr("La Inmaculada Concepción") # Christmas - self[date(year, DEC, 25)] = "Navidad [Christmas]" + self[date(year, DEC, 25)] = self.tr("Navidad") class AR(Argentina): diff --git a/holidays/countries/armenia.py b/holidays/countries/armenia.py index 1c976fda9..0a173b43a 100644 --- a/holidays/countries/armenia.py +++ b/holidays/countries/armenia.py @@ -17,87 +17,80 @@ class Armenia(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Armenia - http://www.parliament.am/legislation.php?sel=show&ID=1274&lang=arm&enc=utf8 - https://www.arlis.am/documentview.aspx?docid=259 + Armenia holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Armenia + - http://www.parliament.am/legislation.php?sel=show&ID=1274&lang=arm&enc=utf8 # noqa: E501 + - https://www.arlis.am/documentview.aspx?docid=259 """ country = "AM" + default_language = "hy" def _populate(self, year): - if year <= 1990: - return + return None + super()._populate(year) - # New Year's Day - name = "Ամանոր [New Year's Day]" + # New Year's Day. + name = self.tr("Նոր տարվա օր") self[date(year, JAN, 1)] = name self[date(year, JAN, 2)] = name - # Christmas and Epiphany Day - self[ - date(year, JAN, 6) - ] = "Սուրբ Ծնունդ եւ Հայտնություն [Christmas and Epiphany Day]" + # Christmas and Epiphany Day. + self[date(year, JAN, 6)] = self.tr("Սուրբ Ծնունդ եւ Հայտնություն") if 2010 <= year <= 2021: - # New Year's holidays and Christmas Eve + # New Year's holidays and Christmas Eve. self[date(year, JAN, 3)] = name self[date(year, JAN, 4)] = name - self[date(year, JAN, 5)] = "նախածննդյան տոներ [Christmas Eve]" + # Christmas Eve. + self[date(year, JAN, 5)] = self.tr("Սուրբ Ծննդյան տոներ") - # The Day of Remembrance of the Dead - self[ - date(year, JAN, 7) - ] = "Մեռելոց հիշատակի օր [The Day of Remembrance of the Dead]" + # The Day of Remembrance of the Dead. + self[date(year, JAN, 7)] = self.tr("Մեռելոց հիշատակի օր") - # Army Day if year >= 2003: - self[date(year, JAN, 28)] = "Բանակի օր [Army Day]" + # Army Day. + self[date(year, JAN, 28)] = self.tr("Բանակի օր") - # Women's Day - self[date(year, MAR, 8)] = "Կանանց տոն [Women's Day]" + # Women's Day. + self[date(year, MAR, 8)] = self.tr("Կանանց տոն") - # Motherhood and Beauty Day if 1994 <= year <= 2001: - self[ - date(year, APR, 7) - ] = "Մայրության և գեղեցկության տոն [Motherhood and Beauty Day]" + # Motherhood and Beauty Day. + self[date(year, APR, 7)] = self.tr("Մայրության և գեղեցկության տոն") - # Armenian Genocide Remembrance Day - self[ - date(year, APR, 24) - ] = "Եղեռնի զոհերի հիշատակի օր [Armenian Genocide Remembrance Day]" + # Armenian Genocide Remembrance Day, + self[date(year, APR, 24)] = self.tr("Եղեռնի զոհերի հիշատակի օր") - # Labour Day if year >= 2001: - name = ( - "Աշխատավորների համերաշխության միջազգային օր " - "[International Day of Workers' Solidarity]" - ) + # International Day of Workers' Solidarity. + name = self.tr("Աշխատավորների համերաշխության միջազգային օր") if year >= 2002: - name = "Աշխատանքի օր [Labour Day]" + # Labor Day. + name = self.tr("Աշխատանքի օր") self[date(year, MAY, 1)] = name - # Victory and Peace Day if year >= 1995: - self[ - date(year, MAY, 9) - ] = "Հաղթանակի և Խաղաղության տոն [Victory and Peace Day]" + # Victory and Peace Day. + self[date(year, MAY, 9)] = self.tr("Հաղթանակի և Խաղաղության տոն") - # Republic Day - self[date(year, MAY, 28)] = "Հանրապետության օր [Republic Day]" + # Republic Day. + self[date(year, MAY, 28)] = self.tr("Հանրապետության օր") - # Constitution Day if year >= 1996: - self[date(year, JUL, 5)] = "Սահմանադրության օր [Constitution Day]" + # Constitution Day. + self[date(year, JUL, 5)] = self.tr("Սահմանադրության օր") - # Independence Day if year >= 1992: - self[date(year, SEP, 21)] = "Անկախության օր [Independence Day]" + # Independence Day. + self[date(year, SEP, 21)] = self.tr("Անկախության օր") - # New Year's Eve - self[date(year, DEC, 31)] = "Ամանոր [New Year's Eve]" + # New Year's Eve. + self[date(year, DEC, 31)] = self.tr("Նոր տարվա գիշեր") class AM(Armenia): diff --git a/holidays/countries/aruba.py b/holidays/countries/aruba.py index f779b1229..65706b00c 100644 --- a/holidays/countries/aruba.py +++ b/holidays/countries/aruba.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, APR, MAY, AUG, DEC, SUN +from holidays.constants import JAN, MAR, APR, MAY, AUG, DEC from holidays.holiday_base import HolidayBase @@ -38,7 +38,7 @@ def _populate(self, year): easter_date = easter(year) # Carnaval Monday self[ - easter_date + rd(days=-48) + easter_date + td(days=-48) ] = "Dialuna di Carnaval [Carnaval Monday]" # Dia di Himno y Bandera @@ -47,18 +47,18 @@ def _populate(self, year): ] = "Dia di Himno y Bandera [National Anthem & Flag Day]" # Good Friday - self[easter_date + rd(days=-2)] = "Bierna Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Bierna Santo [Good Friday]" # Easter Monday self[ - easter_date + rd(days=+1) + easter_date + td(days=+1) ] = "Di Dos Dia di Pasco di Resureccion [Easter Monday]" # King's Day if year >= 2014: kings_day = date(year, APR, 27) - if kings_day.weekday() == SUN: - kings_day += rd(days=-1) + if self._is_sunday(kings_day): + kings_day += td(days=-1) self[kings_day] = "Aña di Rey [King's Day]" @@ -68,8 +68,8 @@ def _populate(self, year): if year <= 1948: queens_day = date(year, AUG, 31) - if queens_day.weekday() == SUN: - queens_day += rd(days=+1) if year < 1980 else rd(days=-1) + if self._is_sunday(queens_day): + queens_day += td(days=+1) if year < 1980 else td(days=-1) self[queens_day] = "Aña di La Reina [Queen's Day]" @@ -77,7 +77,7 @@ def _populate(self, year): self[date(year, MAY, 1)] = "Dia di Obrero [Labour Day]" # Ascension Day - self[easter_date + rd(days=+39)] = "Dia di Asuncion [Ascension Day]" + self[easter_date + td(days=+39)] = "Dia di Asuncion [Ascension Day]" # Christmas Day self[date(year, DEC, 25)] = "Pasco di Nacemento [Christmas]" diff --git a/holidays/countries/australia.py b/holidays/countries/australia.py index 72fa5e3af..0474f8c9c 100644 --- a/holidays/countries/australia.py +++ b/holidays/countries/australia.py @@ -10,17 +10,21 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, TU, WE, FR from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, APR, MAY, JUN, AUG, SEP, OCT, NOV -from holidays.constants import DEC, SAT, SUN +from holidays.constants import JAN, MAR, APR, MAY, JUN, AUG, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase class Australia(HolidayBase): + """ + References: + - https://www.qld.gov.au/recreation/travel/holidays + """ country = "AU" special_holidays = { @@ -94,12 +98,12 @@ def _populate(self, year): # Easter easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-2)] = "Good Friday" if self.subdiv in {"ACT", "NSW", "NT", "QLD", "SA", "VIC"}: - self[easter_date + rd(days=-1)] = "Easter Saturday" + self[easter_date + td(days=-1)] = "Easter Saturday" if self.subdiv in {"ACT", "NSW", "QLD", "VIC"}: self[easter_date] = "Easter Sunday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=+1)] = "Easter Monday" # Anzac Day if year > 1920: @@ -107,12 +111,12 @@ def _populate(self, year): apr25 = date(year, APR, 25) self[apr25] = name if self.observed: - if apr25.weekday() == SAT and self.subdiv in { + if self._is_saturday(apr25) and self.subdiv in { "WA", "NT", }: self[apr25 + rd(weekday=MO)] = name + " (Observed)" - elif apr25.weekday() == SUN and self.subdiv in { + elif self._is_sunday(apr25) and self.subdiv in { "ACT", "NT", "QLD", @@ -239,15 +243,16 @@ def _populate(self, year): # not prior to the 5th - in which case it will begin on the second # Friday. The Wednesday during the show is a public holiday. if self.subdiv == "QLD": - name = "The Royal Queensland Show" - if year == 2020: - self[date(year, AUG, 14)] = name - if year == 2021: - self[date(year, OCT, 29)] = name - else: - self[ - date(year, AUG, 5) + rd(weekday=FR) + rd(weekday=WE) - ] = name + ekka_dates = { + 2020: date(year, AUG, 14), + 2021: date(year, OCT, 29), + } + self[ + ekka_dates.get( + year, + date(year, AUG, 5) + rd(weekday=FR) + rd(weekday=WE), + ) + ] = "The Royal Queensland Show" # Christmas Day name = "Christmas Day" diff --git a/holidays/countries/austria.py b/holidays/countries/austria.py index 18642800c..90b2e95bf 100644 --- a/holidays/countries/austria.py +++ b/holidays/countries/austria.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -37,11 +37,11 @@ def _populate(self, year): self[date(year, JAN, 1)] = "Neujahr" self[date(year, JAN, 6)] = "Heilige Drei Könige" easter_date = easter(year) - self[easter_date + rd(days=+1)] = "Ostermontag" + self[easter_date + td(days=+1)] = "Ostermontag" self[date(year, MAY, 1)] = "Staatsfeiertag" - self[easter_date + rd(days=+39)] = "Christi Himmelfahrt" - self[easter_date + rd(days=+50)] = "Pfingstmontag" - self[easter_date + rd(days=+60)] = "Fronleichnam" + self[easter_date + td(days=+39)] = "Christi Himmelfahrt" + self[easter_date + td(days=+50)] = "Pfingstmontag" + self[easter_date + td(days=+60)] = "Fronleichnam" self[date(year, AUG, 15)] = "Mariä Himmelfahrt" if 1919 <= year <= 1934: self[date(year, NOV, 12)] = "Nationalfeiertag" diff --git a/holidays/countries/azerbaijan.py b/holidays/countries/azerbaijan.py index 792703c64..fd0fe3f64 100644 --- a/holidays/countries/azerbaijan.py +++ b/holidays/countries/azerbaijan.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT from holidays.constants import NOV, DEC @@ -28,11 +27,11 @@ class Azerbaijan(HolidayBase): def _populate(self, year: int) -> None: def _add_observed(hol_date: date, hol_name: str) -> None: - next_workday = hol_date + rd(days=+1) + next_workday = hol_date + td(days=+1) while next_workday.year == year and ( self._is_weekend(next_workday) or self.get(next_workday) ): - next_workday += rd(days=+1) + next_workday += td(days=+1) _add_holiday(next_workday, f"{hol_name} (Observed)") def _add_holiday(hol_date: date, hol_name: str) -> None: @@ -40,7 +39,8 @@ def _add_holiday(hol_date: date, hol_name: str) -> None: self[hol_date] = hol_name if year <= 1989: - return + return None + super()._populate(year) # New Year @@ -149,13 +149,14 @@ def _add_holiday(hol_date: date, hol_name: str) -> None: for date_obs in dates_obs[yr]: _add_holiday(date(yr, *date_obs), name) _add_holiday( - date(yr, *date_obs) + rd(days=+1), name + date(yr, *date_obs) + td(days=+1), name ) else: for dt in _islamic_to_gre(yr, hmonth, hday): _add_holiday(dt, f"{name}* (*estimated)") _add_holiday( - dt + rd(days=+1), f"{name}* (*estimated)" + dt + td(days=+1), + f"{name}* (*estimated)", ) """ diff --git a/holidays/countries/bahrain.py b/holidays/countries/bahrain.py index a47b796f7..2594ab939 100644 --- a/holidays/countries/bahrain.py +++ b/holidays/countries/bahrain.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import FRI, SAT, JAN, MAY, JUL, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -48,16 +47,16 @@ def _populate(self, year): for dt in eid_al_fitr_mapping[year]: eid_al_fitr_day = date(year, *dt) self[eid_al_fitr_day] = eid_al_fitr - self[eid_al_fitr_day + rd(days=+1)] = f"{eid_al_fitr} Holiday" - self[eid_al_fitr_day + rd(days=+2)] = f"{eid_al_fitr} Holiday" + self[eid_al_fitr_day + td(days=+1)] = f"{eid_al_fitr} Holiday" + self[eid_al_fitr_day + td(days=+2)] = f"{eid_al_fitr} Holiday" else: for eid_al_fitr_day in _islamic_to_gre(year, 10, 1): self[eid_al_fitr_day] = f"{eid_al_fitr}* (*estimated)" self[ - eid_al_fitr_day + rd(days=+1) + eid_al_fitr_day + td(days=+1) ] = f"{eid_al_fitr} Holiday* (*estimated)" self[ - eid_al_fitr_day + rd(days=+2) + eid_al_fitr_day + td(days=+2) ] = f"{eid_al_fitr} Holiday* (*estimated)" # Eid Al Adha. @@ -69,18 +68,18 @@ def _populate(self, year): for dt in eid_al_adha_mapping[year]: eid_al_adha_day = date(year, *dt) self[eid_al_adha_day] = eid_al_adha - self[eid_al_adha_day + rd(days=+1)] = f"{eid_al_adha} Holiday" - self[eid_al_adha_day + rd(days=+2)] = f"{eid_al_adha} Holiday" + self[eid_al_adha_day + td(days=+1)] = f"{eid_al_adha} Holiday" + self[eid_al_adha_day + td(days=+2)] = f"{eid_al_adha} Holiday" else: for eid_al_adha_day in _islamic_to_gre(year, 12, 9): self[ - eid_al_adha_day + rd(days=+1) + eid_al_adha_day + td(days=+1) ] = f"{eid_al_adha}* (*estimated)" self[ - eid_al_adha_day + rd(days=+2) + eid_al_adha_day + td(days=+2) ] = f"{eid_al_adha}* (*estimated)" self[ - eid_al_adha_day + rd(days=+3) + eid_al_adha_day + td(days=+3) ] = f"{eid_al_adha}* (*estimated)" # Al Hijra New Year. @@ -104,12 +103,12 @@ def _populate(self, year): for dt in ashura_mapping[year]: ashura_day = date(year, *dt) self[ashura_day] = ashura - self[ashura_day + rd(days=+1)] = f"{ashura} Holiday" + self[ashura_day + td(days=+1)] = f"{ashura} Holiday" else: for ashura_day in _islamic_to_gre(year, 1, 9): self[ashura_day] = f"{ashura}* (*estimated)" self[ - ashura_day + rd(days=+1) + ashura_day + td(days=+1) ] = f"{ashura}* Holiday* (*estimated)" # Prophets Birthday. diff --git a/holidays/countries/belarus.py b/holidays/countries/belarus.py index 1677465bc..1fd190feb 100644 --- a/holidays/countries/belarus.py +++ b/holidays/countries/belarus.py @@ -10,67 +10,74 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import DEC, JAN, JUL, MAR, MAY, NOV +from holidays.constants import JAN, MAR, MAY, JUL, NOV, DEC from holidays.holiday_base import HolidayBase class Belarus(HolidayBase): """ - http://president.gov.by/en/holidays_en/ - http://www.belarus.by/en/about-belarus/national-holidays + Belarus holidays. + + References: + - http://president.gov.by/en/holidays_en/ + - http://www.belarus.by/en/about-belarus/national-holidays """ country = "BY" + default_language = "be" def _populate(self, year): - # The current set of holidays came into force in 1998 + # The current set of holidays came into force in 1998. # http://laws.newsby.org/documents/ukazp/pos05/ukaz05806.htm if year <= 1998: - return + return None super()._populate(year) - # New Year's Day - self[date(year, JAN, 1)] = "Новый год" + # New Year's Day. + name = self.tr("Новы год") + self[date(year, JAN, 1)] = name - # Jan 2nd is the national holiday (New Year) from 2020 + # Jan 2nd is the national holiday (New Year) from 2020. # http://president.gov.by/uploads/documents/2019/464uk.pdf if year >= 2020: - self[date(year, JAN, 2)] = "Новый год" + self[date(year, JAN, 2)] = name - # Christmas Day (Orthodox) - self[ - date(year, JAN, 7) - ] = "Рождество Христово (православное Рождество)" + # Christmas Day (Orthodox). + self[date(year, JAN, 7)] = self.tr( + "Нараджэнне Хрыстова (праваслаўнае Раство)" + ) - # Women's Day - self[date(year, MAR, 8)] = "День женщин" + # Women's Day. + self[date(year, MAR, 8)] = self.tr("Дзень жанчын") - # Radunitsa ("Day of Rejoicing") - self[easter(year, method=EASTER_ORTHODOX) + rd(days=+9)] = "Радуница" + # Radunitsa (Day of Rejoicing). + self[easter(year, method=EASTER_ORTHODOX) + td(days=+9)] = self.tr( + "Радаўніца" + ) - # Labour Day - self[date(year, MAY, 1)] = "Праздник труда" + # Labour Day. + self[date(year, MAY, 1)] = self.tr("Свята працы") # Victory Day - self[date(year, MAY, 9)] = "День Победы" + self[date(year, MAY, 9)] = self.tr("Дзень Перамогі") - # Independence Day - self[ - date(year, JUL, 3) - ] = "День Независимости Республики Беларусь (День Республики)" + # Independence Day. + self[date(year, JUL, 3)] = self.tr( + "Дзень Незалежнасці Рэспублікі Беларусь (Дзень Рэспублікі)" + ) - # October Revolution Day - self[date(year, NOV, 7)] = "День Октябрьской революции" + # October Revolution Day. + self[date(year, NOV, 7)] = self.tr("Дзень Кастрычніцкай рэвалюцыі") - # Christmas Day (Catholic) - self[ - date(year, DEC, 25) - ] = "Рождество Христово (католическое Рождество)" + # Christmas Day (Catholic). + self[date(year, DEC, 25)] = self.tr( + "Нараджэнне Хрыстова (каталіцкае Раство)" + ) class BY(Belarus): diff --git a/holidays/countries/belgium.py b/holidays/countries/belgium.py index 2c8ec200e..a5aa28078 100644 --- a/holidays/countries/belgium.py +++ b/holidays/countries/belgium.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUL, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -38,16 +38,16 @@ def _populate(self, year): self[easter_date] = "Pasen" # Second easter day - self[easter_date + rd(days=+1)] = "Paasmaandag" + self[easter_date + td(days=+1)] = "Paasmaandag" # Ascension day - self[easter_date + rd(days=+39)] = "O.L.H. Hemelvaart" + self[easter_date + td(days=+39)] = "O.L.H. Hemelvaart" # Pentecost - self[easter_date + rd(days=+49)] = "Pinksteren" + self[easter_date + td(days=+49)] = "Pinksteren" # Pentecost monday - self[easter_date + rd(days=+50)] = "Pinkstermaandag" + self[easter_date + td(days=+50)] = "Pinkstermaandag" # International Workers' Day self[date(year, MAY, 1)] = "Dag van de Arbeid" diff --git a/holidays/countries/bolivia.py b/holidays/countries/bolivia.py index b760dc395..9baece8d5 100644 --- a/holidays/countries/bolivia.py +++ b/holidays/countries/bolivia.py @@ -11,19 +11,18 @@ # Copyright: Kateryna Golovanova , 2022 from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV -from holidays.constants import DEC, FRI, SUN +from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, NOV, DEC from holidays.holiday_base import HolidayBase class Bolivia(HolidayBase): """ - Bolivia holidays. - See https://en.wikipedia.org/wiki/Public_holidays_in_Bolivia for details. + https://en.wikipedia.org/wiki/Public_holidays_in_Bolivia + https://www.officeholidays.com/countries/bolivia """ country = "BO" @@ -40,15 +39,16 @@ class Bolivia(HolidayBase): ] def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + super()._populate(year) # New Year's Day. - name = "Año Nuevo" if year >= 1825: - self[date(year, JAN, 1)] = name - - if self.observed and date(year, JAN, 1).weekday() == SUN: - self[date(year, JAN, 1) + rd(days=+1)] = f"{name} (Observed)" + _add_with_observed(date(year, JAN, 1), "Año Nuevo") # Plurinational State Foundation Day. if year >= 2010: @@ -56,94 +56,72 @@ def _populate(self, year): date(year, JAN, 22) ] = "Nacimiento del Estado Plurinacional de Bolivia" - # Good Friday. easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Viernes Santo" - - # La Tablada. - if self.subdiv == "T": - self[date(year, APR, 15)] = "La Tablada" - # Carnival in Oruro. - if self.subdiv == "O": - self[easter_date + rd(days=-51)] = "Carnaval de Oruro" - - # Carnival Monday (Observed on Tuesday). + # Carnival. name = "Feriado por Carnaval" - self[easter_date + rd(days=-48)] = name - self[easter_date + rd(days=-47)] = f"{name} (Observed)" - - # Labor Day. - name = "Dia del trabajo" - self[date(year, MAY, 1)] = name + self[easter_date + td(days=-48)] = name + self[easter_date + td(days=-47)] = name - if self.observed and date(year, MAY, 1).weekday() == SUN: - self[date(year, MAY, 1) + rd(days=+1)] = f"{name} (Observed)" + # Good Friday. + self[easter_date + td(days=-2)] = "Viernes Santo" - # Chuquisaca Day. - if self.subdiv == "H": - self[date(year, MAY, 25)] = "Día del departamento de Chuquisaca" + # Labor Day. + _add_with_observed(date(year, MAY, 1), "Día del trabajo") # Corpus Christi. - self[easter_date + rd(days=+60)] = "Corpus Christi" + self[easter_date + td(days=+60)] = "Corpus Christi" # Andean New Year. - name = "Año Nuevo Andino" if year >= 2010: - self[date(year, JUN, 21)] = name + _add_with_observed(date(year, JUN, 21), "Año Nuevo Andino") - if self.observed and date(year, JUN, 21).weekday() == SUN: - self[date(year, JUN, 21) + rd(days=+1)] = f"{name} (Observed)" + # Independence Day. + if year >= 1825: + _add_with_observed(date(year, AUG, 6), "Día de la Patria") - # La Paz Day. - if self.subdiv == "L": - self[date(year, JUL, 16)] = "Día del departamento de La Paz" + # All Soul's Day. + _add_with_observed(date(year, NOV, 2), "Todos Santos") - # Agrarian Reform Day. - if year >= 1937: - self[date(year, AUG, 2)] = "Día de la Revolución Agraria" + # Christmas Day. + _add_with_observed(date(year, DEC, 25), "Navidad") - # Independence Day. - name = "Dia de la Patria" - if year >= 1825: - self[date(year, AUG, 6)] = name + # Regional holidays. + # La Tablada. + if self.subdiv == "T": + self[date(year, APR, 15)] = "La Tablada" + + # Carnival in Oruro. + elif self.subdiv == "O": + self[easter_date + td(days=-51)] = "Carnaval de Oruro" - if self.observed and date(year, AUG, 6).weekday() > FRI: - self[date(year, AUG, 6) + rd(days=+1)] = f"{name} (Observed)" + # Chuquisaca Day. + elif self.subdiv == "H": + self[date(year, MAY, 25)] = "Día del departamento de Chuquisaca" + + # La Paz Day. + elif self.subdiv == "L": + self[date(year, JUL, 16)] = "Día del departamento de La Paz" # Cochabamba Day. - if self.subdiv == "C": + elif self.subdiv == "C": self[date(year, SEP, 14)] = "Día del departamento de Cochabamba" # Santa Cruz Day. - if self.subdiv == "S": + elif self.subdiv == "S": self[date(year, SEP, 24)] = "Día del departamento de Santa Cruz" # Pando Day. - if self.subdiv == "N": - self[date(year, OCT, 11)] = "Dia del departamento de Pando" - - # All Soul's Day. - name = "Todos Santos" - self[date(year, NOV, 2)] = name - - if self.observed and date(year, NOV, 2).weekday() == SUN: - self[date(year, NOV, 2) + rd(days=+1)] = f"{name} (Observed)" + elif self.subdiv == "N": + self[date(year, SEP, 24)] = "Día del departamento de Pando" # Potosí Day. - if self.subdiv == "P": - self[date(year, NOV, 10)] = "Dia del departamento de Potosí" + elif self.subdiv == "P": + self[date(year, NOV, 10)] = "Día del departamento de Potosí" # Beni Day. - if self.subdiv == "B": - self[date(year, NOV, 18)] = "Dia del departamento de Beni" - - # Christmas Day. - name = "Navidad" - self[date(year, DEC, 25)] = name - - if self.observed and date(year, DEC, 25).weekday() == SUN: - self[date(year, DEC, 25) + rd(days=+1)] = f"{name} (Observed)" + elif self.subdiv == "B": + self[date(year, NOV, 18)] = "Día del departamento de Beni" class BO(Bolivia): diff --git a/holidays/countries/bosnia_and_herzegovina.py b/holidays/countries/bosnia_and_herzegovina.py index d299c6241..c0dc8cff7 100644 --- a/holidays/countries/bosnia_and_herzegovina.py +++ b/holidays/countries/bosnia_and_herzegovina.py @@ -11,20 +11,21 @@ # Copyright: Kateryna Golovanova , 2022 from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import DEC, JAN, JUN, MAR, MAY, NOV, SUN +from holidays.constants import JAN, MAR, MAY, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _islamic_to_gre class BosniaAndHerzegovina(HolidayBase): """ - Bosnia and Herzegovina holidays. - See https://en.wikipedia.org/wiki/Public_holidays_in_Bosnia_and_Herzegovina - for details. + https://en.wikipedia.org/wiki/Public_holidays_in_Bosnia_and_Herzegovina + https://www.paragraf.ba/neradni-dani-fbih.html + https://www.paragraf.ba/neradni-dani-republike-srpske.html + https://www.paragraf.ba/neradni-dani-brcko.html """ country = "BA" @@ -35,107 +36,114 @@ class BosniaAndHerzegovina(HolidayBase): ] def _populate(self, year): + def _add_holiday(hol_date: date, hol_name: str) -> None: + if hol_date.year == year: + self[hol_date] = hol_name + + # New Year's Day + new_year = date(year, JAN, 1) + self[new_year] = "Nova Godina" + self[new_year + td(days=+1)] = "Drugi dan Nove Godine" + + if ( + self.subdiv in {"FBiH", "BD"} + and self.observed + and self._is_sunday(new_year) + ): + self[new_year + td(days=+2)] = "Treći dan Nove Godine" + + # Orthodox Christmas Eve + if self.subdiv in {"FBiH", "RS"}: + self[date(year, JAN, 6)] = "Pravoslavno Badnje veče" - # New Year's Day. - self[date(year, JAN, 1)] = "Nova Godina" - self[date(year, JAN, 2)] = "Drugi dan Nove Godine" - - if self.observed and date(year, JAN, 1).weekday() == SUN: - self[date(year, JAN, 1) + rd(days=+2)] = "Treći dan Nove Godine" - - # Labor Day. - may_1 = date(year, MAY, 1) - self[may_1] = "Dan rada" - self[may_1 + rd(days=+1)] = "Drugi dan Dana rada" + # Orthodox Christmas + self[date(year, JAN, 7)] = "Božić (Божић)" - if self.observed and may_1.weekday() == SUN: - self[may_1 + rd(days=+2)] = "Treći dan Dana rada" + # Orthodox New Year + if self.subdiv == "RS": + self[date(year, JAN, 14)] = "Pravoslavna Nova Godina" + # Independence Day if self.subdiv == "FBiH": - # Independence Day. self[date(year, MAR, 1)] = "Dan nezavisnosti" - easter_date = easter(year) - # Catholic Good Friday. - self[easter_date + rd(days=-2)] = "Veliki Petak (Katolički)" + # Day of establishment of Brčko District + if self.subdiv == "BD": + self[date(year, MAR, 8)] = "Dan uspostavljanja Brčko distrikta" - # Catholic Easter. - self[easter_date] = "Uskrs (Katolički)" - self[easter_date + rd(days=+1)] = "Uskrsni ponedjeljak (Katolički)" - - # Corpus Cristi. + easter_date_catholic = easter(year) + easter_date_orthodox = easter(year, method=EASTER_ORTHODOX) + if self.subdiv in {"FBiH", "RS"}: + # Catholic Good Friday self[ - easter_date + rd(days=+60) - ] = "Tijelovo (Tijelo i Krv Kristova)" - - # Eid al-Fitr. - # Date of observance is announced yearly, this is an estimate. - for dt in _islamic_to_gre(year, 10, 1): - self[dt] = "Ramazanski Bajram" - self[dt + rd(days=+1)] = "Drugi Dan Ramazanski Bajram" - - # Eid ul-Adha. - # Date of observance is announced yearly, this is an estimate. - name = "Kurban Bajram" - for dt in _islamic_to_gre(year, 12, 10): - self[dt] = name - for d in range(1, 4): - self[dt + rd(days=+d)] = name - - # Islamic New Year. - for dt in _islamic_to_gre(year, 1, 1): - self[dt] = "Muslimanska Nova Godina" - - # All Saints Day. - self[date(year, 11, 1)] = "Svi Sveti" - - # All Souls Day. - self[date(year, 11, 2)] = "Dušni dan" - - # Statehood Day. - self[date(year, NOV, 25)] = "Dan državnosti" - - # Catholic Christmas. - self[date(year, DEC, 25)] = "Božić (Katolički)" - - # St. Stephen's Day. - self[date(year, DEC, 26)] = "Stipandan (Stjepandan)" - - elif self.subdiv == "RS": - # Orthodox Christmas Eve. - self[date(year, JAN, 6)] = "Pravoslavno Badnje veče" - - # Orthodox Christmas. - self[date(year, JAN, 7)] = "Božić (Божић)" - - # Republic day. - self[date(year, JAN, 9)] = "Dan Republike" + easter_date_catholic + td(days=-2) + ] = "Veliki Petak (Katolički)" - # Orthodox New Year. - self[date(year, JAN, 14)] = "Pravoslavna Nova Godina" + # Catholic Easter + self[easter_date_catholic] = "Uskrs (Katolički)" - easter_date = easter(year, method=EASTER_ORTHODOX) - # Orthodox Good Friday. - self[easter_date + rd(days=-2)] = "Veliki Petak (Pravoslavni)" + # Orthodox Easter + self[easter_date_orthodox] = "Vaskrs (Pravoslavni)" - # Orthodox Easter. - self[easter_date] = "Vaskrs (Pravoslavni)" + # Orthodox Easter Monday self[ - easter_date + rd(days=+1) + easter_date_orthodox + td(days=+1) ] = "Uskrsni ponedjeljak (Pravoslavni)" - # Victory Day. - self[date(year, MAY, 9)] = "Dan pobjede" + # Catholic Easter Monday + self[ + easter_date_catholic + td(days=+1) + ] = "Uskrsni ponedjeljak (Katolički)" - # St. Vitus Day. - self[date(year, JUN, 28)] = "Vidovdan" + # Orthodox Good Friday + self[easter_date_orthodox + td(days=-2)] = "Veliki Petak (Pravoslavni)" - # Dayton Agreement Day. + # Labor Day + may_1 = date(year, MAY, 1) + self[may_1] = "Dan rada" + self[may_1 + td(days=+1)] = "Drugi dan Dana rada" + + if self.observed and self._is_sunday(may_1): + self[may_1 + td(days=+2)] = "Treći dan Dana rada" + + # Victory Day + if self.subdiv in {"FBiH", "RS"}: + self[date(year, MAY, 9)] = "Dan pobjede nad fašizmom" + + for yr in (year - 1, year): + # Eid al-Fitr + # Date of observance is announced yearly, this is an estimate + for dt in _islamic_to_gre(yr, 10, 1): + _add_holiday(dt, "Ramazanski Bajram") + if self.subdiv in {"FBiH", "RS"}: + _add_holiday( + dt + td(days=+1), "Drugi Dan Ramazanski Bajram" + ) + # Eid ul-Adha + # Date of observance is announced yearly, this is an estimate + for dt in _islamic_to_gre(yr, 12, 10): + _add_holiday(dt, "Kurban Bajram") + if self.subdiv in {"FBiH", "RS"}: + _add_holiday(dt + td(days=+1), "Drugi Dan Kurban Bajram") + + # Dayton Agreement Day + if self.subdiv == "RS": self[date(year, NOV, 21)] = ( "Dan uspostave Opšteg okvirnog sporazuma za mir u " "Bosni i Hercegovini" ) + # Statehood Day + if self.subdiv == "FBiH": + self[date(year, NOV, 25)] = "Dan državnosti" + + # Catholic Christmas Eve + if self.subdiv in {"FBiH", "RS"}: + self[date(year, DEC, 24)] = "Badnji dan (Katolički)" + + # Catholic Christmas + self[date(year, DEC, 25)] = "Božić (Katolički)" + class BA(BosniaAndHerzegovina): pass diff --git a/holidays/countries/botswana.py b/holidays/countries/botswana.py index b679a06b1..8e89ee570 100644 --- a/holidays/countries/botswana.py +++ b/holidays/countries/botswana.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAY, JUL, SEP, OCT, DEC, SAT, SUN +from holidays.constants import JAN, MAY, JUL, SEP, DEC from holidays.holiday_base import HolidayBase @@ -31,67 +32,64 @@ class Botswana(HolidayBase): special_holidays = {2019: ((JUL, 2, "Public Holiday"),)} def _populate(self, year: int): + def _add_with_observed( + hol_date: date, hol_name1: str, hol_name2: str = None + ) -> None: + self[hol_date] = hol_name1 + if hol_name2: + self[hol_date + td(days=+1)] = hol_name2 + + if self.observed and year >= 1995: + if self._is_saturday(hol_date) and hol_name2: + self[hol_date + td(days=+2)] = f"{hol_name2} (Observed)" + elif self._is_sunday(hol_date): + self[ + hol_date + td(days=+2 if hol_name2 else +1) + ] = f"{hol_name1} (Observed)" + if year <= 1965: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" - self[date(year, JAN, 2)] = "New Year's Day Holiday" + _add_with_observed( + date(year, JAN, 1), "New Year's Day", "New Year's Day Holiday" + ) # Easter and easter related calculations easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=-1)] = "Holy Saturday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=-1)] = "Holy Saturday" + self[easter_date + td(days=+1)] = "Easter Monday" + self[easter_date + td(days=+39)] = "Ascension Day" - self[date(year, MAY, 1)] = "Labour Day" - self[easter_date + rd(days=+39)] = "Ascension Day" + _add_with_observed(date(year, MAY, 1), "Labour Day") + if ( + self.observed + and year >= 2016 + and self._is_saturday(date(year, MAY, 1)) + ): + self[date(year, MAY, 1) + td(days=+2)] = "Labour Day Holiday" - self[date(year, JUL, 1)] = "Sir Seretse Khama Day" + _add_with_observed(date(year, JUL, 1), "Sir Seretse Khama Day") # 3rd Monday of July = "President's Day" - d = date(year, JUL, 1) + rd(weekday=MO(+3)) - self[d] = "President's Day" - self[d + rd(days=+1)] = "President's Day Holiday" - - self[date(year, SEP, 30)] = "Botswana Day" - self[date(year, OCT, 1)] = "Botswana Day Holiday" - - self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Boxing Day" - - if self.observed: - for k, v in list(self.items()): - # Whenever Boxing Day falls on a Saturday, - # it rolls over to the following Monday - if ( - 2016 <= year == k.year - and k.weekday() == SAT - and v.upper() in {"BOXING DAY", "LABOUR DAY"} - ): - # Add the (Observed) holiday - self[k + rd(days=+2)] = v + " Holiday" - if ( - 1995 <= year == k.year - and k.weekday() == SUN - and v.upper() != "NEW YEAR'S DAY HOLIDAY" - ): - # Add the (Observed) holiday - self[k + rd(days=+1)] = v + " (Observed)" - - # If there is a holiday and an (Observed) holiday - # on the same day, add an (Observed) holiday for that holiday - hol_names = self.get(k).split(",") - if len(hol_names) > 1: - # self.get(date) returns a string containing holidays as a - # comma delimited string split on delimiter to determine if - # there are multiple on the same day - # Add an (Observed) for the one that is not (Observed) - for name in hol_names: - if " (Observed)" not in name: - self[k + rd(days=+1)] = ( - name.lstrip() + " (Observed)" - ) + dt = date(year, JUL, 1) + rd(weekday=MO(+3)) + self[dt] = "President's Day" + self[dt + td(days=+1)] = "President's Day Holiday" + + _add_with_observed( + date(year, SEP, 30), "Botswana Day", "Botswana Day Holiday" + ) + + _add_with_observed(date(year, DEC, 25), "Christmas Day", "Boxing Day") + + if ( + self.observed + and year >= 2016 + and self._is_saturday(date(year, DEC, 26)) + ): + self[date(year, DEC, 26) + td(days=+2)] = "Boxing Day Holiday" class BW(Botswana): diff --git a/holidays/countries/brazil.py b/holidays/countries/brazil.py index cee6e5f58..ed527090d 100644 --- a/holidays/countries/brazil.py +++ b/holidays/countries/brazil.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import SU @@ -78,16 +79,16 @@ def _populate(self, year): self[date(year, DEC, 25)] = "Natal" easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Sexta-feira Santa" + self[easter_date + td(days=-2)] = "Sexta-feira Santa" self[easter_date] = "Páscoa" - self[easter_date + rd(days=+60)] = "Corpus Christi" + self[easter_date + td(days=+60)] = "Corpus Christi" - quaresma = easter_date + rd(days=-46) + quaresma = easter_date + td(days=-46) self[quaresma] = "Quarta-feira de cinzas (Início da Quaresma)" - self[quaresma + rd(days=-1)] = "Carnaval" + self[quaresma + td(days=-1)] = "Carnaval" if self.subdiv == "AC": self[date(year, JAN, 23)] = "Dia do evangélico" diff --git a/holidays/countries/bulgaria.py b/holidays/countries/bulgaria.py index 605ccf3fe..ae1cfb818 100644 --- a/holidays/countries/bulgaria.py +++ b/holidays/countries/bulgaria.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, MAY, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -40,57 +40,66 @@ class Bulgaria(HolidayBase): """ country = "BG" + default_language = "bg" def _populate(self, year): - super()._populate(year) - if year < 1990: - return + return None + + super()._populate(year) - # New Year's Day - self[date(year, JAN, 1)] = "Нова година" + # New Year's Day. + self[date(year, JAN, 1)] = self.tr("Нова година") - # Liberation Day - self[ - date(year, MAR, 3) - ] = "Ден на Освобождението на България от османско иго" + # Liberation Day. + self[date(year, MAR, 3)] = self.tr( + "Ден на Освобождението на България от османско иго" + ) - # International Workers' Day - self[ - date(year, MAY, 1) - ] = "Ден на труда и на международната работническа солидарност" + # International Workers' Day. + self[date(year, MAY, 1)] = self.tr( + "Ден на труда и на международната работническа солидарност" + ) - # Saint George's Day - self[ - date(year, MAY, 6) - ] = "Гергьовден, Ден на храбростта и Българската армия" + # Saint George's Day. + self[date(year, MAY, 6)] = self.tr( + "Гергьовден, Ден на храбростта и Българската армия" + ) - # Bulgarian Education and Culture and Slavonic Literature Day - self[date(year, MAY, 24)] = ( + # Bulgarian Education and Culture and Slavonic Literature Day. + self[date(year, MAY, 24)] = self.tr( "Ден на светите братя Кирил и Методий, на българската азбука, " "просвета и култура и на славянската книжовност" ) - # Unification Day - self[date(year, SEP, 6)] = "Ден на Съединението" + # Unification Day. + self[date(year, SEP, 6)] = self.tr("Ден на Съединението") - # Independence Day - self[date(year, SEP, 22)] = "Ден на Независимостта на България" + # Independence Day. + self[date(year, SEP, 22)] = self.tr( + "Ден на Независимостта на България" + ) - # National Awakening Day - self[date(year, NOV, 1)] = "Ден на народните будители" + # National Awakening Day. + self[date(year, NOV, 1)] = self.tr("Ден на народните будители") - # Christmas - self[date(year, DEC, 24)] = "Бъдни вечер" - self[date(year, DEC, 25)] = "Рождество Христово" - self[date(year, DEC, 26)] = "Рождество Христово" + # Christmas Eve. + self[date(year, DEC, 24)] = self.tr("Бъдни вечер") + # Christmas Day 1. + self[date(year, DEC, 25)] = self.tr("Рождество Христово") + # Christmas Day 2. + self[date(year, DEC, 26)] = self.tr("Рождество Христово") - # Easter + # Easter. easter_date = easter(year, method=EASTER_ORTHODOX) - self[easter_date + rd(days=-2)] = "Велики петък" - self[easter_date + rd(days=-1)] = "Велика събота" - self[easter_date] = "Великден" - self[easter_date + rd(days=+1)] = "Великден" + # Good Friday. + self[easter_date + td(days=-2)] = self.tr("Велики петък") + # Easter Saturday. + self[easter_date + td(days=-1)] = self.tr("Велика събота") + # Easter Sunday. + self[easter_date] = self.tr("Великден") + # Easter Monday. + self[easter_date + td(days=+1)] = self.tr("Великден") class BG(Bulgaria): diff --git a/holidays/countries/burundi.py b/holidays/countries/burundi.py index ffd0cb18d..291144661 100644 --- a/holidays/countries/burundi.py +++ b/holidays/countries/burundi.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, APR, MAY, JUL, AUG, OCT, NOV, DEC, SUN +from holidays.constants import JAN, FEB, APR, MAY, JUN, JUL, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _islamic_to_gre @@ -34,80 +34,67 @@ class Burundi(HolidayBase): country = "BI" def _populate(self, year): - super()._populate(year) + def _add_with_observed(hol_date: date, hol_name: str) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + obs_date = hol_date + td(days=+1) + if obs_date.year == year: + self[obs_date] = f"{hol_name} (Observed)" + + if year <= 1961: + return None - def _add_holiday(dt: date, hol: str) -> None: - """Only add if in current year; prevents adding holidays across - years (handles multi-day Islamic holidays that straddle Gregorian - years). - """ - if dt.year == year: - self[dt] = hol + super()._populate(year) # New Year's Day - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") # Unity Day - name = "Unity Day" - self[date(year, FEB, 5)] = name - if date(year, FEB, 5).weekday() == SUN: - self[date(year, FEB, 6)] = name + " (Observed)" + if year >= 1992: + _add_with_observed(date(year, FEB, 5), "Unity Day") # President Ntaryamira Day - name = "President Ntaryamira Day" - self[date(year, APR, 6)] = "President Ntaryamira Day" - if date(year, APR, 6).weekday() == SUN: - self[date(year, APR, 7)] = name + " (Observed)" + if year >= 1995: + _add_with_observed(date(year, APR, 6), "President Ntaryamira Day") # Labour Day - name = "Labour Day" - self[date(year, MAY, 1)] = name - if date(year, MAY, 1).weekday() == SUN: - self[date(year, MAY, 2)] = name + " (Observed)" + _add_with_observed(date(year, MAY, 1), "Labour Day") # Ascension Day - name = "Ascension Day" - self[easter(year) + rd(days=+39)] = name + self[easter(year) + td(days=+39)] = "Ascension Day" - # Independence Day post 1962 - name = "Independence Day" - if year > 1961: - self[date(year, JUL, 1)] = name - if date(year, JUL, 1).weekday() == SUN: - self[date(year, JUL, 2)] = name + " (Observed)" + # President Nkurunziza Day + if year >= 2022: + _add_with_observed(date(year, JUN, 8), "President Nkurunziza Day") - # Eid Al Adha- Feast of the Sacrifice - # date of observance is announced yearly - for yr in (year - 1, year): - for date_obs in _islamic_to_gre(yr, 12, 10): - hol_date = date_obs - _add_holiday(hol_date, "Eid Al Adha") - _add_holiday(hol_date + rd(days=+1), "Eid Al Adha") + # Independence Day + _add_with_observed(date(year, JUL, 1), "Independence Day") # Assumption Day - name = "Assumption Day" - self[date(year, AUG, 15)] = name + _add_with_observed(date(year, AUG, 15), "Assumption Day") # Prince Louis Rwagasore Day - name = "Prince Louis Rwagasore Day" - self[date(year, OCT, 13)] = name - if date(year, OCT, 13).weekday() == SUN: - self[date(year, OCT, 14)] = name + " (Observed)" + _add_with_observed(date(year, OCT, 13), "Prince Louis Rwagasore Day") # President Ndadaye's Day - name = "President Ndadaye's Day" - self[date(year, OCT, 21)] = name - if date(year, OCT, 21).weekday() == SUN: - self[date(year, OCT, 22)] = name + " (Observed)" + if year >= 1994: + _add_with_observed(date(year, OCT, 21), "President Ndadaye's Day") # All Saints' Day - name = "All Saints' Day" - self[date(year, NOV, 1)] = name - if date(year, NOV, 1).weekday() == SUN: - self[date(year, NOV, 2)] = name + " (Observed)" + _add_with_observed(date(year, NOV, 1), "All Saints' Day") # Christmas Day - self[date(year, DEC, 25)] = "Christmas Day" + _add_with_observed(date(year, DEC, 25), "Christmas Day") + + # Eid ul Fitr + # date of observance is announced yearly + for dt in _islamic_to_gre(year, 10, 1): + _add_with_observed(dt, "Eid ul Fitr") + + # Eid al Adha + # date of observance is announced yearly + for dt in _islamic_to_gre(year, 12, 10): + _add_with_observed(dt, "Eid al Adha") class BI(Burundi): diff --git a/holidays/countries/canada.py b/holidays/countries/canada.py index eede8eea0..e9ef2e7a0 100644 --- a/holidays/countries/canada.py +++ b/holidays/countries/canada.py @@ -10,18 +10,20 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, SU from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC, FRI, SUN +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase class Canada(HolidayBase): country = "CA" + default_language = "en" subdivisions = [ "AB", "BC", @@ -44,24 +46,26 @@ def __init__(self, **kwargs): kwargs["subdiv"] = "ON" HolidayBase.__init__(self, **kwargs) - @staticmethod - def _get_nearest_monday(d: date) -> date: - if d.weekday() < FRI: - return d + rd(weekday=MO(-1)) - else: - return d + rd(weekday=MO) + def _get_nearest_monday(self, dt: date) -> date: + return ( + dt + rd(weekday=MO(-1)) + if not self._is_friday(dt) and not self._is_weekend(dt) + else dt + rd(weekday=MO) + ) def _populate(self, year): - super()._populate(year) - if year < 1867: - return + return None + + super()._populate(year) - # New Year's Day - name = "New Year's Day" + # New Year's Day. + name = self.tr("New Year's Day") self[date(year, JAN, 1)] = name - if self.observed and self._is_weekend(date(year, JAN, 1)): - self[date(year, JAN, 1) + rd(weekday=MO)] = name + " (Observed)" + if self.observed and self._is_weekend(year, JAN, 1): + self[date(year, JAN, 1) + rd(weekday=MO)] = ( + self.tr("%s (Observed)") % name + ) # Family Day / Louis Riel Day (MB) / Islander Day (PE) # / Heritage Day (NS, YT) @@ -71,21 +75,36 @@ def _populate(self, year): or (self.subdiv == "ON" and year >= 2008) or (self.subdiv == "NB" and year >= 2018) ): - self[date(year, FEB, 1) + rd(weekday=MO(+3))] = "Family Day" + self[date(year, FEB, 1) + rd(weekday=MO(+3))] = self.tr( + "Family Day" + ) elif self.subdiv == "BC": if 2013 <= year <= 2018: - self[date(year, FEB, 1) + rd(weekday=MO(+2))] = "Family Day" + self[date(year, FEB, 1) + rd(weekday=MO(+2))] = self.tr( + "Family Day" + ) elif year > 2018: - self[date(year, FEB, 1) + rd(weekday=MO(+3))] = "Family Day" + self[date(year, FEB, 1) + rd(weekday=MO(+3))] = self.tr( + "Family Day" + ) elif self.subdiv == "MB" and year >= 2008: - self[date(year, FEB, 1) + rd(weekday=MO(+3))] = "Louis Riel Day" + self[date(year, FEB, 1) + rd(weekday=MO(+3))] = self.tr( + "Louis Riel Day" + ) elif self.subdiv == "PE" and year >= 2010: - self[date(year, FEB, 1) + rd(weekday=MO(+3))] = "Islander Day" + self[date(year, FEB, 1) + rd(weekday=MO(+3))] = self.tr( + "Islander Day" + ) elif self.subdiv == "PE" and year == 2009: - self[date(year, FEB, 1) + rd(weekday=MO(+2))] = "Islander Day" + self[date(year, FEB, 1) + rd(weekday=MO(+2))] = self.tr( + "Islander Day" + ) + # http://novascotia.ca/lae/employmentrights/NovaScotiaHeritageDay.asp elif self.subdiv == "NS" and year >= 2015: - # http://novascotia.ca/lae/employmentrights/NovaScotiaHeritageDay.asp - self[date(year, FEB, 1) + rd(weekday=MO(+3))] = "Heritage Day" + # Heritage Day. + self[date(year, FEB, 1) + rd(weekday=MO(+3))] = self.tr( + "Heritage Day" + ) elif self.subdiv == "YT" and year >= 1974: # start date? # https://www.britannica.com/topic/Heritage-Day-Canadian-holiday @@ -97,23 +116,25 @@ def _populate(self, year): # Friday before the last Sunday in February dt = ( date(year, MAR, 1) - + rd(days=-1) + + td(days=-1) + rd(weekday=SU(-1)) - + rd(days=-2) + + td(days=-2) ) - self[dt] = "Heritage Day" + # Heritage Day. + self[dt] = self.tr("Heritage Day") - # St. Patrick's Day + # St. Patrick's Day. if self.subdiv == "NL" and year >= 1900: - # Nearest Monday to March 17 + # Nearest Monday to March 17. dt = self._get_nearest_monday(date(year, MAR, 17)) - self[dt] = "St. Patrick's Day" + # St. Patrick's Day. + self[dt] = self.tr("St. Patrick's Day") easter_date = easter(year) - # Good Friday - self[easter_date + rd(days=-2)] = "Good Friday" - # Easter Monday - self[easter_date + rd(days=+1)] = "Easter Monday" + # Good Friday. + self[easter_date + td(days=-2)] = self.tr("Good Friday") + # Easter Monday. + self[easter_date + td(days=+1)] = self.tr("Easter Monday") # St. George's Day if self.subdiv == "NL" and year >= 1990: @@ -124,76 +145,92 @@ def _populate(self, year): else: # Nearest Monday to April 23 dt = self._get_nearest_monday(date(year, APR, 23)) - self[dt] = "St. George's Day" + self[dt] = self.tr("St. George's Day") # Victoria Day / National Patriots' Day (QC) if year >= 1953: dt = date(year, MAY, 24) + rd(weekday=MO(-1)) if self.subdiv not in {"NB", "NS", "PE", "NL", "QC"}: - self[dt] = "Victoria Day" + self[dt] = self.tr("Victoria Day") elif self.subdiv == "QC": - self[dt] = "National Patriots' Day" + self[dt] = self.tr("National Patriots' Day") # National Aboriginal Day if self.subdiv == "NT" and year >= 1996: - self[date(year, JUN, 21)] = "National Aboriginal Day" + self[date(year, JUN, 21)] = self.tr("National Aboriginal Day") # St. Jean Baptiste Day if self.subdiv == "QC" and year >= 1925: - name = "St. Jean Baptiste Day" + name = self.tr("St. Jean Baptiste Day") dt = date(year, JUN, 24) self[dt] = name - if self.observed and dt.weekday() == SUN: - self[dt + rd(days=+1)] = name + " (Observed)" + if self.observed and self._is_sunday(dt): + self[dt + td(days=+1)] = self.tr("%s (Observed)") % name # Discovery Day if self.subdiv == "NL" and year >= 1997: # Nearest Monday to June 24 dt = self._get_nearest_monday(date(year, JUN, 24)) - self[dt] = "Discovery Day" + self[dt] = self.tr("Discovery Day") elif self.subdiv == "YT" and year >= 1912: - self[date(year, AUG, 1) + rd(weekday=MO(+3))] = "Discovery Day" + self[date(year, AUG, 1) + rd(weekday=MO(+3))] = self.tr( + "Discovery Day" + ) # Canada Day / Memorial Day (NL) if year >= 1983: - name = "Memorial Day" if self.subdiv == "NL" else "Canada Day" + name = ( + self.tr("Memorial Day") + if self.subdiv == "NL" + else self.tr("Canada Day") + ) else: - name = "Dominion Day" + name = self.tr("Dominion Day") dt = date(year, JUL, 1) self[dt] = name if year >= 1879 and self.observed and self._is_weekend(dt): - self[dt + rd(weekday=MO)] = name + " (Observed)" + self[dt + rd(weekday=MO)] = self.tr("%s (Observed)") % name # Nunavut Day if self.subdiv == "NU": - name = "Nunavut Day" + name = self.tr("Nunavut Day") if year >= 2001: dt = date(year, JUL, 9) self[dt] = name - if self.observed and dt.weekday() == SUN: - self[dt + rd(days=+1)] = name + " (Observed)" + if self.observed and self._is_sunday(dt): + self[dt + td(days=+1)] = self.tr("%s (Observed)") % name elif year == 2000: self[date(2000, APR, 1)] = name # Civic Holiday if year >= 1900 and self.subdiv in {"MB", "NT", "ON"}: - self[date(year, AUG, 1) + rd(weekday=MO)] = "Civic Holiday" + self[date(year, AUG, 1) + rd(weekday=MO)] = self.tr( + "Civic Holiday" + ) + # https://en.wikipedia.org/wiki/Civic_Holiday#Alberta elif year >= 1974 and self.subdiv == "AB": - # https://en.wikipedia.org/wiki/Civic_Holiday#Alberta - self[date(year, AUG, 1) + rd(weekday=MO)] = "Heritage Day" + # Heritage Day. + self[date(year, AUG, 1) + rd(weekday=MO)] = self.tr("Heritage Day") + # https://en.wikipedia.org/wiki/Civic_Holiday elif year >= 1974 and self.subdiv == "BC": - # https://en.wikipedia.org/wiki/Civic_Holiday - self[date(year, AUG, 1) + rd(weekday=MO)] = "British Columbia Day" + # British Columbia Day. + self[date(year, AUG, 1) + rd(weekday=MO)] = self.tr( + "British Columbia Day" + ) + # https://en.wikipedia.org/wiki/Civic_Holiday elif year >= 1900 and self.subdiv == "NB": - # https://en.wikipedia.org/wiki/Civic_Holiday - self[date(year, AUG, 1) + rd(weekday=MO)] = "New Brunswick Day" + self[date(year, AUG, 1) + rd(weekday=MO)] = self.tr( + "New Brunswick Day" + ) + # https://en.wikipedia.org/wiki/Civic_Holiday elif year >= 1900 and self.subdiv == "SK": - # https://en.wikipedia.org/wiki/Civic_Holiday - self[date(year, AUG, 1) + rd(weekday=MO)] = "Saskatchewan Day" + self[date(year, AUG, 1) + rd(weekday=MO)] = self.tr( + "Saskatchewan Day" + ) # Labour Day if year >= 1894: - self[date(year, SEP, 1) + rd(weekday=MO)] = "Labour Day" + self[date(year, SEP, 1) + rd(weekday=MO)] = self.tr("Labour Day") # Funeral of Queen Elizabeth II # https://www.narcity.com/provinces-territories-will-have-a-day-off-monday-mourn-queen @@ -206,51 +243,55 @@ def _populate(self, year): "PE", "YT", }: - self[ - date(2022, SEP, 19) - ] = "Funeral of Her Majesty the Queen Elizabeth II" + self[date(2022, SEP, 19)] = self.tr( + "Funeral of Her Majesty the Queen Elizabeth II" + ) # National Day for Truth and Reconciliation - if year >= 2021 and self.subdiv in {"MB", "NS"}: - self[ - date(year, SEP, 30) - ] = "National Day for Truth and Reconciliation" + if (year >= 2021 and self.subdiv in {"MB", "NS"}) or ( + year >= 2023 and self.subdiv == "BC" + ): + self[date(year, SEP, 30)] = self.tr( + "National Day for Truth and Reconciliation" + ) # Thanksgiving if year >= 1931 and self.subdiv not in {"NB", "NL", "NS", "PE"}: + # in 1935, Canadian Thanksgiving was moved due to the General + # Election falling on the second Monday of October + # https://books.google.ca/books?id=KcwlQsmheG4C&pg=RA1-PA1940&lpg=RA1-PA1940&dq=canada+thanksgiving+1935&source=bl&ots=j4qYrcfGuY&sig=gxXeAQfXVsOF9fOwjSMswPHJPpM&hl=en&sa=X&ved=0ahUKEwjO0f3J2PjOAhVS4mMKHRzKBLAQ6AEIRDAG#v=onepage&q=canada%20thanksgiving%201935&f=false if year == 1935: - # in 1935, Canadian Thanksgiving was moved due to the General - # Election falling on the second Monday of October - # https://books.google.ca/books?id=KcwlQsmheG4C&pg=RA1-PA1940&lpg=RA1-PA1940&dq=canada+thanksgiving+1935&source=bl&ots=j4qYrcfGuY&sig=gxXeAQfXVsOF9fOwjSMswPHJPpM&hl=en&sa=X&ved=0ahUKEwjO0f3J2PjOAhVS4mMKHRzKBLAQ6AEIRDAG#v=onepage&q=canada%20thanksgiving%201935&f=false - self[date(1935, OCT, 25)] = "Thanksgiving" + self[date(1935, OCT, 25)] = self.tr("Thanksgiving") else: - self[date(year, OCT, 1) + rd(weekday=MO(+2))] = "Thanksgiving" + self[date(year, OCT, 1) + rd(weekday=MO(+2))] = self.tr( + "Thanksgiving" + ) - # Remembrance Day + # Remembrance Day, if year >= 1931 and self.subdiv not in {"ON", "QC"}: - name = "Remembrance Day" + name = self.tr("Remembrance Day") dt = date(year, NOV, 11) self[dt] = name if ( self.observed - and dt.weekday() == SUN + and self._is_sunday(dt) and self.subdiv in {"NS", "NL", "NT", "PE", "SK"} ): - self[dt + rd(weekday=MO)] = name + " (Observed)" + self[dt + rd(weekday=MO)] = self.tr("%s (Observed)") % name - # Christmas Day - name = "Christmas Day" + # Christmas Day, + name = self.tr("Christmas Day") dt = date(year, DEC, 25) self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" + self[dt + td(days=+2)] = self.tr("%s (Observed)") % name - # Boxing Day - name = "Boxing Day" + # Boxing Day. + name = self.tr("Boxing Day") dt = date(year, DEC, 26) self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" + self[dt + td(days=+2)] = self.tr("%s (Observed)") % name class CA(Canada): diff --git a/holidays/countries/chile.py b/holidays/countries/chile.py index e144a33d8..7779ed725 100644 --- a/holidays/countries/chile.py +++ b/holidays/countries/chile.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date, datetime +from datetime import timedelta as td from dateutil import tz from dateutil.easter import easter @@ -19,7 +20,6 @@ from pymeeus.Sun import Sun from holidays.constants import JAN, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC -from holidays.constants import TUE, WED, THU, FRI, SAT, SUN from holidays.holiday_base import HolidayBase @@ -55,41 +55,41 @@ class Chile(HolidayBase): ] def _populate(self, year): - # Law 2.977 established official holidays for Chile # in its current form if year <= 1914: - return + return None + super()._populate(year) # New Year's Day (Law 2.977) self[date(year, JAN, 1)] = "Año Nuevo [New Year's Day]" # Day after, if it's a Sunday (Law 20.983) - if year >= 2017 and date(year, JAN, 1).weekday() == SUN: + if year >= 2017 and self._is_sunday(date(year, JAN, 1)): self[date(year, JAN, 2)] = "Fiestas Patrias [Holiday]" # Holy Week (Law 2.977) easter_date = easter(year) self[ - easter_date + rd(days=-2) + easter_date + td(days=-2) ] = "Semana Santa (Viernes Santo) [Good Friday)]" self[ - easter_date + rd(days=-1) + easter_date + td(days=-1) ] = "Semana Santa (Sábado Santo) [Good Saturday)]" # Ascension if year <= 1967: self[ - easter_date + rd(days=+39) + easter_date + td(days=+39) ] = "Ascensión del Señor [Ascension of Jesus]" # Corpus Christi if year <= 1967 or 1987 <= year <= 2006: # Law 19.668 if year <= 1999: - dt = easter_date + rd(days=+60) + dt = easter_date + td(days=+60) else: - dt = easter_date + rd(days=+57) + dt = easter_date + td(days=+57) self[dt] = "Corpus Christi [Corpus Christi]" # Labour Day (Law 2.200, renamed with Law 18.018) @@ -122,9 +122,9 @@ def _populate(self, year): dt = date(year, JUN, 29) if year >= 2000: # floating Monday holiday (Law 19.668) - if dt.weekday() < FRI: + if not self._is_friday(dt) and not self._is_weekend(dt): dt += rd(weekday=MO(-1)) - elif dt.weekday() == FRI: + elif self._is_friday(dt): dt += rd(weekday=MO) self[dt] = "San Pedro y San Pablo [Saint Peter and Saint Paul]" @@ -152,11 +152,11 @@ def _populate(self, year): # National Holiday Friday preceding Independence Day (Law 20.983) # Monday, September 17, 2007, is declared a holiday. - if year >= 2017 and date(year, SEP, 18).weekday() == SAT: + if year >= 2017 and self._is_saturday(date(year, SEP, 18)): self[date(year, SEP, 17)] = "Fiestas Patrias [Holiday]" # National Holiday Monday preceding Independence Day (Law 20.215) - if year >= 2007 and date(year, SEP, 18).weekday() == TUE: + if year >= 2007 and self._is_tuesday(date(year, SEP, 18)): self[date(year, SEP, 17)] = "Fiestas Patrias [Holiday]" # Independence Day (Law 2.977) @@ -170,7 +170,7 @@ def _populate(self, year): ] = "Día de las Glorias del Ejército [Army Day]" # National Holiday Friday following Army Day (Law 20.215) - if year >= 2008 and date(year, SEP, 19).weekday() == THU: + if year >= 2008 and self._is_thursday(date(year, SEP, 19)): self[date(year, SEP, 20)] = "Fiestas Patrias [Holiday]" # Decree-law 636, Law 8.223 @@ -183,9 +183,9 @@ def _populate(self, year): name = "Día de la Raza [Columbus day]" if year >= 2000: # floating Monday holiday (Law 19.668) - if dt.weekday() < FRI: + if not self._is_friday(dt) and not self._is_weekend(dt): dt += rd(weekday=MO(-1)) - elif dt.weekday() == FRI: + elif self._is_friday(dt): dt += rd(weekday=MO) if year <= 2019: # Day of the Meeting of Two Worlds (Law 3.810) @@ -206,10 +206,10 @@ def _populate(self, year): # This holiday is moved to the preceding Friday # if it falls on a Tuesday, or to the following Friday # if it falls on a Wednesday (Law 20.299) - if dt.weekday() == WED: - dt += rd(days=+2) - elif dt.weekday() == TUE: - dt += rd(days=-4) + if self._is_wednesday(dt): + dt += td(days=+2) + elif self._is_tuesday(dt): + dt += td(days=-4) self[dt] = ( "Día Nacional de las Iglesias Evangélicas y Protestantes" " [Reformation Day]" diff --git a/holidays/countries/china.py b/holidays/countries/china.py index a0c0e2db7..422532061 100644 --- a/holidays/countries/china.py +++ b/holidays/countries/china.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, APR, MAY, OCT from holidays.holiday_base import HolidayBase @@ -30,10 +29,10 @@ def __init__(self, **kwargs): HolidayBase.__init__(self, **kwargs) def _populate(self, year): - super()._populate(year) - if year <= 1949: - return + return None + + super()._populate(year) self[date(year, JAN, 1)] = "New Year's Day" @@ -41,24 +40,24 @@ def _populate(self, year): dt = date(year, MAY, 1) self[dt] = name if 2000 <= year <= 2007: - self[dt + rd(days=+1)] = name - self[dt + rd(days=+2)] = name + self[dt + td(days=+1)] = name + self[dt + td(days=+2)] = name name = "Chinese New Year (Spring Festival)" dt = self.cnls.lunar_n_y_date(year) self[dt] = name - self[dt + rd(days=+1)] = name + self[dt + td(days=+1)] = name if 2008 <= year <= 2013: - self[dt + rd(days=-1)] = name + self[dt + td(days=-1)] = name else: - self[dt + rd(days=+2)] = name + self[dt + td(days=+2)] = name name = "National Day" dt = date(year, OCT, 1) self[dt] = name - self[dt + rd(days=+1)] = name + self[dt + td(days=+1)] = name if year >= 2000: - self[dt + rd(days=+2)] = name + self[dt + td(days=+2)] = name if year >= 2008: self[date(year, APR, 5)] = "Tomb-Sweeping Day" diff --git a/holidays/countries/colombia.py b/holidays/countries/colombia.py index 6b4a9eaac..78a01925f 100644 --- a/holidays/countries/colombia.py +++ b/holidays/countries/colombia.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, MAY, JUN, JUL, AUG, OCT, NOV, DEC, MON +from holidays.constants import JAN, MAR, MAY, JUN, JUL, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -30,7 +31,7 @@ class Colombia(HolidayBase): country = "CO" - def _add_with_bridge(self, _date, name): + def _add_with_bridge(self, dt, name): """ On the 6th of December 1983, the government of Colombia declared which holidays are to take effect, and also clarified that a subset of them @@ -46,10 +47,10 @@ def _add_with_bridge(self, _date, name): 1984: https://bit.ly/3B7ogt8 """ - if self.observed and _date.weekday() != MON and _date.year > 1983: - self[_date + rd(weekday=MO)] = name + " (Observed)" + if self.observed and not self._is_monday(dt) and dt.year > 1983: + self[dt + rd(weekday=MO)] = name + " (Observed)" else: - self[_date] = name + self[dt] = name def _populate(self, year): super()._populate(year) @@ -149,29 +150,29 @@ def _add_easter_based_holidays(self, year): def _add_fixed_easter_based_holidays(self, _easter): if _easter.year > 1950: # Maundy Thursday - self[_easter + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[_easter + td(days=-3)] = "Jueves Santo [Maundy Thursday]" # Good Friday - self[_easter + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[_easter + td(days=-2)] = "Viernes Santo [Good Friday]" def _add_flexible_easter_based_holidays(self, _easter): if _easter.year > 1950: # Ascension of Jesus self._add_with_bridge( - _easter + rd(days=+39), + _easter + td(days=+39), "Ascensión del señor [Ascension of Jesus]", ) # Corpus Christi self._add_with_bridge( - _easter + rd(days=+60), + _easter + td(days=+60), "Corpus Christi [Corpus Christi]", ) if _easter.year > 1983: # Sacred Heart self._add_with_bridge( - _easter + rd(days=+68), + _easter + td(days=+68), "Sagrado Corazón [Sacred Heart]", ) diff --git a/holidays/countries/croatia.py b/holidays/countries/croatia.py index 4d023e6b5..d80104f60 100644 --- a/holidays/countries/croatia.py +++ b/holidays/countries/croatia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUN, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -40,10 +40,10 @@ def _populate(self, year): # Easter self[easter_date] = "Uskrs" # Easter Monday - self[easter_date + rd(days=+1)] = "Uskrsni ponedjeljak" + self[easter_date + td(days=+1)] = "Uskrsni ponedjeljak" # Corpus Christi - self[easter_date + rd(days=+60)] = "Tijelovo" + self[easter_date + td(days=+60)] = "Tijelovo" # International Workers' Day self[date(year, MAY, 1)] = "Međunarodni praznik rada" diff --git a/holidays/countries/cuba.py b/holidays/countries/cuba.py index d1312a988..abc9e6e31 100644 --- a/holidays/countries/cuba.py +++ b/holidays/countries/cuba.py @@ -10,12 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import MO -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAY, JUL, OCT, DEC, SUN +from holidays.constants import JAN, MAY, JUL, OCT, DEC from holidays.holiday_base import HolidayBase @@ -23,6 +22,10 @@ class Cuba(HolidayBase): country = "CU" def _populate(self, year): + def _add_observed(hol_date: date) -> None: + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{self[hol_date]} (Observed)" + super()._populate(year) """ @@ -39,17 +42,15 @@ def _populate(self, year): go to the next Monday. """ - name = "Aniversario de la Revolución [Anniversary of the Revolution]" - self[date(year, JAN, 1)] = name - if ( - year <= 2013 - and self.observed - and date(year, JAN, 1).weekday() == SUN - ): - self[date(year, JAN, 1) + rd(weekday=MO)] = name + " (Observed)" + dt = date(year, JAN, 1) + self[ + dt + ] = "Aniversario de la Revolución [Anniversary of the Revolution]" + if year <= 2013: + _add_observed(dt) # Granted in 2007 decree. - if year > 2007: + if year >= 2008: self[date(year, JAN, 2)] = "Día de la Victoria [Victory Day]" # Granted temporarily in 2012 and 2013: @@ -57,12 +58,11 @@ def _populate(self, year): # https://bit.ly/3v6bM18 # Permanently granted in 2013 decree for 2014 and onwards. if year >= 2012: - self[easter(year) + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter(year) + td(days=-2)] = "Viernes Santo [Good Friday]" - name = "Día Internacional de los Trabajadores [Labour Day]" - self[date(year, MAY, 1)] = name - if self.observed and date(year, MAY, 1).weekday() == SUN: - self[date(year, MAY, 1) + rd(weekday=MO)] = name + " (Observed)" + dt = date(year, MAY, 1) + self[dt] = "Día Internacional de los Trabajadores [Labour Day]" + _add_observed(dt) self[date(year, JUL, 25)] = ( "Conmemoración del asalto a Moncada " @@ -78,10 +78,9 @@ def _populate(self, year): "[Commemoration of the Assault of the Moncada garrison]" ) - name = "Inicio de las Guerras de Independencia [Independence Day]" - self[date(year, OCT, 10)] = name - if self.observed and date(year, OCT, 10).weekday() == SUN: - self[date(year, OCT, 10) + rd(weekday=MO)] = name + " (Observed)" + dt = date(year, OCT, 10) + self[dt] = "Inicio de las Guerras de Independencia [Independence Day]" + _add_observed(dt) # In 1969, Christmas was cancelled for the sugar harvest but then was # cancelled for good: @@ -91,7 +90,7 @@ def _populate(self, year): # In 1998, Christmas returns for good: # https://bit.ly/3cyXhwz # https://bit.ly/3cyXj7F - if year >= 1997 or year < 1969: + if year <= 1968 or year >= 1997: self[date(year, DEC, 25)] = "Día de Navidad [Christmas Day]" # Granted in 2007 decree. diff --git a/holidays/countries/curacao.py b/holidays/countries/curacao.py index 53c684482..5bbb06e6d 100644 --- a/holidays/countries/curacao.py +++ b/holidays/countries/curacao.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, APR, MAY, JUL, AUG, OCT, DEC, SUN +from holidays.constants import JAN, APR, MAY, JUL, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -34,22 +34,22 @@ def _populate(self, year): easter_date = easter(year) # Carnaval Monday self[ - easter_date + rd(days=-48) + easter_date + td(days=-48) ] = "Maandag na de Grote Karnaval [Carnaval Monday]" # Good Friday - self[easter_date + rd(days=-2)] = "Goede Vrijdag [Good Friday]" + self[easter_date + td(days=-2)] = "Goede Vrijdag [Good Friday]" # Easter Monday self[ - easter_date + rd(days=+1) + easter_date + td(days=+1) ] = "Di Dos Dia di Pasku di Resureccion [Easter Monday]" # King's Day if year >= 2014: kings_day = date(year, APR, 27) - if kings_day.weekday() == SUN: - kings_day += rd(days=-1) + if self._is_sunday(kings_day): + kings_day += td(days=-1) self[kings_day] = "Koningsdag [King's Day]" @@ -59,19 +59,19 @@ def _populate(self, year): if year <= 1948: queens_day = date(year, AUG, 31) - if queens_day.weekday() == SUN: - queens_day += rd(days=1) if year < 1980 else rd(days=-1) + if self._is_sunday(queens_day): + queens_day += td(days=1) if year < 1980 else td(days=-1) self[queens_day] = "Anja di La Reina [Queen's Day]" # Labour Day labour_day = date(year, MAY, 1) - if labour_day.weekday() == SUN: - labour_day += rd(days=+1) + if self._is_sunday(labour_day): + labour_day += td(days=+1) self[labour_day] = "Dia di Obrero [Labour Day]" # Ascension Day - self[easter_date + rd(days=+39)] = "Hemelvaartsdag [Ascension Day]" + self[easter_date + td(days=+39)] = "Hemelvaartsdag [Ascension Day]" # Dia di Himno y Bandera self[ diff --git a/holidays/countries/cyprus.py b/holidays/countries/cyprus.py index 3f5650925..288d5e8c8 100644 --- a/holidays/countries/cyprus.py +++ b/holidays/countries/cyprus.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -20,71 +20,69 @@ class Cyprus(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Cyprus + Cyprus holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Cyprus """ country = "CY" + default_language = "el" def _populate(self, year): super()._populate(year) easter_date = easter(year, method=EASTER_ORTHODOX) - # New Years - self[date(year, JAN, 1)] = "Πρωτοχρονιά [New Year's Day]" + # New Years Day. + self[date(year, JAN, 1)] = self.tr("Πρωτοχρονιά") - # Epiphany - self[date(year, JAN, 6)] = "Θεοφάνεια [Epiphany]" + # Epiphany. + self[date(year, JAN, 6)] = self.tr("Θεοφάνεια") - # Clean Monday - self[easter_date + rd(days=-48)] = "Καθαρά Δευτέρα [Clean Monday]" + # Clean Monday. + self[easter_date + td(days=-48)] = self.tr("Καθαρά Δευτέρα") - # Greek Independence Day - self[ - date(year, MAR, 25) - ] = "Εικοστή Πέμπτη Μαρτίου [Greek Independence Day]" + # Greek Independence Day. + self[date(year, MAR, 25)] = self.tr("Εικοστή Πέμπτη Μαρτίου") - # Cyprus National Day - self[date(year, APR, 1)] = "1η Απριλίου [Cyprus National Day]" + # Cyprus National Day. + self[date(year, APR, 1)] = self.tr("1η Απριλίου") - # Good Friday - self[easter_date + rd(days=-2)] = "Μεγάλη Παρασκευή [Good Friday]" + # Good Friday. + self[easter_date + td(days=-2)] = self.tr("Μεγάλη Παρασκευή") - # Easter Sunday - self[easter_date] = "Κυριακή του Πάσχα [Easter Sunday]" + # Easter Sunday. + self[easter_date] = self.tr("Κυριακή του Πάσχα") - # Easter Monday - self[easter_date + rd(days=+1)] = "Δευτέρα του Πάσχα [Easter Monday]" + # Easter Monday. + self[easter_date + td(days=+1)] = self.tr("Δευτέρα του Πάσχα") - # Labour Day - self[date(year, MAY, 1)] = "Εργατική Πρωτομαγιά [Labour day]" + # Labour Day. + self[date(year, MAY, 1)] = self.tr("Εργατική Πρωτομαγιά") - # Monday of the Holy Spirit - self[ - easter_date + rd(days=+50) - ] = "Δευτέρα του Αγίου Πνεύματος [Monday of the Holy Spirit]" + # Monday of the Holy Spirit. + self[easter_date + td(days=+50)] = self.tr( + "Δευτέρα του Αγίου Πνεύματος" + ) - # Assumption of Mary - self[date(year, AUG, 15)] = "Κοίμηση της Θεοτόκου [Assumption of Mary]" + # Assumption of Mary. + self[date(year, AUG, 15)] = self.tr("Κοίμηση της Θεοτόκου") - # Cyprus Independence Day - self[ - date(year, OCT, 1) - ] = "Ημέρα Ανεξαρτησίας της Κύπρου [Cyprus Independence Day]" + # Cyprus Independence Day. + self[date(year, OCT, 1)] = self.tr("Ημέρα Ανεξαρτησίας της Κύπρου") - # Ochi Day - self[date(year, OCT, 28)] = "Ημέρα του Όχι [Ochi Day]" + # Ochi Day. + self[date(year, OCT, 28)] = self.tr("Ημέρα του Όχι") - # Christmas Eve - self[date(year, DEC, 24)] = "Παραμονή Χριστουγέννων [Christmas Eve]" + # Christmas Eve. + self[date(year, DEC, 24)] = self.tr("Παραμονή Χριστουγέννων") - # Christmas - self[date(year, DEC, 25)] = "Χριστούγεννα [Christmas]" + # Christmas Day. + self[date(year, DEC, 25)] = self.tr("Χριστούγεννα") - # Day after Christmas - self[ - date(year, DEC, 26) - ] = "Δεύτερη μέρα Χριστουγέννων [Day after Christmas]" + # Day After Christmas. + self[date(year, DEC, 26)] = self.tr("Δεύτερη μέρα Χριστουγέννων") class CY(Cyprus): diff --git a/holidays/countries/czechia.py b/holidays/countries/czechia.py index 490758a38..b73cba022 100644 --- a/holidays/countries/czechia.py +++ b/holidays/countries/czechia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUL, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -36,8 +36,8 @@ def _populate(self, year): easter_date = easter(year) if year <= 1951 or year >= 2016: - self[easter_date + rd(days=-2)] = "Velký pátek" - self[easter_date + rd(days=+1)] = "Velikonoční pondělí" + self[easter_date + td(days=-2)] = "Velký pátek" + self[easter_date + td(days=+1)] = "Velikonoční pondělí" if year >= 1951: self[date(year, MAY, 1)] = "Svátek práce" diff --git a/holidays/countries/denmark.py b/holidays/countries/denmark.py index a5e8d38b7..656d691c9 100644 --- a/holidays/countries/denmark.py +++ b/holidays/countries/denmark.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, DEC from holidays.holiday_base import HolidayBase @@ -20,28 +20,31 @@ class Denmark(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Denmark + Denmark holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Denmark """ country = "DK" + default_language = "da" def _populate(self, year): super()._populate(year) easter_date = easter(year) - # Public holidays - self[date(year, JAN, 1)] = "Nytårsdag" - self[easter_date + rd(days=-7)] = "Palmesøndag" - self[easter_date + rd(days=-3)] = "Skærtorsdag" - self[easter_date + rd(days=-2)] = "Langfredag" - self[easter_date] = "Påskedag" - self[easter_date + rd(days=+1)] = "Anden påskedag" - self[easter_date + rd(days=+26)] = "Store bededag" - self[easter_date + rd(days=+39)] = "Kristi himmelfartsdag" - self[easter_date + rd(days=+49)] = "Pinsedag" - self[easter_date + rd(days=+50)] = "Anden pinsedag" - self[date(year, DEC, 25)] = "Juledag" - self[date(year, DEC, 26)] = "Anden juledag" + self[date(year, JAN, 1)] = self.tr("Nytårsdag") + self[easter_date + td(days=-7)] = self.tr("Palmesøndag") + self[easter_date + td(days=-3)] = self.tr("Skærtorsdag") + self[easter_date + td(days=-2)] = self.tr("Langfredag") + self[easter_date] = self.tr("Påskedag") + self[easter_date + td(days=+1)] = self.tr("Anden påskedag") + self[easter_date + td(days=+26)] = self.tr("Store bededag") + self[easter_date + td(days=+39)] = self.tr("Kristi himmelfartsdag") + self[easter_date + td(days=+49)] = self.tr("Pinsedag") + self[easter_date + td(days=+50)] = self.tr("Anden pinsedag") + self[date(year, DEC, 25)] = self.tr("Juledag") + self[date(year, DEC, 26)] = self.tr("Anden juledag") class DK(Denmark): diff --git a/holidays/countries/djibouti.py b/holidays/countries/djibouti.py index a855ceefc..e0e84cf6f 100644 --- a/holidays/countries/djibouti.py +++ b/holidays/countries/djibouti.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, MAY, JUN, FRI, SAT from holidays.holiday_base import HolidayBase @@ -22,7 +21,6 @@ class Djibouti(HolidayBase): - # Holidays here are estimates, it is common for the day to be pushed # if falls in a weekend, although not a rule that can be implemented. # Holidays after 2020: the following four moving date holidays whose exact @@ -77,7 +75,7 @@ def _add_holiday(dt: date, hol: str) -> None: hol_date = date_obs _add_holiday(hol_date, "Eid al-Fitr") _add_holiday( - hol_date + rd(days=+1), "Eid al-Fitr deuxième jour" + hol_date + td(days=+1), "Eid al-Fitr deuxième jour" ) # Arafat & Eid al-Adha - Scarfice Festive @@ -86,9 +84,9 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 12, 9): hol_date = date_obs _add_holiday(hol_date, "Arafat") - _add_holiday(hol_date + rd(days=+1), "Eid al-Adha") + _add_holiday(hol_date + td(days=+1), "Eid al-Adha") _add_holiday( - hol_date + rd(days=+2), "Eid al-Adha deuxième jour" + hol_date + td(days=+2), "Eid al-Adha deuxième jour" ) # Islamic New Year - (hijari_year, 1, 1) diff --git a/holidays/countries/dominican_republic.py b/holidays/countries/dominican_republic.py index 1c508a17f..1e15b3abd 100644 --- a/holidays/countries/dominican_republic.py +++ b/holidays/countries/dominican_republic.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO @@ -61,7 +62,7 @@ def _populate(self, year): easter_date = easter(year) # Good Friday - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" # Labor Day labor_day = self.__change_day_by_law( @@ -71,7 +72,7 @@ def _populate(self, year): # Feast of Corpus Christi self[ - easter_date + rd(days=+60) + easter_date + td(days=+60) ] = "Corpus Christi [Feast of Corpus Christi]" # Restoration Day diff --git a/holidays/countries/egypt.py b/holidays/countries/egypt.py index 802d831dc..48ec830a2 100644 --- a/holidays/countries/egypt.py +++ b/holidays/countries/egypt.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAY, JUN, JUL, OCT from holidays.holiday_base import HolidayBase @@ -20,7 +20,6 @@ class Egypt(HolidayBase): - # Holidays here are estimates, it is common for the day to be pushed # if falls in a weekend, although not a rule that can be implemented. # Holidays after 2020: the following four moving date holidays whose exact @@ -66,7 +65,7 @@ def _add_holiday(dt: date, hol: str) -> None: self[easter_date] = "Coptic Easter Sunday" # Sham El Nessim - Spring Festival - self[easter_date + rd(days=+1)] = "Sham El Nessim" + self[easter_date + td(days=+1)] = "Sham El Nessim" # Sinai Libration Day if year > 1982: @@ -95,8 +94,8 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 10, 1): hol_date = date_obs _add_holiday(hol_date, "Eid al-Fitr") - _add_holiday(hol_date + rd(days=+1), "Eid al-Fitr Holiday") - _add_holiday(hol_date + rd(days=+2), "Eid al-Fitr Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Fitr Holiday") + _add_holiday(hol_date + td(days=+2), "Eid al-Fitr Holiday") # Arafat Day & Eid al-Adha - Scarfice Festive # date of observance is announced yearly @@ -104,9 +103,9 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 12, 9): hol_date = date_obs _add_holiday(hol_date, "Arafat Day") - _add_holiday(hol_date + rd(days=+1), "Eid al-Adha") - _add_holiday(hol_date + rd(days=+2), "Eid al-Adha Holiday") - _add_holiday(hol_date + rd(days=+3), "Eid al-Adha Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Adha") + _add_holiday(hol_date + td(days=+2), "Eid al-Adha Holiday") + _add_holiday(hol_date + td(days=+3), "Eid al-Adha Holiday") # Islamic New Year - (hijari_year, 1, 1) for date_obs in _islamic_to_gre(year, 1, 1): diff --git a/holidays/countries/estonia.py b/holidays/countries/estonia.py index d09056317..44468a5d9 100644 --- a/holidays/countries/estonia.py +++ b/holidays/countries/estonia.py @@ -10,16 +10,15 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAY, JUN, AUG, DEC from holidays.holiday_base import HolidayBase class Estonia(HolidayBase): - country = "EE" def _populate(self, year): @@ -34,7 +33,7 @@ def _populate(self, year): self[date(year, FEB, 24)] = "iseseisvuspäev" # Good Friday - self[easter_date + rd(days=-2)] = "suur reede" + self[easter_date + td(days=-2)] = "suur reede" # Easter Sunday self[easter_date] = "ülestõusmispühade 1. püha" @@ -43,7 +42,7 @@ def _populate(self, year): self[date(year, MAY, 1)] = "kevadpüha" # Pentecost - self[easter_date + rd(days=+49)] = "nelipühade 1. püha" + self[easter_date + td(days=+49)] = "nelipühade 1. püha" # Victory Day self[date(year, JUN, 23)] = "võidupüha" diff --git a/holidays/countries/eswatini.py b/holidays/countries/eswatini.py index f06c5a814..7c4656e7e 100644 --- a/holidays/countries/eswatini.py +++ b/holidays/countries/eswatini.py @@ -11,11 +11,11 @@ import warnings from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, APR, MAY, JUL, SEP, DEC, SUN +from holidays.constants import JAN, APR, MAY, JUL, SEP, DEC from holidays.holiday_base import HolidayBase @@ -33,44 +33,58 @@ class Eswatini(HolidayBase): } def _populate(self, year): + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + # As of 2021/1/1, whenever a public holiday falls on a Sunday + # it rolls over to the following Monday + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date) and year >= 2021: + self[hol_date + td(days=days)] = f"{hol_name} (Observed)" + # Observed since 1939 if year <= 1938: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" - self[easter_date + rd(days=+39)] = "Ascension Day" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" + self[easter_date + td(days=+39)] = "Ascension Day" + + if year >= 1987: + # https://www.officeholidays.com/holidays/swaziland/birthday-of-king-mswati-iii + # In 2071, 2076, 2082 Apr 20 is Easter Monday, + # so observed on Apr 21 (Tue) + _add_with_observed( + date(year, APR, 19), + "King's Birthday", + +2 if year in {2071, 2076, 2082} else +1, + ) if year >= 1969: - self[date(year, APR, 25)] = "National Flag Day" + # In 2038 Apr 26 is Easter Monday, + # so observed on Apr 27 (Tue) + _add_with_observed( + date(year, APR, 25), + "National Flag Day", + +2 if year == 2038 else +1, + ) + + _add_with_observed(date(year, MAY, 1), "Worker's Day") if year >= 1983: # https://www.officeholidays.com/holidays/swaziland/birthday-of-late-king-sobhuza - self[date(year, JUL, 22)] = "Birthday of Late King Sobhuza" + _add_with_observed( + date(year, JUL, 22), "Birthday of Late King Sobhuza" + ) - if year >= 1987: - # https://www.officeholidays.com/holidays/swaziland/birthday-of-king-mswati-iii - self[date(year, APR, 19)] = "King's Birthday" - - self[date(year, MAY, 1)] = "Worker's Day" - self[date(year, SEP, 6)] = "Independence Day" - self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Boxing Day" - - # As of 2021/1/1, whenever a public holiday falls on a - # Sunday - # it rolls over to the following Monday - if self.observed and year >= 2021: - for k, v in list(self.items()): - if k.weekday() == SUN and k.year == year: - dt = k + rd(days=+1) - while self.get(dt): - dt += rd(days=+1) - self[dt] = v + " (Observed)" + _add_with_observed(date(year, SEP, 6), "Independence Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day", days=+2) + _add_with_observed(date(year, DEC, 26), "Boxing Day") class Swaziland(Eswatini): diff --git a/holidays/countries/ethiopia.py b/holidays/countries/ethiopia.py index 9eef373b4..eda6521c9 100644 --- a/holidays/countries/ethiopia.py +++ b/holidays/countries/ethiopia.py @@ -9,11 +9,10 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -from calendar import isleap from datetime import date +from datetime import timedelta as td from dateutil.easter import easter, EASTER_ORTHODOX -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, MAY, SEP from holidays.holiday_base import HolidayBase @@ -34,8 +33,21 @@ class Ethiopia(HolidayBase): - country = "ET" + default_language = "am" + + @staticmethod + def _is_leap_year(year): + """ + Ethiopian leap years are coincident with leap years in the Gregorian + calendar until the end of February 2100. It starts earlier from new + year of western calendar. + Ethiopian leap year starts on Sep 11, so it has an effect on + holidays between Sep 11 and Jan 1. Therefore, here on the following + function we intentionally add 1 to the leap year to offset the + difference. + """ + return HolidayBase._is_leap_year(year + 1) def _populate(self, year): super()._populate(year) @@ -47,82 +59,79 @@ def _populate(self, year): # It occurs on September 11 in the Gregorian Calendar; # except for the year preceding a leap year, when it occurs on # September 12. - if self.ethiopian_isleap(year): - self[date(year, SEP, 12)] = "አዲስ ዓመት እንቁጣጣሽ/Ethiopian New Year" + if self._is_leap_year(year): + # Ethiopian New Year. + self[date(year, SEP, 12)] = self.tr("አዲስ ዓመት እንቁጣጣሽ") else: - self[date(year, SEP, 11)] = "አዲስ ዓመት እንቁጣጣሽ/Ethiopian New Year" + # Ethiopian New Year. + self[date(year, SEP, 11)] = self.tr("አዲስ ዓመት እንቁጣጣሽ") - # Finding of true cross - if self.ethiopian_isleap(year): - self[date(year, SEP, 28)] = "መስቀል/Finding of True Cross" + # Finding of true cross. + if self._is_leap_year(year): + # Finding of True Cross. + self[date(year, SEP, 28)] = self.tr("መስቀል") else: - self[date(year, SEP, 27)] = "መስቀል/Finding of True Cross" + # Finding of True Cross. + self[date(year, SEP, 27)] = self.tr("መስቀል") - # Ethiopian Christmas - self[date(year, JAN, 7)] = "ገና/Ethiopian X-Mas" + # Orthodox Christmas. + self[date(year, JAN, 7)] = self.tr("ገና") - # Ethiopian Ephiphany - self[date(year, JAN, 19)] = "ጥምቀት/Ephiphany" + # Orthodox Epiphany. + self[date(year, JAN, 19)] = self.tr("ጥምቀት") - # Ethiopian Good Friday easter_date = easter(year, EASTER_ORTHODOX) - self[easter_date + rd(days=-2)] = "ስቅለት/Ethiopian Good Friday" + # Orthodox Good Friday. + self[easter_date + td(days=-2)] = self.tr("ስቅለት") - # Ethiopian Easter - Orthodox Easter - self[easter_date] = "ፋሲካ/Ethiopian Easter" + # Orthodox Easter Sunday. + self[easter_date] = self.tr("ፋሲካ") - # Adwa Victory Day if year > 1896: - self[date(year, MAR, 2)] = "አድዋ/Victory of Adwa" + # Adwa Victory Day. + self[date(year, MAR, 2)] = self.tr("አድዋ") - # Labour Day - self[date(year, MAY, 1)] = "የሰራተኞች ቀን/Labor Day" + # Labour Day. + self[date(year, MAY, 1)] = self.tr("የሰራተኞች ቀን") - # Patriots Day if year > 1941: - self[date(year, MAY, 5)] = "የአርበኞች ቀን/Patriots Day" + # Patriots Day. + self[date(year, MAY, 5)] = self.tr("የአርበኞች ቀን") - # Derg Downfall Day if year > 1991: - self[ - date(year, MAY, 28) - ] = "ደርግ የወደቀበት ቀን/Downfall of Dergue regime" + # Downfall of Dergue Regime Day. + self[date(year, MAY, 28)] = self.tr("ደርግ የወደቀበት ቀን") - # Downfall of King. Hailesilassie if year < 1991 and year > 1974: - if self.ethiopian_isleap(year): - self[date(year, SEP, 13)] = "ደርግ የመጣበት ቀን/Formation of Dergue" + # Downfall of King Haile Selassie. + name = self.tr("ደርግ የመጣበት ቀን") + if self._is_leap_year(year): + self[date(year, SEP, 13)] = name else: - self[date(year, SEP, 12)] = "ደርግ የመጣበት ቀን/Formation of Dergue" + self[date(year, SEP, 12)] = name # Eid al-Fitr - Feast Festive # date of observance is announced yearly, This is an estimate since # having the Holiday on Weekend does change the number of days, - # deceided to leave it since marking a Weekend as a holiday + # decided to leave it since marking a Weekend as a holiday # wouldn't do much harm. for date_obs in _islamic_to_gre(year, 10, 1): hol_date = date_obs - self[hol_date] = "ኢድ አልፈጥር/Eid-Al-Fitr" + # Eid al-Fitr. + self[hol_date] = self.tr("ኢድ አልፈጥር") - # Eid al-Adha - Scarfice Festive + # Eid al-Adha - Sacrifice Festive # date of observance is announced yearly for date_obs in _islamic_to_gre(year, 12, 9): hol_date = date_obs - self[hol_date + rd(days=+1)] = "አረፋ/Eid-Al-Adha" + # Eid al-Adha. + self[hol_date + td(days=+1)] = self.tr("አረፋ") # Prophet Muhammad's Birthday - (hijari_year, 3, 12) for date_obs in _islamic_to_gre(year, 3, 12): hol_date = date_obs - self[hol_date + rd(days=+1)] = "መውሊድ/Prophet Muhammad's Birthday" - - # Ethiopian leap years are coincident with leap years in the Gregorian - # calendar until the end of February 2100. It starts earlier from new year - # of western calendar. - # Ethiopian leap year starts on Sep 11, so it has an effect on - # holidays between Sep 11 and Jan 1. Therefore, here on the following - # function we intentionally add 1 to the leap year to offset the difference - def ethiopian_isleap(self, year): - return isleap(year + 1) + # Prophet Muhammad's Birthday. + self[hol_date + td(days=+1)] = self.tr("መውሊድ") class ET(Ethiopia): diff --git a/holidays/countries/finland.py b/holidays/countries/finland.py index 156ad930c..21018ef5c 100644 --- a/holidays/countries/finland.py +++ b/holidays/countries/finland.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import FR, SA @@ -33,12 +34,12 @@ def _populate(self, year): self[date(year, JAN, 1)] = "Uudenvuodenpäivä" self[date(year, JAN, 6)] = "Loppiainen" - self[easter_date + rd(days=-2)] = "Pitkäperjantai" + self[easter_date + td(days=-2)] = "Pitkäperjantai" self[easter_date] = "Pääsiäispäivä" - self[easter_date + rd(days=+1)] = "2. pääsiäispäivä" + self[easter_date + td(days=+1)] = "2. pääsiäispäivä" self[date(year, MAY, 1)] = "Vappu" - self[easter_date + rd(days=+39)] = "Helatorstai" - self[easter_date + rd(days=+49)] = "Helluntaipäivä" + self[easter_date + td(days=+39)] = "Helatorstai" + self[easter_date + td(days=+49)] = "Helluntaipäivä" self[date(year, JUN, 20) + rd(weekday=SA)] = "Juhannuspäivä" self[date(year, OCT, 31) + rd(weekday=SA)] = "Pyhäinpäivä" self[date(year, DEC, 6)] = "Itsenäisyyspäivä" diff --git a/holidays/countries/france.py b/holidays/countries/france.py index 97e03273e..e540ca131 100644 --- a/holidays/countries/france.py +++ b/holidays/countries/france.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -87,17 +87,17 @@ def _populate(self, year): "Martinique", "Polynésie Française", }: - self[easter_date + rd(days=-2)] = "Vendredi saint" + self[easter_date + td(days=-2)] = "Vendredi saint" if self.subdiv == "Alsace-Moselle": self[date(year, DEC, 26)] = "Deuxième jour de Noël" if year >= 1886: - self[easter_date + rd(days=+1)] = "Lundi de Pâques" - self[easter_date + rd(days=+50)] = "Lundi de Pentecôte" + self[easter_date + td(days=+1)] = "Lundi de Pâques" + self[easter_date + td(days=+50)] = "Lundi de Pentecôte" if year >= 1802: - self[easter_date + rd(days=+39)] = "Ascension" + self[easter_date + td(days=+39)] = "Ascension" self[date(year, AUG, 15)] = "Assomption" self[date(year, NOV, 1)] = "Toussaint" diff --git a/holidays/countries/georgia.py b/holidays/countries/georgia.py index 525fa6541..bfb5ca985 100644 --- a/holidays/countries/georgia.py +++ b/holidays/countries/georgia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, AUG, OCT, NOV from holidays.holiday_base import HolidayBase @@ -20,82 +20,71 @@ class Georgia(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Georgia_(country) + Georgia holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Georgia_(country) """ country = "GE" + default_language = "ka" def _populate(self, year): super()._populate(year) - # New Year's Day - name = "ახალი წელი" - self[date(year, JAN, 1)] = name + # New Year's Day. + self[date(year, JAN, 1)] = self.tr("ახალი წელი") - # New Year's Day - name = "ბედობა" - self[date(year, JAN, 2)] = name + # New Year's Day. + self[date(year, JAN, 2)] = self.tr("ბედობა") - # Christmas Day (Orthodox) - name = "ქრისტეშობა" - self[date(year, JAN, 7)] = name + # Orthodox Christmas Day. + self[date(year, JAN, 7)] = self.tr("ქრისტეშობა") - # Baptism Day of our Lord Jesus Christ - name = "ნათლისღება" - self[date(year, JAN, 19)] = name + # Baptism Day of our Lord Jesus Christ. + self[date(year, JAN, 19)] = self.tr("ნათლისღება") - # Mother's Day - name = "დედის დღე" - self[date(year, MAR, 3)] = name + # Mother's Day. + self[date(year, MAR, 3)] = self.tr("დედის დღე") - # Women's Day - name = "ქალთა საერთაშორისო დღე" - self[date(year, MAR, 8)] = name + # Women's Day. + self[date(year, MAR, 8)] = self.tr("ქალთა საერთაშორისო დღე") easter_date = easter(year, method=EASTER_ORTHODOX) - # Orthodox Good Friday - name = "წითელი პარასკევი" - self[easter_date + rd(days=-2)] = name + # Orthodox Good Friday. + self[easter_date + td(days=-2)] = self.tr("წითელი პარასკევი") - # Orthodox Holy Saturday - name = "დიდი შაბათი" - self[easter_date + rd(days=-1)] = name + # Orthodox Holy Saturday. + self[easter_date + td(days=-1)] = self.tr("დიდი შაბათი") - # Orthodox Easter Sunday - name = "აღდგომა" - self[easter_date] = name + # Orthodox Easter Sunday. + self[easter_date] = self.tr("აღდგომა") - # Orthodox Easter Monday - name = "შავი ორშაბათი" - self[easter_date + rd(days=+1)] = name + # Orthodox Easter Monday. + self[easter_date + td(days=+1)] = self.tr("შავი ორშაბათი") - # National Unity Day - name = "ეროვნული ერთიანობის დღე" - self[date(year, APR, 9)] = name + # National Unity Day. + self[date(year, APR, 9)] = self.tr("ეროვნული ერთიანობის დღე") - # Day of Victory - name = "ფაშიზმზე გამარჯვების დღე" - self[date(year, MAY, 9)] = name + # Day of Victory. + self[date(year, MAY, 9)] = self.tr("ფაშიზმზე გამარჯვების დღე") - # Saint Andrew the First-Called Day - name = "წმინდა ანდრია პირველწოდებულის დღე" - self[date(year, MAY, 12)] = name + # Saint Andrew the First-Called Day. + self[date(year, MAY, 12)] = self.tr( + "წმინდა ანდრია პირველწოდებულის დღე" + ) - # Independence Day - name = "დამოუკიდებლობის დღე" - self[date(year, MAY, 26)] = name + # Independence Day. + self[date(year, MAY, 26)] = self.tr("დამოუკიდებლობის დღე") - # Saint Mary's Day - name = "მარიამობა" - self[date(year, AUG, 28)] = name + # Saint Mary's Day. + self[date(year, AUG, 28)] = self.tr("მარიამობა") - # Day of Svetitskhoveli Cathedral - name = "სვეტიცხოვლობა" - self[date(year, OCT, 14)] = name + # Day of Svetitskhoveli Cathedral. + self[date(year, OCT, 14)] = self.tr("სვეტიცხოვლობა") - # Saint George's Day - name = "გიორგობა" - self[date(year, NOV, 23)] = name + # Saint George's Day. + self[date(year, NOV, 23)] = self.tr("გიორგობა") class GE(Georgia): diff --git a/holidays/countries/germany.py b/holidays/countries/germany.py index b8b6f5716..859d6c7a6 100644 --- a/holidays/countries/germany.py +++ b/holidays/countries/germany.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import WE @@ -76,13 +77,12 @@ class Germany(HolidayBase): ] def _populate(self, year): - super()._populate(year) - if year <= 1989: - return + return None - if year > 1990: + super()._populate(year) + if year > 1990: self[date(year, JAN, 1)] = "Neujahr" if self.subdiv in {"BW", "BY", "BYP", "ST"}: @@ -90,7 +90,7 @@ def _populate(self, year): easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Karfreitag" + self[easter_date + td(days=-2)] = "Karfreitag" if self.subdiv == "BB": # will always be a Sunday and we have no "observed" rule so @@ -98,7 +98,7 @@ def _populate(self, year): # holiday by law self[easter_date] = "Ostersonntag" - self[easter_date + rd(days=+1)] = "Ostermontag" + self[easter_date + td(days=+1)] = "Ostermontag" self[date(year, MAY, 1)] = "Erster Mai" @@ -108,18 +108,18 @@ def _populate(self, year): "und der Beendigung des Zweiten Weltkriegs in Europa" ) - self[easter_date + rd(days=+39)] = "Christi Himmelfahrt" + self[easter_date + td(days=+39)] = "Christi Himmelfahrt" if self.subdiv == "BB": # will always be a Sunday and we have no "observed" rule so # this is pretty pointless but it's nonetheless an official # holiday by law - self[easter_date + rd(days=+49)] = "Pfingstsonntag" + self[easter_date + td(days=+49)] = "Pfingstsonntag" - self[easter_date + rd(days=+50)] = "Pfingstmontag" + self[easter_date + td(days=+50)] = "Pfingstmontag" if self.subdiv in {"BW", "BY", "BYP", "HE", "NW", "RP", "SL"}: - self[easter_date + rd(days=+60)] = "Fronleichnam" + self[easter_date + td(days=+60)] = "Fronleichnam" if self.subdiv in {"BY", "SL"}: self[date(year, AUG, 15)] = "Mariä Himmelfahrt" @@ -147,6 +147,10 @@ def _populate(self, year): if self.subdiv == "BE": self[date(year, MAR, 8)] = "Internationaler Frauentag" + if year >= 2023: + if self.subdiv == "MV": + self[date(year, MAR, 8)] = "Internationaler Frauentag" + self[date(year, DEC, 25)] = "Erster Weihnachtstag" self[date(year, DEC, 26)] = "Zweiter Weihnachtstag" diff --git a/holidays/countries/greece.py b/holidays/countries/greece.py index f206369ce..c7a3b4ff8 100644 --- a/holidays/countries/greece.py +++ b/holidays/countries/greece.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter from dateutil.relativedelta import MO, TU @@ -21,38 +22,43 @@ class Greece(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Greece + Greece holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Greece """ country = "GR" + default_language = "el" def _populate(self, year): super()._populate(year) easter_date = easter(year, method=EASTER_ORTHODOX) - # New Years - self[date(year, JAN, 1)] = "Πρωτοχρονιά [New Year's Day]" - # Epiphany - self[date(year, JAN, 6)] = "Θεοφάνεια [Epiphany]" + # New Year's Day. + self[date(year, JAN, 1)] = self.tr("Πρωτοχρονιά") + + # Epiphany. + self[date(year, JAN, 6)] = self.tr("Θεοφάνεια") - # Clean Monday - self[easter_date + rd(days=-48)] = "Καθαρά Δευτέρα [Clean Monday]" + # Clean Monday. + self[easter_date + td(days=-48)] = self.tr("Καθαρά Δευτέρα") - # Independence Day - self[date(year, MAR, 25)] = "Εικοστή Πέμπτη Μαρτίου [Independence Day]" + # Independence Day. + self[date(year, MAR, 25)] = self.tr("Εικοστή Πέμπτη Μαρτίου") - # Easter Monday - self[easter_date + rd(days=+1)] = "Δευτέρα του Πάσχα [Easter Monday]" + # Easter Monday. + self[easter_date + td(days=+1)] = self.tr("Δευτέρα του Πάσχα") - # Monday of the Holy Spirit - self[ - easter_date + rd(days=+50) - ] = "Δευτέρα του Αγίου Πνεύματος [Monday of the Holy Spirit]" + # Monday of the Holy Spirit. + self[easter_date + td(days=+50)] = self.tr( + "Δευτέρα του Αγίου Πνεύματος" + ) - # Labour Day - name = "Εργατική Πρωτομαγιά [Labour day]" - name_observed = name + " (Observed)" + # Labour Day. + name = self.tr("Εργατική Πρωτομαγιά") + name_observed = self.tr("%s (παρατηρήθηκε)") self[date(year, MAY, 1)] = name if self.observed and self._is_weekend(year, MAY, 1): @@ -62,21 +68,19 @@ def _populate(self, year): # https://www.timeanddate.com/holidays/greece/labor-day if self.get(labour_day_observed_date): labour_day_observed_date += rd(weekday=TU) - self[labour_day_observed_date] = name_observed + self[labour_day_observed_date] = name_observed % name - # Assumption of Mary - self[date(year, AUG, 15)] = "Κοίμηση της Θεοτόκου [Assumption of Mary]" + # Assumption of Mary. + self[date(year, AUG, 15)] = self.tr("Κοίμηση της Θεοτόκου") - # Ochi Day - self[date(year, OCT, 28)] = "Ημέρα του Όχι [Ochi Day]" + # Ochi Day. + self[date(year, OCT, 28)] = self.tr("Ημέρα του Όχι") - # Christmas - self[date(year, DEC, 25)] = "Χριστούγεννα [Christmas]" + # Christmas Day. + self[date(year, DEC, 25)] = self.tr("Χριστούγεννα") - # Day after Christmas - self[ - date(year, DEC, 26) - ] = "Επόμενη ημέρα των Χριστουγέννων [Day after Christmas]" + # Day after Christmas. + self[date(year, DEC, 26)] = self.tr("Επόμενη ημέρα των Χριστουγέννων") class GR(Greece): diff --git a/holidays/countries/guam.py b/holidays/countries/guam.py new file mode 100644 index 000000000..5bd7839dd --- /dev/null +++ b/holidays/countries/guam.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysGU(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "GU" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "GU" + super()._populate(year) + + +class GU(HolidaysGU): + pass + + +class GUM(HolidaysGU): + pass + + +class Guam(HolidaysGU): + pass diff --git a/holidays/countries/honduras.py b/holidays/countries/honduras.py index 58ec54ecd..992eafc26 100644 --- a/holidays/countries/honduras.py +++ b/holidays/countries/honduras.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import WE @@ -33,13 +34,13 @@ def _populate(self, year): easter_date = easter(year) # Maundy Thursday - self[easter_date + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Maundy Thursday]" # Good Friday - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" # Holy Saturday - self[easter_date + rd(days=-1)] = "Sábado de Gloria [Holy Saturday]" + self[easter_date + td(days=-1)] = "Sábado de Gloria [Holy Saturday]" # Panamerican Day self[date(year, APR, 14)] = "Día de las Américas [Panamerican Day]" @@ -68,8 +69,8 @@ def _populate(self, year): holiday_name = "Semana Morazánica [Morazan Weekend]" first_wednesday = date(year, OCT, 1) + rd(weekday=WE(+1)) self[first_wednesday] = holiday_name - self[first_wednesday + rd(days=+1)] = holiday_name - self[first_wednesday + rd(days=+2)] = holiday_name + self[first_wednesday + td(days=+1)] = holiday_name + self[first_wednesday + td(days=+2)] = holiday_name # Christmas self[date(year, DEC, 25)] = "Navidad [Christmas]" diff --git a/holidays/countries/hongkong.py b/holidays/countries/hongkong.py index 19f0c8019..f6e5228be 100644 --- a/holidays/countries/hongkong.py +++ b/holidays/countries/hongkong.py @@ -10,13 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, OCT, DEC -from holidays.constants import MON, TUE, WED, THU, FRI, SAT, SUN from holidays.holiday_base import HolidayBase from holidays.utils import _ChineseLuniSolar @@ -50,15 +50,16 @@ def __init__(self, **kwargs): def _populate(self, year): # Current set of holidays actually valid since 1946 if year <= 1945: - return + return None + super()._populate(year) day_following = "The day following " # The first day of January first_date = date(year, JAN, 1) - if self.observed and first_date.weekday() == SUN: - self[first_date + rd(days=+1)] = ( + if self.observed and self._is_sunday(first_date): + self[first_date + td(days=+1)] = ( day_following + "the first day of January" ) else: @@ -72,64 +73,52 @@ def _populate(self, year): fourth_day_lunar = "The fourth day of Lunar New Year" new_year_date = self.cnls.lunar_n_y_date(year) if self.observed: - self[new_year_date] = name - if new_year_date.weekday() in {MON, TUE, WED, THU}: - self[new_year_date] = name - self[new_year_date + rd(days=+1)] = second_day_lunar - self[new_year_date + rd(days=+2)] = third_day_lunar - if new_year_date.weekday() == FRI: - self[new_year_date] = name - self[new_year_date + rd(days=+1)] = second_day_lunar - self[new_year_date + rd(days=+3)] = fourth_day_lunar - if new_year_date.weekday() == SAT: - self[new_year_date] = name - self[new_year_date + rd(days=+2)] = third_day_lunar - self[new_year_date + rd(days=+3)] = fourth_day_lunar - if new_year_date.weekday() == SUN: + if self._is_sunday(new_year_date): if year in {2006, 2007, 2010}: - self[new_year_date + rd(days=-1)] = preceding_day_lunar + self[new_year_date + td(days=-1)] = preceding_day_lunar else: - self[new_year_date + rd(days=+3)] = fourth_day_lunar + self[new_year_date + td(days=+3)] = fourth_day_lunar else: self[new_year_date] = name - if new_year_date.weekday() == SAT: - self[new_year_date + rd(days=+3)] = fourth_day_lunar + if self._is_saturday(new_year_date): + self[new_year_date + td(days=+3)] = fourth_day_lunar else: - self[new_year_date + rd(days=+1)] = second_day_lunar - if new_year_date.weekday() == FRI: - self[new_year_date + rd(days=+3)] = fourth_day_lunar + self[new_year_date + td(days=+1)] = second_day_lunar + if self._is_friday(new_year_date): + self[new_year_date + td(days=+3)] = fourth_day_lunar else: - self[new_year_date + rd(days=+2)] = third_day_lunar + self[new_year_date + td(days=+2)] = third_day_lunar else: self[new_year_date] = name - self[new_year_date + rd(days=+1)] = second_day_lunar - self[new_year_date + rd(days=+2)] = third_day_lunar + self[new_year_date + td(days=+1)] = second_day_lunar + self[new_year_date + td(days=+2)] = third_day_lunar easter_date = easter(year) - easter_monday_date = easter_date + rd(days=+1) + easter_monday_date = easter_date + td(days=+1) + # Ching Ming Festival name = "Ching Ming Festival" - if self.is_leap_year(year) or ( - year > 2008 and self.is_leap_year(year - 1) + if self._is_leap_year(year) or ( + year > 2008 and self._is_leap_year(year - 1) ): ching_ming_date = date(year, APR, 4) else: ching_ming_date = date(year, APR, 5) if self.observed and ( - ching_ming_date.weekday() == SUN + self._is_sunday(ching_ming_date) or ching_ming_date == easter_monday_date ): - self[ching_ming_date + rd(days=+1)] = day_following + name + self[ching_ming_date + td(days=+1)] = day_following + name else: self[ching_ming_date] = name # Easter Holiday good_friday = "Good Friday" easter_monday = "Easter Monday" - self[easter_date + rd(days=-2)] = good_friday - self[easter_date + rd(days=-1)] = day_following + good_friday + self[easter_date + td(days=-2)] = good_friday + self[easter_date + td(days=-1)] = day_following + good_friday if self.observed and self.get(easter_monday_date): - self[easter_monday_date + rd(days=+1)] = ( + self[easter_monday_date + td(days=+1)] = ( day_following + easter_monday ) else: @@ -139,8 +128,8 @@ def _populate(self, year): if year >= 1998: name = "The Birthday of the Buddha" buddha_date = self.cnls.lunar_to_gre(year, 4, 8) - if self.observed and buddha_date.weekday() == SUN: - self[buddha_date + rd(days=+1)] = day_following + name + if self.observed and self._is_sunday(buddha_date): + self[buddha_date + td(days=+1)] = day_following + name else: self[buddha_date] = name @@ -148,16 +137,16 @@ def _populate(self, year): if year >= 1998: name = "Labour Day" labour_date = date(year, MAY, 1) - if self.observed and labour_date.weekday() == SUN: - self[labour_date + rd(days=+1)] = day_following + name + if self.observed and self._is_sunday(labour_date): + self[labour_date + td(days=+1)] = day_following + name else: self[labour_date] = name # Tuen Ng Festival name = "Tuen Ng Festival" tuen_ng_date = self.cnls.lunar_to_gre(year, 5, 5) - if self.observed and tuen_ng_date.weekday() == SUN: - self[tuen_ng_date + rd(days=+1)] = day_following + name + if self.observed and self._is_sunday(tuen_ng_date): + self[tuen_ng_date + td(days=+1)] = day_following + name else: self[tuen_ng_date] = name @@ -165,8 +154,8 @@ def _populate(self, year): if year >= 1997: name = "Hong Kong Special Administrative Region Establishment Day" hksar_date = date(year, JUL, 1) - if self.observed and hksar_date.weekday() == SUN: - self[hksar_date + rd(days=+1)] = day_following + name + if self.observed and self._is_sunday(hksar_date): + self[hksar_date + td(days=+1)] = day_following + name else: self[hksar_date] = name @@ -178,15 +167,15 @@ def _populate(self, year): # before 1983 public holiday lies on Monday # from 1983 to 2010 public holiday lies on same day # since 2011 public holiday lies on Monday - if mid_autumn_date.weekday() == SAT: + if self._is_saturday(mid_autumn_date): if 1983 <= year <= 2010: self[mid_autumn_date] = name else: - self[mid_autumn_date + rd(days=+2)] = ( + self[mid_autumn_date + td(days=+2)] = ( "The second day of the " + name + " (Monday)" ) else: - self[mid_autumn_date + rd(days=+1)] = ( + self[mid_autumn_date + td(days=+1)] = ( day_following + "the " + name ) else: @@ -197,17 +186,17 @@ def _populate(self, year): name = "National Day" national_date = date(year, OCT, 1) if self.observed and ( - national_date.weekday() == SUN or self.get(national_date) + self._is_sunday(national_date) or self.get(national_date) ): - self[national_date + rd(days=+1)] = day_following + name + self[national_date + td(days=+1)] = day_following + name else: self[national_date] = name # Chung Yeung Festival name = "Chung Yeung Festival" chung_yeung_date = self.cnls.lunar_to_gre(year, 9, 9) - if self.observed and chung_yeung_date.weekday() == SUN: - self[chung_yeung_date + rd(days=+1)] = day_following + name + if self.observed and self._is_sunday(chung_yeung_date): + self[chung_yeung_date + td(days=+1)] = day_following + name else: self[chung_yeung_date] = name @@ -217,18 +206,18 @@ def _populate(self, year): second_after_christmas = "The second weekday after " + name christmas_date = date(year, DEC, 25) if self.observed: - if christmas_date.weekday() == SUN: - self[christmas_date + rd(days=+1)] = first_after_christmas - self[christmas_date + rd(days=+2)] = second_after_christmas - elif christmas_date.weekday() == SAT: + if self._is_sunday(christmas_date): + self[christmas_date + td(days=+1)] = first_after_christmas + self[christmas_date + td(days=+2)] = second_after_christmas + elif self._is_saturday(christmas_date): self[christmas_date] = name - self[christmas_date + rd(days=+2)] = first_after_christmas + self[christmas_date + td(days=+2)] = first_after_christmas else: self[christmas_date] = name - self[christmas_date + rd(days=+1)] = first_after_christmas + self[christmas_date + td(days=+1)] = first_after_christmas else: self[christmas_date] = name - self[christmas_date + rd(days=+1)] = day_following + name + self[christmas_date + td(days=+1)] = day_following + name # Previous holidays if 1952 <= year <= 1997: @@ -243,13 +232,9 @@ def _populate(self, year): # Anniversary of the victory in the Second Sino-Japanese War self[ - dt + rd(days=-1) + dt + td(days=-1) ] = "Anniversary of the victory in the Second Sino-Japanese War" - @staticmethod - def is_leap_year(year): - return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) - class HK(HongKong): pass diff --git a/holidays/countries/hungary.py b/holidays/countries/hungary.py index 101d765b9..7430167ef 100644 --- a/holidays/countries/hungary.py +++ b/holidays/countries/hungary.py @@ -10,12 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, APR, MAY, AUG, OCT, NOV, DEC, MON -from holidays.constants import TUE, THU +from holidays.constants import JAN, MAR, APR, MAY, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -61,21 +60,21 @@ def _populate(self, year: int) -> None: # Good Friday if 2017 <= year: - self[easter_date + rd(days=-2)] = "Nagypéntek" + self[easter_date + td(days=-2)] = "Nagypéntek" # Easter self[easter_date] = "Húsvét" # Second easter day if 1955 != year: - self[easter_date + rd(days=+1)] = "Húsvét Hétfő" + self[easter_date + td(days=+1)] = "Húsvét Hétfő" # Pentecost - self[easter_date + rd(days=+49)] = "Pünkösd" + self[easter_date + td(days=+49)] = "Pünkösd" # Pentecost monday if year <= 1952 or 1992 <= year: - self[easter_date + rd(days=+50)] = "Pünkösdhétfő" + self[easter_date + td(days=+50)] = "Pünkösdhétfő" # International Workers' Day if 1946 <= year: @@ -129,12 +128,9 @@ def _populate(self, year: int) -> None: # New Year's Eve # Since 2014, the last day of the year is an observed day off if New # Year's Day falls on a Tuesday. - if ( - self.observed - and 2014 <= year - and date(year, DEC, 31).weekday() == MON - ): - self[date(year, DEC, 31)] = "Szilveszter" + dec_31 = date(year, DEC, 31) + if self.observed and 2014 <= year and self._is_monday(dec_31): + self[dec_31] = "Szilveszter" def _add_with_observed_day_off( self, @@ -149,10 +145,10 @@ def _add_with_observed_day_off( self[day] = desc # TODO: should it be a separate flag? if self.observed and since <= day.year: - if day.weekday() == TUE and before: - self[day + rd(days=-1)] = desc + " előtti pihenőnap" - elif day.weekday() == THU and after: - self[day + rd(days=+1)] = desc + " utáni pihenőnap" + if self._is_tuesday(day) and before: + self[day + td(days=-1)] = desc + " előtti pihenőnap" + elif self._is_thursday(day) and after: + self[day + td(days=+1)] = desc + " utáni pihenőnap" class HU(Hungary): diff --git a/holidays/countries/iceland.py b/holidays/countries/iceland.py index ba581537b..85203fcfd 100644 --- a/holidays/countries/iceland.py +++ b/holidays/countries/iceland.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, TH @@ -33,15 +34,15 @@ def _populate(self, year): # Public holidays self[date(year, JAN, 1)] = "Nýársdagur" easter_date = easter(year) - self[easter_date + rd(days=-3)] = "Skírdagur" - self[easter_date + rd(days=-2)] = "Föstudagurinn langi" + self[easter_date + td(days=-3)] = "Skírdagur" + self[easter_date + td(days=-2)] = "Föstudagurinn langi" self[easter_date] = "Páskadagur" - self[easter_date + rd(days=+1)] = "Annar í páskum" + self[easter_date + td(days=+1)] = "Annar í páskum" self[date(year, APR, 19) + rd(weekday=TH(+1))] = "Sumardagurinn fyrsti" self[date(year, MAY, 1)] = "Verkalýðsdagurinn" - self[easter_date + rd(days=+39)] = "Uppstigningardagur" - self[easter_date + rd(days=+49)] = "Hvítasunnudagur" - self[easter_date + rd(days=+50)] = "Annar í hvítasunnu" + self[easter_date + td(days=+39)] = "Uppstigningardagur" + self[easter_date + td(days=+49)] = "Hvítasunnudagur" + self[easter_date + td(days=+50)] = "Annar í hvítasunnu" self[date(year, JUN, 17)] = "Þjóðhátíðardagurinn" # First Monday of August self[ diff --git a/holidays/countries/india.py b/holidays/countries/india.py index 1529dbc2c..be6b953bb 100644 --- a/holidays/countries/india.py +++ b/holidays/countries/india.py @@ -11,9 +11,9 @@ import warnings from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, JUN, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -269,20 +269,20 @@ def _populate(self, year): name = "Eid ul-Fitr" for dt in _islamic_to_gre(year, 10, 1): self[dt] = f"{name}* (*estimated)" - self[dt + rd(days=+1)] = f"{name}* (*estimated)" + self[dt + td(days=+1)] = f"{name}* (*estimated)" # Eid al-Adha, i.e., Feast of the Sacrifice name = "Eid al-Adha" for dt in _islamic_to_gre(year, 12, 10): self[dt] = f"{name}* (*estimated)" - self[dt + rd(days=+1)] = f"{name}* (*estimated)" + self[dt + td(days=+1)] = f"{name}* (*estimated)" # Christian holidays easter_date = easter(year) - self[easter_date + rd(days=-7)] = "Palm Sunday" - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-7)] = "Palm Sunday" + self[easter_date + td(days=-2)] = "Good Friday" self[easter_date] = "Easter Sunday" - self[easter_date + rd(days=+49)] = "Feast of Pentecost" + self[easter_date + td(days=+49)] = "Feast of Pentecost" self[date(year, DEC, 25)] = "Christmas Day" diff --git a/holidays/countries/indonesia.py b/holidays/countries/indonesia.py index 4eefa7438..13f66df0b 100644 --- a/holidays/countries/indonesia.py +++ b/holidays/countries/indonesia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP from holidays.constants import OCT, NOV, DEC @@ -105,14 +105,14 @@ def _populate(self, year): hol_date = date(year, *date_obs) self[hol_date] = "Hari Raya Idul Fitri" self[ - hol_date + rd(days=+1) + hol_date + td(days=+1) ] = "Hari kedua dari Hari Raya Idul Fitri" else: for date_obs in _islamic_to_gre(year, 10, 1): hol_date = date_obs self[hol_date] = "Hari Raya Idul Fitri* (*estimated)" self[ - hol_date + rd(days=+1) + hol_date + td(days=+1) ] = "Hari kedua dari Hari Raya Idul Fitri* (*estimated)" # Eid al-Adha @@ -248,7 +248,7 @@ def _populate(self, year): self[hol_date] = "Isra' Mi'raj Nabi Muhammad* (*estimated)" # Good Friday - self[easter(year) + rd(days=-2)] = "Wafat Yesus Kristus" + self[easter(year) + td(days=-2)] = "Wafat Yesus Kristus" # Buddha's Birthday if year >= 1983: @@ -283,7 +283,7 @@ def _populate(self, year): self[date(year, MAY, 1)] = "Hari Buruh Internasional" # Ascension Day - self[easter(year) + rd(days=+39)] = "Kenaikan Yesus Kristus" + self[easter(year) + td(days=+39)] = "Kenaikan Yesus Kristus" # Pancasila Day if year >= 2017: diff --git a/holidays/countries/ireland.py b/holidays/countries/ireland.py index 257855acc..18bee6b37 100644 --- a/holidays/countries/ireland.py +++ b/holidays/countries/ireland.py @@ -8,13 +8,15 @@ # 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 dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAR, MAY, JUN, AUG, OCT, DEC, FRI +from holidays.constants import JAN, FEB, MAR, MAY, JUN, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -40,7 +42,7 @@ def _populate(self, year): name = "St. Brigid's Day" dt = date(year, FEB, 1) self[dt] = name - if self.observed and dt.weekday() != FRI: + if self.observed and not self._is_friday(dt): self[dt + rd(weekday=MO)] = name + " (Observed)" # St. Patrick's Day @@ -51,7 +53,7 @@ def _populate(self, year): self[dt + rd(weekday=MO)] = name + " (Observed)" # Easter Monday - self[easter(year) + rd(days=+1)] = "Easter Monday" + self[easter(year) + td(days=+1)] = "Easter Monday" # May bank holiday (first Monday in May) if year >= 1978: @@ -83,7 +85,7 @@ def _populate(self, year): dt = date(year, DEC, 26) self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" + self[dt + td(days=+2)] = name + " (Observed)" class IE(Ireland): diff --git a/holidays/countries/israel.py b/holidays/countries/israel.py index 3596d2a38..6fa89bd31 100644 --- a/holidays/countries/israel.py +++ b/holidays/countries/israel.py @@ -11,18 +11,16 @@ from datetime import date +from datetime import timedelta as td from convertdate import gregorian, hebrew from convertdate.holidays import hanukkah, lag_baomer, passover, purim from convertdate.holidays import rosh_hashanah, shavuot, sukkot, yom_kippur -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import WED, THU, SAT from holidays.holiday_base import HolidayBase class Israel(HolidayBase): - country = "IL" def _populate(self, year): @@ -32,15 +30,15 @@ def _populate(self, year): name = "Passover I" passover_start_dt = date(*passover(year, eve=True)) self[passover_start_dt] = name + " - Eve" - self[passover_start_dt + rd(days=+1)] = name + self[passover_start_dt + td(days=+1)] = name name = "Passover" for offset in range(2, 6): - self[passover_start_dt + rd(days=offset)] = name + " - Chol HaMoed" + self[passover_start_dt + td(days=offset)] = name + " - Chol HaMoed" name = "Passover VII" - self[passover_start_dt + rd(days=+6)] = name + " - Eve" - self[passover_start_dt + rd(days=+7)] = name + self[passover_start_dt + td(days=+6)] = name + " - Eve" + self[passover_start_dt + td(days=+7)] = name # Memorial Day name = "Memorial Day" @@ -49,27 +47,29 @@ def _populate(self, year): hebrew.to_jd_gregorianyear(year, hebrew.IYYAR, 3) ) ) - self[memorial_day_dt + rd(days=+1)] = name + self[memorial_day_dt + td(days=+1)] = name observed_delta = 0 if self.observed: day_in_week = memorial_day_dt.weekday() - if day_in_week in {WED, THU}: + if self._is_wednesday(memorial_day_dt) or self._is_thursday( + memorial_day_dt + ): observed_delta = -(day_in_week - 1) - elif 2004 <= year and day_in_week == SAT: + elif 2004 <= year and self._is_saturday(memorial_day_dt): observed_delta = 1 if observed_delta != 0: - self[memorial_day_dt + rd(days=observed_delta + 1)] = ( + self[memorial_day_dt + td(days=observed_delta + 1)] = ( name + " (Observed)" ) # Independence Day name = "Independence Day" - self[memorial_day_dt + rd(days=+2)] = name + self[memorial_day_dt + td(days=+2)] = name if self.observed and observed_delta != 0: - self[memorial_day_dt + rd(days=observed_delta + 2)] = ( + self[memorial_day_dt + td(days=observed_delta + 2)] = ( name + " (Observed)" ) @@ -82,46 +82,46 @@ def _populate(self, year): name = "Shavuot" shavuot_dt = date(*shavuot(year, eve=True)) self[shavuot_dt] = name + " - Eve" - self[shavuot_dt + rd(days=+1)] = name + self[shavuot_dt + td(days=+1)] = name # Rosh Hashana name = "Rosh Hashanah" rosh_hashanah_dt = date(*rosh_hashanah(year, eve=True)) self[rosh_hashanah_dt] = name + " - Eve" - self[rosh_hashanah_dt + rd(days=+1)] = name - self[rosh_hashanah_dt + rd(days=+2)] = name + self[rosh_hashanah_dt + td(days=+1)] = name + self[rosh_hashanah_dt + td(days=+2)] = name # Yom Kippur name = "Yom Kippur" yom_kippur_dt = date(*yom_kippur(year, eve=True)) self[yom_kippur_dt] = name + " - Eve" - self[yom_kippur_dt + rd(days=+1)] = name + self[yom_kippur_dt + td(days=+1)] = name # Sukkot name = "Sukkot I" sukkot_start_dt = date(*sukkot(year, eve=True)) self[sukkot_start_dt] = name + " - Eve" - self[sukkot_start_dt + rd(days=+1)] = name + self[sukkot_start_dt + td(days=+1)] = name name = "Sukkot" for offset in range(2, 7): - self[sukkot_start_dt + rd(days=offset)] = name + " - Chol HaMoed" + self[sukkot_start_dt + td(days=offset)] = name + " - Chol HaMoed" name = "Sukkot VII" - self[sukkot_start_dt + rd(days=+7)] = name + " - Eve" - self[sukkot_start_dt + rd(days=+8)] = name + self[sukkot_start_dt + td(days=+7)] = name + " - Eve" + self[sukkot_start_dt + td(days=+8)] = name # Hanukkah name = "Hanukkah" hk_start_date = date(*hanukkah(year, eve=False)) for offset in range(8): - hk_date = hk_start_date + rd(days=offset) + hk_date = hk_start_date + td(days=offset) if hk_date.year == year: self[hk_date] = name # Some o prior's year Hannukah may fall in current year. hk_start_date = date(*hanukkah(year - 1, eve=False)) for offset in range(8): - hk_date = hk_start_date + rd(days=offset) + hk_date = hk_start_date + td(days=offset) if hk_date.year == year: self[hk_date] = name @@ -129,8 +129,8 @@ def _populate(self, year): name = "Purim" purim_date = date(*purim(year, eve=True)) self[purim_date] = name + " - Eve" - self[purim_date + rd(days=+1)] = name - self[purim_date + rd(days=+2)] = "Shushan Purim" + self[purim_date + td(days=+1)] = name + self[purim_date + td(days=+2)] = "Shushan Purim" class IL(Israel): diff --git a/holidays/countries/italy.py b/holidays/countries/italy.py index 5b01f45e3..f10269331 100644 --- a/holidays/countries/italy.py +++ b/holidays/countries/italy.py @@ -11,6 +11,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import relativedelta as rd @@ -22,7 +23,6 @@ class Italy(HolidayBase): - country = "IT" # Reference: https://it.wikipedia.org/wiki/Province_d%27Italia # Please maintain in alphabetical order for easy updating in the future @@ -158,7 +158,7 @@ def _populate(self, year): self[date(year, JAN, 6)] = "Epifania del Signore" easter_date = easter(year) self[easter_date] = "Pasqua di Resurrezione" - self[easter_date + rd(days=+1)] = "Lunedì dell'Angelo" + self[easter_date + td(days=+1)] = "Lunedì dell'Angelo" if year >= 1946: self[date(year, APR, 25)] = "Festa della Liberazione" self[date(year, MAY, 1)] = "Festa dei Lavoratori" @@ -223,7 +223,7 @@ def _populate(self, year): if self.subdiv in {"BT", "Trani"}: self[date(year, MAY, 3)] = "San Nicola Pellegrino" elif self.subdiv == "BZ": - self[easter_date + rd(days=+50)] = "Lunedì di Pentecoste" + self[easter_date + td(days=+50)] = "Lunedì di Pentecoste" self[date(year, AUG, 15)] = "Maria Santissima Assunta" elif self.subdiv == "CA": self[date(year, OCT, 30)] = "San Saturnino di Cagliari" diff --git a/holidays/countries/jamaica.py b/holidays/countries/jamaica.py index 8f91caa76..914ea073b 100644 --- a/holidays/countries/jamaica.py +++ b/holidays/countries/jamaica.py @@ -10,92 +10,73 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import MO, SU +from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAY, JUN, AUG, OCT, DEC, SUN +from holidays.constants import JAN, MAY, AUG, OCT, DEC from holidays.holiday_base import HolidayBase class Jamaica(HolidayBase): """ https://en.wikipedia.org/wiki/Public_holidays_in_Jamaica + https://www.mlss.gov.jm/wp-content/uploads/2017/11/The-Holidays-Public-General-Act.pdf """ country = "JM" def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + super()._populate(year) # New Year's Day - name = "New Year's Day" - _date = date(year, JAN, 1) - if self.observed and _date.weekday() == SUN: - self[_date + rd(weekday=MO(+1))] = name + " (Observed)" - else: - self[_date] = name - - # Valentine's Day - self[date(year, FEB, 14)] = "Valentine's Day" - - # Mother's Day - self[date(year, MAY, 1) + rd(weekday=SU(+2))] = "Mother's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") # Labour Day - name = "Labour Day" - _date = date(year, MAY, 23) - if self.observed and _date.weekday() == SUN: - self[_date + rd(weekday=MO)] = name + " (Observed)" - else: - self[_date] = name - - # Father's Day - self[date(year, JUN, 1) + rd(weekday=SU(+3))] = "Father's Day" + dt = date(year, MAY, 23) + name = "National Labour Day" + self[dt] = name + if self.observed and self._is_weekend(dt): + self[dt + rd(weekday=MO)] = f"{name} (Observed)" # Emancipation Day - name = "Emancipation Day" - _date = date(year, AUG, 1) - if self.observed and _date.weekday() == SUN: - self[_date + rd(weekday=MO)] = name + " (Observed)" - else: - self[_date] = name + if year >= 1998: + _add_with_observed(date(year, AUG, 1), "Emancipation Day") # Independence Day - name = "Independence Day" - _date = date(year, AUG, 6) - if self.observed and self._is_weekend(_date): - self[_date + rd(weekday=MO)] = name - else: - self[_date] = name + _add_with_observed(date(year, AUG, 6), "Independence Day") # National Heroes Day self[date(year, OCT, 1) + rd(weekday=MO(+3))] = "National Heroes Day" - # Christmas - self[date(year, DEC, 25)] = "Christmas day" - - # Boxing day - self[date(year, DEC, 26)] = "Boxing day" + # Christmas Day + dt = date(year, DEC, 25) + name = "Christmas Day" + self[dt] = name + if self.observed and self._is_sunday(dt): + self[dt + td(days=+2)] = f"{name} (Observed)" - # New Year Eve - # self[date(year, DEC, 31)] = "New Year Eve" + # Boxing Day + _add_with_observed(date(year, DEC, 26), "Boxing Day") # Holidays based on Easter easter_date = easter(year) # Ash Wednesday - self[easter_date + rd(days=-46)] = "Ash Wednesday" + self[easter_date + td(days=-46)] = "Ash Wednesday" # Good Friday - self[easter_date + rd(days=-2)] = "Good Friday" - - # Easter - self[easter_date] = "Easter" + self[easter_date + td(days=-2)] = "Good Friday" - # Easter - self[easter_date + rd(days=+1)] = "Easter Monday" + # Easter Monday + self[easter_date + td(days=+1)] = "Easter Monday" class JM(Jamaica): diff --git a/holidays/countries/japan.py b/holidays/countries/japan.py index 5faa325f9..589003638 100644 --- a/holidays/countries/japan.py +++ b/holidays/countries/japan.py @@ -10,6 +10,8 @@ # License: MIT (see LICENSE file) from datetime import date, datetime +from datetime import timedelta as td +from gettext import gettext as tr from dateutil import tz from dateutil.relativedelta import MO @@ -17,8 +19,8 @@ from pymeeus.Epoch import Epoch from pymeeus.Sun import Sun -from holidays.constants import SUN, JAN, FEB, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC +from holidays.constants import JAN, FEB, APR, MAY, JUN, JUL, AUG, SEP, OCT +from holidays.constants import NOV, DEC from holidays.holiday_base import HolidayBase @@ -28,14 +30,15 @@ class Japan(HolidayBase): """ country = "JP" + default_language = "ja" special_holidays = { - 1959: ((APR, 10, "結婚の儀"),), # The Crown Prince marriage ceremony. - 1989: ((FEB, 24, "大喪の礼"),), # State Funeral of Emperor Shōwa. - 1990: ((NOV, 12, "即位礼正殿の儀"),), # Enthronement ceremony. - 1993: ((JUN, 9, "結婚の儀"),), # The Crown Prince marriage ceremony. + 1959: ((APR, 10, tr("結婚の儀")),), # The Crown Prince marriage ceremony. + 1989: ((FEB, 24, tr("大喪の礼")),), # State Funeral of Emperor Shōwa. + 1990: ((NOV, 12, tr("即位礼正殿の儀")),), # Enthronement ceremony. + 1993: ((JUN, 9, tr("結婚の儀")),), # The Crown Prince marriage ceremony. 2019: ( - (MAY, 1, "天皇の即位の日"), # Enthronement day. - (OCT, 22, "即位礼正殿の儀が行われる日"), # Enthronement ceremony. + (MAY, 1, tr("天皇の即位の日")), # Enthronement day. + (OCT, 22, tr("即位礼正殿の儀が行われる日")), # Enthronement ceremony. ), } @@ -45,121 +48,122 @@ def _populate(self, year): super()._populate(year) - # New Year's Day - self[date(year, JAN, 1)] = "元日" + # New Year's Day. + self[date(year, JAN, 1)] = self.tr("元日") - # Coming of Age Day - if year <= 1999: - self[date(year, JAN, 15)] = "成人の日" - else: - self[date(year, JAN, 1) + rd(weekday=MO(+2))] = "成人の日" + # Coming of Age Day. + self[ + date(year, JAN, 15) + if year <= 1999 + else date(year, JAN, 1) + rd(weekday=MO(+2)) + # Coming of Age Day. + ] = self.tr("成人の日") - # Foundation Day + # Foundation Day. if year >= 1967: - self[date(year, FEB, 11)] = "建国記念の日" + self[date(year, FEB, 11)] = self.tr("建国記念の日") - # Reiwa Emperor's Birthday + # Reiwa Emperor's Birthday. if year >= 2020: - self[date(year, FEB, 23)] = "天皇誕生日" + self[date(year, FEB, 23)] = self.tr("天皇誕生日") - # Vernal Equinox Day + # Vernal Equinox Day. epoch = Sun.get_equinox_solstice(year, target="spring") equinox = map(int, Epoch(epoch).get_full_date()) adjusted_date = datetime(*equinox, tzinfo=tz.UTC).astimezone( tz.gettz("Asia/Tokyo") ) - self[adjusted_date.date()] = "春分の日" + self[adjusted_date.date()] = self.tr("春分の日") - # Showa Emperor's Birthday, Greenery Day or Showa Day + # Showa Emperor's Birthday, Greenery Day or Showa Day. if year <= 1988: - self[date(year, APR, 29)] = "天皇誕生日" + self[date(year, APR, 29)] = self.tr("天皇誕生日") elif year <= 2006: - self[date(year, APR, 29)] = "みどりの日" + self[date(year, APR, 29)] = self.tr("みどりの日") else: - self[date(year, APR, 29)] = "昭和の日" + self[date(year, APR, 29)] = self.tr("昭和の日") - # Constitution Memorial Day - self[date(year, MAY, 3)] = "憲法記念日" + # Constitution Memorial Day. + self[date(year, MAY, 3)] = self.tr("憲法記念日") - # Greenery Day + # Greenery Day. if year >= 2007: - self[date(year, MAY, 4)] = "みどりの日" + self[date(year, MAY, 4)] = self.tr("みどりの日") - # Children's Day - self[date(year, MAY, 5)] = "こどもの日" + # Children's Day. + self[date(year, MAY, 5)] = self.tr("こどもの日") - # Marine Day + # Marine Day. if 1996 <= year <= 2002: - self[date(year, JUL, 20)] = "海の日" + self[date(year, JUL, 20)] = self.tr("海の日") elif year == 2020: - self[date(year, JUL, 23)] = "海の日" + self[date(year, JUL, 23)] = self.tr("海の日") elif year == 2021: - self[date(year, JUL, 22)] = "海の日" + self[date(year, JUL, 22)] = self.tr("海の日") elif year >= 2003: - self[date(year, JUL, 1) + rd(weekday=MO(+3))] = "海の日" + self[date(year, JUL, 1) + rd(weekday=MO(+3))] = self.tr("海の日") - # Mountain Day + # Mountain Day. if year == 2020: - self[date(year, AUG, 10)] = "山の日" + self[date(year, AUG, 10)] = self.tr("山の日") elif year == 2021: - self[date(year, AUG, 8)] = "山の日" + self[date(year, AUG, 8)] = self.tr("山の日") elif year >= 2016: - self[date(year, AUG, 11)] = "山の日" + self[date(year, AUG, 11)] = self.tr("山の日") - # Respect for the Aged Day + # Respect for the Aged Day. if 1966 <= year <= 2002: - self[date(year, SEP, 15)] = "敬老の日" + self[date(year, SEP, 15)] = self.tr("敬老の日") elif year >= 2003: - self[date(year, SEP, 1) + rd(weekday=MO(+3))] = "敬老の日" + self[date(year, SEP, 1) + rd(weekday=MO(+3))] = self.tr("敬老の日") - # Autumnal Equinox Day + # Autumnal Equinox Day. epoch = Sun.get_equinox_solstice(year, target="autumn") equinox = map(int, Epoch(epoch).get_full_date()) adjusted_date = datetime(*equinox, tzinfo=tz.UTC).astimezone( tz.gettz("Asia/Tokyo") ) - self[adjusted_date.date()] = "秋分の日" + self[adjusted_date.date()] = self.tr("秋分の日") - # Health and Sports Day + # Health and Sports Day. if 1966 <= year <= 1999: - self[date(year, OCT, 10)] = "体育の日" + self[date(year, OCT, 10)] = self.tr("体育の日") elif 2000 <= year <= 2019: - self[date(year, OCT, 1) + rd(weekday=MO(+2))] = "体育の日" + self[date(year, OCT, 1) + rd(weekday=MO(+2))] = self.tr("体育の日") elif year == 2020: - self[date(year, JUL, 24)] = "スポーツの日" + self[date(year, JUL, 24)] = self.tr("スポーツの日") elif year == 2021: - self[date(year, JUL, 23)] = "スポーツの日" + self[date(year, JUL, 23)] = self.tr("スポーツの日") elif 2022 <= year: - self[date(year, OCT, 1) + rd(weekday=MO(+2))] = "スポーツの日" + self[date(year, OCT, 1) + rd(weekday=MO(+2))] = self.tr("スポーツの日") - # Culture Day - self[date(year, NOV, 3)] = "文化の日" + # Culture Day. + self[date(year, NOV, 3)] = self.tr("文化の日") - # Labour Thanksgiving Day - self[date(year, NOV, 23)] = "勤労感謝の日" + # Labour Thanksgiving Day. + self[date(year, NOV, 23)] = self.tr("勤労感謝の日") - # Regarding the Emperor of Heisei + # Regarding the Emperor of Heisei. if 1989 <= year <= 2018: - # Heisei Emperor's Birthday - self[date(year, DEC, 23)] = "天皇誕生日" + self[date(year, DEC, 23)] = self.tr("天皇誕生日") if self.observed: # When a national holiday falls on Sunday, next working day - # shall become a public holiday (振替休日) - substitute holidays + # shall become a public holiday (振替休日) - substitute holidays. for dt in list(self.keys()): - if dt.year == year and dt.weekday() == SUN: - hol_date = dt + rd(days=+1) + if dt.year == year and self._is_sunday(dt): + hol_date = dt + td(days=+1) while hol_date in self: - hol_date += rd(days=+1) - self[hol_date] = "振替休日" + hol_date += td(days=+1) + self[hol_date] = self.tr("振替休日") # A weekday between national holidays becomes - # a holiday too (国民の休日) - citizens' holidays + # a holiday too (国民の休日) - citizens' holidays. for dt in list(self.keys()): - if dt.year == year and dt + rd(days=+2) in self: - hol_date = dt + rd(days=+1) - if hol_date.weekday() != SUN and hol_date not in self: - self[hol_date] = "国民の休日" + if dt.year == year and dt + td(days=+2) in self: + hol_date = dt + td(days=+1) + if not self._is_sunday(hol_date) and hol_date not in self: + self[hol_date] = self.tr("国民の休日") class JP(Japan): diff --git a/holidays/countries/kazakhstan.py b/holidays/countries/kazakhstan.py index d31cc220a..43f12ee2b 100644 --- a/holidays/countries/kazakhstan.py +++ b/holidays/countries/kazakhstan.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, MAR, MAY, JUL, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -29,78 +28,99 @@ class Kazakhstan(HolidayBase): country = "KZ" def _populate(self, year): + def _add_with_observed( + hol_date: date, + hol_name: str, + sat_days: int = +2, + sun_days: int = +1, + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_weekend(hol_date) and year >= 2002: + self[ + hol_date + + td( + days=sat_days + if self._is_saturday(hol_date) + else sun_days + ) + ] = f"{hol_name} (Observed)" + + # Kazakhstan declared its sovereignty on 25 October 1990 + if year <= 1990: + return None + super()._populate(year) # New Year's holiday (2 days) name = "New Year" - self[date(year, JAN, 1)] = name - self[date(year, JAN, 2)] = name + _add_with_observed(date(year, JAN, 1), name, sun_days=+2) + _add_with_observed(date(year, JAN, 2), name, sun_days=+2) + + # Orthodox Christmas (nonworking day, without extending) + if year >= 2006: + self[date(year, JAN, 7)] = "Orthodox Christmas" # International Women's Day - self[date(year, MAR, 8)] = "International Women's Day" + _add_with_observed(date(year, MAR, 8), "International Women's Day") # Nauryz holiday name = "Nauryz holiday" if year >= 2010: - self[date(year, MAR, 21)] = name - self[date(year, MAR, 22)] = name - self[date(year, MAR, 23)] = name + _add_with_observed( + date(year, MAR, 21), name, sat_days=+3, sun_days=+3 + ) + _add_with_observed(date(year, MAR, 22), name, sun_days=+3) + _add_with_observed(date(year, MAR, 23), name, sun_days=+2) elif year >= 2002: - self[date(year, MAR, 22)] = name + _add_with_observed(date(year, MAR, 22), name) # Kazakhstan People Solidarity Holiday - self[date(year, MAY, 1)] = "Kazakhstan People Solidarity Holiday" + _add_with_observed( + date(year, MAY, 1), "Kazakhstan People Solidarity Holiday" + ) # Defender of the Fatherland Day if year >= 2013: - self[date(year, MAY, 7)] = "Defender of the Fatherland Day" + _add_with_observed( + date(year, MAY, 7), + "Defender of the Fatherland Day", + sat_days=+3, + ) # Victory Day - self[date(year, MAY, 9)] = "Victory Day" + _add_with_observed(date(year, MAY, 9), "Victory Day") # Capital Day if year >= 2009: - self[date(year, JUL, 6)] = "Capital Day" + _add_with_observed(date(year, JUL, 6), "Capital Day") # Constitution Day of the Republic of Kazakhstan if year >= 1996: - self[ - date(year, AUG, 30) - ] = "Constitution Day of the Republic of Kazakhstan" + _add_with_observed( + date(year, AUG, 30), + "Constitution Day of the Republic of Kazakhstan", + ) # Republic Day if 1994 <= year <= 2008 or year >= 2022: - self[date(year, OCT, 25)] = "Republic Day" + _add_with_observed(date(year, OCT, 25), "Republic Day") # First President Day if 2012 <= year <= 2021: - self[date(year, DEC, 1)] = "First President Day" + _add_with_observed(date(year, DEC, 1), "First President Day") # Kazakhstan Independence Day name = "Kazakhstan Independence Day" - self[date(year, DEC, 16)] = name if 2002 <= year <= 2021: - self[date(year, DEC, 17)] = name - - if self.observed and year >= 2002: - for k, v in list(self.items()): - if self._is_weekend(k) and k.year == year: - next_workday = k + rd(days=+1) - while self._is_weekend(next_workday) or self.get( - next_workday - ): - next_workday += rd(days=+1) - self[next_workday] = v + " (Observed)" - - # Nonworking days (without extending) - # Orthodox Christmas - if year >= 2006: - self[date(year, JAN, 7)] = "Orthodox Christmas" + _add_with_observed(date(year, DEC, 16), name, sun_days=+2) + _add_with_observed(date(year, DEC, 17), name, sun_days=+2) + else: + _add_with_observed(date(year, DEC, 16), name) - # Kurban Ait + # Kurban Ait (nonworking day, without extending) if year >= 2006: - for hol_date in _islamic_to_gre(year, 12, 10): - self[hol_date] = "Kurban Ait" + for dt in _islamic_to_gre(year, 12, 10): + self[dt] = "Kurban Ait" class KZ(Kazakhstan): diff --git a/holidays/countries/kenya.py b/holidays/countries/kenya.py index 762a512be..9ba62ec6f 100644 --- a/holidays/countries/kenya.py +++ b/holidays/countries/kenya.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAY, JUN, OCT, DEC, SUN +from holidays.constants import JAN, FEB, APR, MAY, JUN, AUG, SEP, OCT, DEC from holidays.holiday_base import HolidayBase @@ -26,28 +26,57 @@ class Kenya(HolidayBase): """ country = "KE" + special_holidays = { + 2020: ((FEB, 11, "President Moi Celebration of Life Day"),), + 2022: ( + (APR, 29, "State Funeral for Former President Mwai Kibaki"), + (AUG, 9, "Election Day"), + (SEP, 10, "Day of Mourning for Queen Elizabeth II"), + (SEP, 11, "Day of Mourning for Queen Elizabeth II"), + (SEP, 12, "Day of Mourning for Queen Elizabeth II"), + (SEP, 13, "Inauguration Day"), + ), + } def _populate(self, year): + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=days)] = f"{hol_name} (Observed)" + + if year <= 1962: + return None + super()._populate(year) # Public holidays - self[date(year, JAN, 1)] = "New Year's Day" - self[date(year, MAY, 1)] = "Labour Day" - self[date(year, JUN, 1)] = "Madaraka Day" - self[date(year, OCT, 10)] = "Huduma Day" - self[date(year, OCT, 20)] = "Mashujaa Day" - self[date(year, DEC, 12)] = "Jamhuri (Independence) Day" - self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Utamaduni Day" - - if self.observed: - for k, v in list(self.items()): - if k.weekday() == SUN and k.year == year: - self[k + rd(days=+1)] = v + " (Observed)" + _add_with_observed(date(year, JAN, 1), "New Year's Day") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" + + _add_with_observed(date(year, MAY, 1), "Labour Day") + + if year >= 2010: + _add_with_observed(date(year, JUN, 1), "Madaraka Day") + + if 2002 <= year <= 2009 or year >= 2018: + _add_with_observed( + date(year, OCT, 10), + "Utamaduni Day" if year >= 2021 else "Moi Day", + ) + + _add_with_observed( + date(year, OCT, 20), + "Mashujaa Day" if year >= 2010 else "Kenyatta Day", + ) + + _add_with_observed(date(year, DEC, 12), "Jamhuri Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day", days=+2) + _add_with_observed(date(year, DEC, 26), "Boxing Day") class KE(Kenya): diff --git a/holidays/countries/kyrgyzstan.py b/holidays/countries/kyrgyzstan.py index 33dd4829d..bca66c31c 100644 --- a/holidays/countries/kyrgyzstan.py +++ b/holidays/countries/kyrgyzstan.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, FEB, MAR, APR, MAY, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -75,7 +74,7 @@ def _populate(self, year): name = "Orozo Ait" for dt in _islamic_to_gre(year, 10, 1): self[dt] = name - self[dt + rd(days=+1)] = name + self[dt + td(days=+1)] = name # Kurman Ait. for dt in _islamic_to_gre(year, 12, 10): diff --git a/holidays/countries/latvia.py b/holidays/countries/latvia.py index dbe73b206..0ba71277d 100644 --- a/holidays/countries/latvia.py +++ b/holidays/countries/latvia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.holiday_base import HolidayBase @@ -33,13 +33,13 @@ def _populate(self, year): # Good Friday easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Lielā Piektdiena" + self[easter_date + td(days=-2)] = "Lielā Piektdiena" # Easter self[easter_date] = "Lieldienas" # Easter 2nd day - self[easter_date + rd(days=+1)] = "Otrās Lieldienas" + self[easter_date + td(days=+1)] = "Otrās Lieldienas" # International Workers' Day self[date(year, 5, 1)] = "Darba svētki" diff --git a/holidays/countries/lesotho.py b/holidays/countries/lesotho.py index a229c4302..335f53141 100644 --- a/holidays/countries/lesotho.py +++ b/holidays/countries/lesotho.py @@ -8,10 +8,11 @@ # 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 dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, JUL, OCT, DEC from holidays.holiday_base import HolidayBase @@ -44,9 +45,9 @@ def _populate(self, year): self[date(year, MAY, 25)] = "Africa/Heroes Day" easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" - self[easter_date + rd(days=+39)] = "Ascension Day" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" + self[easter_date + td(days=+39)] = "Ascension Day" self[date(year, MAY, 1)] = "Workers' Day" if year > 1997: diff --git a/holidays/countries/liechtenstein.py b/holidays/countries/liechtenstein.py index 18cb4bb1a..27e08e8e8 100644 --- a/holidays/countries/liechtenstein.py +++ b/holidays/countries/liechtenstein.py @@ -11,9 +11,9 @@ # Copyright: Kateryna Golovanova , 2022 from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import AUG, DEC, FEB, JAN, MAR, MAY, NOV, SEP from holidays.holiday_base import HolidayBase @@ -43,34 +43,34 @@ def _populate(self, year): easter_date = easter(year) # Shrove Tuesday. - self[easter_date + rd(days=-47)] = "Fasnachtsdienstag" + self[easter_date + td(days=-47)] = "Fasnachtsdienstag" # Saint Joseph's Day. self[date(year, MAR, 19)] = "Josefstag" # Good Friday. - self[easter_date + rd(days=-2)] = "Karfreitag" + self[easter_date + td(days=-2)] = "Karfreitag" # Easter. self[easter_date] = "Ostersonntag" # Easter Monday. - self[easter_date + rd(days=+1)] = "Ostermontag" + self[easter_date + td(days=+1)] = "Ostermontag" # Labor Day. self[date(year, MAY, 1)] = "Tag der Arbeit" # Ascension Day. - self[easter_date + rd(days=+39)] = "Auffahrt" + self[easter_date + td(days=+39)] = "Auffahrt" # Pentecost. - self[easter_date + rd(days=+49)] = "Pfingstsonntag" + self[easter_date + td(days=+49)] = "Pfingstsonntag" # Whit Monday. - self[easter_date + rd(days=+50)] = "Pfingstmontag" + self[easter_date + td(days=+50)] = "Pfingstmontag" # Corpus Christi. - self[easter_date + rd(days=+60)] = "Fronleichnam" + self[easter_date + td(days=+60)] = "Fronleichnam" # National Day. self[date(year, AUG, 15)] = "Staatsfeiertag" diff --git a/holidays/countries/lithuania.py b/holidays/countries/lithuania.py index 1a1847990..697c56d08 100644 --- a/holidays/countries/lithuania.py +++ b/holidays/countries/lithuania.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import SU @@ -48,7 +49,7 @@ def _populate(self, year): self[easter_date] = "Velykos" # Easter 2nd day - self[easter_date + rd(days=+1)] = "Velykų antroji diena" + self[easter_date + td(days=+1)] = "Velykų antroji diena" # International Workers' Day self[date(year, 5, 1)] = "Tarptautinė darbo diena" diff --git a/holidays/countries/luxembourg.py b/holidays/countries/luxembourg.py index bbe46f332..b4fba8473 100644 --- a/holidays/countries/luxembourg.py +++ b/holidays/countries/luxembourg.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUN, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -31,13 +31,13 @@ def _populate(self, year): # Public holidays self[date(year, JAN, 1)] = "Neijoerschdag" easter_date = easter(year) - self[easter_date + rd(days=+1)] = "Ouschterméindeg" + self[easter_date + td(days=+1)] = "Ouschterméindeg" self[date(year, MAY, 1)] = "Dag vun der Aarbecht" if year >= 2019: # Europe Day: not in legislation yet, but introduced starting 2019 self[date(year, MAY, 9)] = "Europadag" - self[easter_date + rd(days=+39)] = "Christi Himmelfaart" - self[easter_date + rd(days=+50)] = "Péngschtméindeg" + self[easter_date + td(days=+39)] = "Christi Himmelfaart" + self[easter_date + td(days=+50)] = "Péngschtméindeg" self[date(year, JUN, 23)] = "Nationalfeierdag" self[date(year, AUG, 15)] = "Léiffrawëschdag" self[date(year, NOV, 1)] = "Allerhellgen" diff --git a/holidays/countries/madagascar.py b/holidays/countries/madagascar.py index cb1afa11f..ca72631e8 100644 --- a/holidays/countries/madagascar.py +++ b/holidays/countries/madagascar.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import SU @@ -30,7 +31,8 @@ class Madagascar(HolidayBase): def _populate(self, year): # Observed since 1947 if year <= 1946: - return + return None + super()._populate(year) self[date(year, JAN, 1)] = "Taom-baovao / New Year's Day" @@ -57,21 +59,21 @@ def _populate(self, year): easter_date = easter(year) self[easter_date] = "Fetin'ny paska / Easter Sunday" - self[easter_date + rd(days=+1)] = "Alatsinain'ny paska / Easter Monday" + self[easter_date + td(days=+1)] = "Alatsinain'ny paska / Easter Monday" self[ - easter_date + rd(days=+39) + easter_date + td(days=+39) ] = "Fiakaran'ny Jesosy kristy tany an-danitra / Ascension Day" - whit_sunday = easter_date + rd(days=+49) + whit_sunday = easter_date + td(days=+49) self[whit_sunday] = "Pentekosta / Whit Sunday" self[ - easter_date + rd(days=+50) + easter_date + td(days=+50) ] = "Alatsinain'ny pentekosta / Whit Monday" dt = date(year, MAY, 31) + rd(weekday=SU(-1)) if dt == whit_sunday: - dt += rd(days=+7) + dt += td(days=+7) self[dt] = "Fetin'ny Reny / Mother's Day" diff --git a/holidays/countries/malawi.py b/holidays/countries/malawi.py index ef0422de6..d2e0dba18 100644 --- a/holidays/countries/malawi.py +++ b/holidays/countries/malawi.py @@ -10,10 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from dateutil.relativedelta import MO from holidays.constants import JAN, MAR, MAY, JUL, OCT, DEC from holidays.holiday_base import HolidayBase @@ -28,30 +27,36 @@ class Malawi(HolidayBase): country = "MW" def _populate(self, year): + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_weekend(hol_date): + obs_date = hol_date + td( + days=+2 if self._is_saturday(hol_date) else days + ) + self[obs_date] = f"{hol_name} (Observed)" + # Observed since 2000 if year <= 1999: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") + _add_with_observed(date(year, JAN, 15), "John Chilembwe Day") + _add_with_observed(date(year, MAR, 3), "Martyrs Day") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" - - self[date(year, JAN, 15)] = "John Chilembwe Day" - self[date(year, MAR, 3)] = "Martyrs Day" - self[date(year, MAY, 1)] = "Labour Day" - self[date(year, MAY, 14)] = "Kamuzu Day" - self[date(year, JUL, 6)] = "Independence Day" - self[date(year, OCT, 15)] = "Mother's Day" - self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Boxing Day" - - if self.observed: - for k, v in list(self.items()): - if self._is_weekend(k) and k.year == year: - self[k + rd(weekday=MO)] = v + " (Observed)" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" + + _add_with_observed(date(year, MAY, 1), "Labour Day") + _add_with_observed(date(year, MAY, 14), "Kamuzu Day") + _add_with_observed(date(year, JUL, 6), "Independence Day") + _add_with_observed(date(year, OCT, 15), "Mother's Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day", days=+2) + _add_with_observed(date(year, DEC, 26), "Boxing Day", days=+2) class MW(Malawi): diff --git a/holidays/countries/malaysia.py b/holidays/countries/malaysia.py index 1eaf4408e..73b370c30 100644 --- a/holidays/countries/malaysia.py +++ b/holidays/countries/malaysia.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from typing import Iterable, Optional, Union from dateutil.easter import easter @@ -17,7 +18,7 @@ from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC, FRI, SAT, SUN +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _ChineseLuniSolar, _islamic_to_gre @@ -59,6 +60,7 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: """ An subclass of :py:class:`HolidayBase` representing public holidays in @@ -100,7 +102,9 @@ def __init__( See parameters and usage in :py:class:`HolidayBase`. """ self.cnls = _ChineseLuniSolar() - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) def _populate(self, year): def _add_holiday(dt: date, hol: str) -> None: @@ -118,7 +122,7 @@ def _add_holiday(dt: date, hol: str) -> None: # The second day of Chinese New Year is not a federal holiday in # Kelantan and Terengganu. However, it is gazetted as a state holiday # in both states, effectively making it a nationwide holiday. - self[hol_date + rd(days=+1)] = "Chinese New Year Holiday" + self[hol_date + td(days=+1)] = "Chinese New Year Holiday" # Wesak Day. # Date of observance is announced yearly @@ -297,7 +301,8 @@ def _add_holiday(dt: date, hol: str) -> None: for hol_date, hol_suffix in hol_dates: _add_holiday(hol_date, f"{name}{hol_suffix}") _add_holiday( - hol_date + rd(days=+1), f"Second day of {name}{hol_suffix}" + hol_date + td(days=+1), + f"Second day of {name}{hol_suffix}", ) # Hari Raya Haji and Arafat Day. @@ -342,11 +347,12 @@ def _add_holiday(dt: date, hol: str) -> None: _add_holiday(hol_date, f"{name}{hol_suffix}") if self.subdiv == "TRG": # Arafat Day is one day before Eid al-Adha - _add_holiday(hol_date + rd(days=-1), f"Arafat Day{hol_suffix}") + _add_holiday(hol_date + td(days=-1), f"Arafat Day{hol_suffix}") if self.subdiv in {"KDH", "KTN", "PLS", "TRG"}: # Second day _add_holiday( - hol_date + rd(days=+1), f"{name} Holiday{hol_suffix}" + hol_date + td(days=+1), + f"{name} Holiday{hol_suffix}", ) # ---------------------------------------------------------# @@ -612,24 +618,24 @@ def _add_holiday(dt: date, hol: str) -> None: if hol_date.year != year: continue in_lieu_date = None - if hol_date.weekday() == FRI and self.subdiv in {"JHR", "KDH"}: - in_lieu_date = hol_date + rd(days=+2) - elif hol_date.weekday() == SAT and self.subdiv in { + if self._is_friday(hol_date) and self.subdiv in {"JHR", "KDH"}: + in_lieu_date = hol_date + td(days=+2) + elif self._is_saturday(hol_date) and self.subdiv in { "KTN", "TRG", }: - in_lieu_date = hol_date + rd(days=+1) - elif hol_date.weekday() == SUN and self.subdiv not in { + in_lieu_date = hol_date + td(days=+1) + elif self._is_sunday(hol_date) and self.subdiv not in { "JHR", "KDH", "KTN", "TRG", }: - in_lieu_date = hol_date + rd(days=+1) + in_lieu_date = hol_date + td(days=+1) if not in_lieu_date: continue while in_lieu_date.year == year and in_lieu_date in self: - in_lieu_date += rd(days=+1) + in_lieu_date += td(days=+1) _add_holiday(in_lieu_date, f"{hol_name} [In lieu]") # The last two days in May (Pesta Kaamatan). @@ -705,7 +711,7 @@ def _add_holiday(dt: date, hol: str) -> None: # Good Friday. if self.subdiv in {"SBH", "SWK"}: - self[easter(year) + rd(days=-2)] = "Good Friday" + self[easter(year) + td(days=-2)] = "Good Friday" # ----------------------------- # State holidays (single state) @@ -771,7 +777,6 @@ def _add_holiday(dt: date, hol: str) -> None: class MY(Malaysia): - # __init__ required for IDE typing and inheritance of docstring. def __init__( self, @@ -781,12 +786,14 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) class MYS(Malaysia): - # __init__ required for IDE typing and inheritance of docstring. def __init__( self, @@ -796,5 +803,8 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) diff --git a/holidays/countries/malta.py b/holidays/countries/malta.py index ff4debef1..117a6202c 100644 --- a/holidays/countries/malta.py +++ b/holidays/countries/malta.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, MAY, JUN, AUG, SEP, DEC from holidays.holiday_base import HolidayBase @@ -34,7 +34,7 @@ def _populate(self, year): self[date(year, MAR, 31)] = "Freedom Day" # Easter and easter related calculations - good_friday = easter(year) + rd(days=-2) + good_friday = easter(year) + td(days=-2) self[good_friday] = "Good Friday" self[date(year, MAY, 1)] = "Worker's Day" diff --git a/holidays/countries/marshall_islands.py b/holidays/countries/marshall_islands.py new file mode 100644 index 000000000..7e012566f --- /dev/null +++ b/holidays/countries/marshall_islands.py @@ -0,0 +1,108 @@ +# 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) +import warnings +from datetime import date +from datetime import timedelta as td + +from dateutil.easter import easter +from dateutil.relativedelta import FR +from dateutil.relativedelta import relativedelta as rd + +from holidays.constants import JAN, MAR, MAY, JUL, SEP, NOV, DEC +from holidays.holiday_base import HolidayBase + + +class HolidaysMH(HolidayBase): + """ + https://rmiparliament.org/cms/component/content/article/14-pressrelease/49-important-public-holidays.html?Itemid=101 + https://www.rmiembassyus.org/country-profile#:~:text=national%20holidays + """ + + country = "MH" + special_holidays = { + 2019: ((NOV, 18, "General Election Day"),), # Third Monday in November + } + + def _add_with_observed( + self, dt: date, name: str, after_sat: bool = False + ) -> None: + """ + Adds observed holiday on Monday when the current date falls on a Sunday + or, if after_sat is True, on a Saturday. + :param dt: The date. + :param name: The name of the holiday. + :param after_sat: Whether to add a Monday observed holiday when the + current date falls on a Saturday. + :return: None. + """ + self[dt] = name + if not self.observed: + return + if self._is_saturday(dt): + if after_sat: + self[dt + td(days=+2)] = f"{name} (Holiday)" + elif self._is_sunday(dt): + self[dt + td(days=+1)] = f"{name} (Holiday)" + + def _populate(self, year): + super()._populate(year) + + if year < 2023: + warnings.warn( + "Years before 2022 are not available for the Marshall Islands " + "(MH).", + Warning, + ) + + # New Year's Day + name = "New Year's Day" + self._add_with_observed(date(year, JAN, 1), name, after_sat=True) + + # Nuclear Victims Remembrance Day + self._add_with_observed( + date(year, MAR, 1), "Nuclear Victims Remembrance Day" + ) + + # Good Friday + self[easter(year) + td(days=-2)] = "Good Friday Friday" + + # Constitution Day + self[date(year, MAY, 1)] = "Constitution Day" + + # Fisherman's Day + self[date(year, JUL, 1) + rd(weekday=FR)] = "Fisherman's Day" + + # Dri-jerbal Day + self[date(year, SEP, 1) + rd(weekday=FR)] = "Dri-jerbal Day" + + # Manit Day + self[date(year, SEP, 30) + rd(weekday=FR(-1))] = "Manit Day" + + # President's Day + self._add_with_observed(date(year, NOV, 17), "President's Day") + + # Gospel Day + self[date(year, DEC, 1) + rd(weekday=FR)] = "Gospel Day" + + # Christmas Day + self._add_with_observed(date(year, DEC, 25), "Christmas Day") + + +class MH(HolidaysMH): + pass + + +class MHL(HolidaysMH): + pass + + +class MarshallIslands(HolidaysMH): + pass diff --git a/holidays/countries/mexico.py b/holidays/countries/mexico.py index 3832a7b82..b7275e08d 100644 --- a/holidays/countries/mexico.py +++ b/holidays/countries/mexico.py @@ -10,24 +10,24 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import FRI, SAT, SUN, JAN, FEB, MAR, MAY, SEP, NOV, DEC +from holidays.constants import JAN, FEB, MAR, MAY, SEP, NOV, DEC from holidays.holiday_base import HolidayBase class Mexico(HolidayBase): - country = "MX" def _add_with_observed(self, holiday: date, name: str): self[holiday] = name - if self.observed and holiday.weekday() == SAT: - self[holiday + rd(days=-1)] = name + " (Observed)" - elif self.observed and holiday.weekday() == SUN: - self[holiday + rd(days=+1)] = name + " (Observed)" + if self.observed and self._is_saturday(holiday): + self[holiday + td(days=-1)] = name + " (Observed)" + elif self.observed and self._is_sunday(holiday): + self[holiday + td(days=+1)] = name + " (Observed)" def _populate(self, year): super()._populate(year) @@ -36,11 +36,11 @@ def _populate(self, year): name = "Año Nuevo [New Year's Day]" dt = date(year, JAN, 1) self[dt] = name - if self.observed and dt.weekday() == SUN: - self[dt + rd(days=+1)] = name + " (Observed)" + if self.observed and self._is_sunday(dt): + self[dt + td(days=+1)] = name + " (Observed)" # The next year's observed New Year's Day can be in this year # when it falls on a Friday (Jan 1st is a Saturday) - if self.observed and date(year, DEC, 31).weekday() == FRI: + if self.observed and self._is_friday(year, DEC, 31): self[date(year, DEC, 31)] = name + " (Observed)" # Constitution Day diff --git a/holidays/countries/moldova.py b/holidays/countries/moldova.py index 7b03aedad..5c503cab7 100644 --- a/holidays/countries/moldova.py +++ b/holidays/countries/moldova.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, MAY, JUN, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -42,10 +42,10 @@ def _populate(self, year): # Orthodox Easter for day_after_easter in [-2, 0, 1]: - self[easter_date + rd(days=day_after_easter)] = "Paştele" + self[easter_date + td(days=day_after_easter)] = "Paştele" # Paştele Blajinilor - self[easter_date + rd(days=+9)] = "Paştele Blajinilor" + self[easter_date + td(days=+9)] = "Paştele Blajinilor" # Labour Day self[date(year, MAY, 1)] = "Ziua Internatională a Muncii" diff --git a/holidays/countries/monaco.py b/holidays/countries/monaco.py index 95b28a7bc..eb8b3a055 100644 --- a/holidays/countries/monaco.py +++ b/holidays/countries/monaco.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import SUN, JAN, MAY, AUG, NOV, DEC +from holidays.constants import JAN, MAY, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -32,8 +32,8 @@ class Monaco(HolidayBase): def _populate(self, year): def _add_with_observed(hol_date: date, hol_name: str) -> None: self[hol_date] = hol_name - if self.observed and hol_date.weekday() == SUN: - self[hol_date + rd(days=+1)] = f"{hol_name} (Observed)" + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" super()._populate(year) @@ -48,7 +48,7 @@ def _add_with_observed(hol_date: date, hol_name: str) -> None: easter_date = easter(year) # Easter Monday - self[easter_date + rd(days=+1)] = "Le lundi de Pâques [Easter Monday]" + self[easter_date + td(days=+1)] = "Le lundi de Pâques [Easter Monday]" # Labour Day _add_with_observed( @@ -56,15 +56,15 @@ def _add_with_observed(hol_date: date, hol_name: str) -> None: ) # Ascension's Day - self[easter_date + rd(days=+39)] = "L'Ascension [Ascension's Day]" + self[easter_date + td(days=+39)] = "L'Ascension [Ascension's Day]" # Whit Monday self[ - easter_date + rd(days=+50) + easter_date + td(days=+50) ] = "Le lundi de Pentecôte [Whit Monday]" # Corpus Christi - self[easter_date + rd(days=+60)] = "La Fête Dieu [Corpus Christi]" + self[easter_date + td(days=+60)] = "La Fête Dieu [Corpus Christi]" # Assumption's Day _add_with_observed( @@ -83,8 +83,8 @@ def _add_with_observed(hol_date: date, hol_name: str) -> None: # Immaculate Conception's Day dt = date(year, DEC, 8) - if year >= 2019 and dt.weekday() == SUN: - dt += rd(days=+1) + if year >= 2019 and self._is_sunday(dt): + dt += td(days=+1) self[dt] = "L'Immaculée Conception [Immaculate Conception's Day]" # Christmas Day diff --git a/holidays/countries/montenegro.py b/holidays/countries/montenegro.py index 677a4b467..e598bd99d 100644 --- a/holidays/countries/montenegro.py +++ b/holidays/countries/montenegro.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAY, JUL, SUN +from holidays.constants import JAN, MAY, JUL from holidays.holiday_base import HolidayBase @@ -29,30 +29,19 @@ class Montenegro(HolidayBase): country = "ME" - def _add_holiday_observed( - self, holiday_name: str, holiday_date_1: date, holiday_date_2: date - ) -> None: - if holiday_date_1.weekday() == SUN: - self[holiday_date_1] = holiday_name - self[holiday_date_1 + rd(days=+1)] = f"{holiday_name} (Observed)" - self[holiday_date_1 + rd(days=+2)] = f"{holiday_name} (Observed)" - elif holiday_date_2.weekday() == SUN: - self[holiday_date_1] = holiday_name - self[holiday_date_2] = holiday_name - self[holiday_date_2 + rd(days=+1)] = f"{holiday_name} (Observed)" - else: - self[holiday_date_1] = holiday_name - self[holiday_date_2] = holiday_name + def _add_holiday_observed(self, hol_date: date, hol_name: str) -> None: + self[hol_date] = hol_name + if self._is_weekend(hol_date): + self[hol_date + td(days=+2)] = f"{hol_name} (Observed)" + self[hol_date + td(days=+1)] = ( + f"{hol_name} (Observed)" if self._is_sunday(hol_date) else hol_name + ) def _populate(self, year: int) -> None: super()._populate(year) # New Year's Day. - self._add_holiday_observed( - "New Year's Day", - date(year, JAN, 1), - date(year, JAN, 2), - ) + self._add_holiday_observed(date(year, JAN, 1), "New Year's Day") # Orthodox Christmas Eve. self[date(year, JAN, 6)] = "Orthodox Christmas Eve" @@ -63,32 +52,22 @@ def _populate(self, year: int) -> None: easter_sunday = easter(year, method=EASTER_ORTHODOX) # Good Friday. - self[easter_sunday + rd(days=-2)] = "Orthodox Good Friday" + self[easter_sunday + td(days=-2)] = "Orthodox Good Friday" # Easter Sunday. self[easter_sunday] = "Orthodox Easter Sunday" # Easter Monday. - self[easter_sunday + rd(days=+1)] = "Orthodox Easter Monday" + self[easter_sunday + td(days=+1)] = "Orthodox Easter Monday" # Labour Day. - self._add_holiday_observed( - "Labour Day", date(year, MAY, 1), date(year, MAY, 2) - ) + self._add_holiday_observed(date(year, MAY, 1), "Labour Day") # Independence Day. - self._add_holiday_observed( - "Independence Day", - date(year, MAY, 21), - date(year, MAY, 22), - ) + self._add_holiday_observed(date(year, MAY, 21), "Independence Day") # Statehood Day. - self._add_holiday_observed( - "Statehood Day", - date(year, JUL, 13), - date(year, JUL, 14), - ) + self._add_holiday_observed(date(year, JUL, 13), "Statehood Day") class ME(Montenegro): diff --git a/holidays/countries/morocco.py b/holidays/countries/morocco.py index b6296da1f..80d4dc480 100644 --- a/holidays/countries/morocco.py +++ b/holidays/countries/morocco.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, MAR, MAY, JUL, AUG, NOV from holidays.holiday_base import HolidayBase @@ -103,7 +102,7 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 10, 1): hol_date = date_obs _add_holiday(hol_date, "Eid al-Fitr") - _add_holiday(hol_date + rd(days=+1), "Eid al-Fitr") + _add_holiday(hol_date + td(days=+1), "Eid al-Fitr") # Eid al-Adha - Sacrifice Festive # date of observance is announced yearly @@ -111,7 +110,7 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 12, 10): hol_date = date_obs _add_holiday(hol_date, "Eid al-Adha") - _add_holiday(hol_date + rd(days=+1), "Eid al-Adha") + _add_holiday(hol_date + td(days=+1), "Eid al-Adha") # Islamic New Year - (hijari_year, 1, 1) for date_obs in _islamic_to_gre(year, 1, 1): @@ -123,7 +122,7 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 3, 12): hol_date = date_obs _add_holiday(hol_date, "Aid al Mawlid Annabawi") - _add_holiday(hol_date + rd(days=+1), "Aid al Mawlid Annabawi") + _add_holiday(hol_date + td(days=+1), "Aid al Mawlid Annabawi") class MA(Morocco): diff --git a/holidays/countries/mozambique.py b/holidays/countries/mozambique.py index 809fe2129..d16f84794 100644 --- a/holidays/countries/mozambique.py +++ b/holidays/countries/mozambique.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, APR, MAY, JUN, SEP, OCT, DEC, SUN +from holidays.constants import JAN, FEB, APR, MAY, JUN, SEP, OCT, DEC from holidays.holiday_base import HolidayBase @@ -22,33 +22,39 @@ class Mozambique(HolidayBase): country = "MZ" def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + # whenever a public holiday falls on a Sunday, + # it rolls over to the following Monday + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (PONTE)" + if year <= 1974: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "Ano novo" + _add_with_observed(date(year, JAN, 1), "Ano novo") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Sexta-feira Santa" + self[easter_date + td(days=-2)] = "Sexta-feira Santa" # carnival is the Tuesday before Ash Wednesday # which is 40 days before easter excluding sundays - self[easter_date + rd(days=-47)] = "Carnaval" - - self[date(year, FEB, 3)] = "Dia dos Heróis Moçambicanos" - self[date(year, APR, 7)] = "Dia da Mulher Moçambicana" - self[date(year, MAY, 1)] = "Dia Mundial do Trabalho" - self[date(year, JUN, 25)] = "Dia da Independência Nacional" - self[date(year, SEP, 7)] = "Dia da Vitória" - self[date(year, SEP, 25)] = "Dia das Forças Armadas" - self[date(year, OCT, 4)] = "Dia da Paz e Reconciliação" - self[date(year, DEC, 25)] = "Dia de Natal e da Família" - - # whenever a public holiday falls on a Sunday, - # it rolls over to the following Monday - if self.observed: - for k, v in list(self.items()): - if k.weekday() == SUN and k.year == year: - self[k + rd(days=+1)] = v + " (PONTE)" + self[easter_date + td(days=-47)] = "Carnaval" + + _add_with_observed(date(year, FEB, 3), "Dia dos Heróis Moçambicanos") + _add_with_observed(date(year, APR, 7), "Dia da Mulher Moçambicana") + _add_with_observed(date(year, MAY, 1), "Dia Mundial do Trabalho") + _add_with_observed( + date(year, JUN, 25), "Dia da Independência Nacional" + ) + _add_with_observed(date(year, SEP, 7), "Dia da Vitória") + _add_with_observed(date(year, SEP, 25), "Dia das Forças Armadas") + if year >= 1993: + _add_with_observed( + date(year, OCT, 4), "Dia da Paz e Reconciliação" + ) + _add_with_observed(date(year, DEC, 25), "Dia de Natal e da Família") class MZ(Mozambique): diff --git a/holidays/countries/namibia.py b/holidays/countries/namibia.py index 65f8f0ebb..b8f3d1cdf 100644 --- a/holidays/countries/namibia.py +++ b/holidays/countries/namibia.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, MAY, AUG, SEP, DEC, SUN +from holidays.constants import JAN, FEB, MAR, MAY, AUG, SEP, DEC from holidays.holiday_base import HolidayBase @@ -33,43 +33,47 @@ class Namibia(HolidayBase): } def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + # https://tinyurl.com/lacorg5835 + # As of 1991/2/1, whenever a public holiday falls on a Sunday, + # it rolls over to the monday, unless that monday is already + # a public holiday. + self[hol_date] = hol_name + if ( + self.observed + and self._is_sunday(hol_date) + and hol_date >= date(1991, FEB, 1) + ): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + if year <= 1989: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" - self[date(year, MAR, 21)] = "Independence Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") + _add_with_observed(date(year, MAR, 21), "Independence Day") - # Easter Calculation easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" - self[easter_date + rd(days=+39)] = "Ascension Day" - # --------END OF EASTER------------# - - self[date(year, MAY, 1)] = "Workers' Day" - self[date(year, MAY, 4)] = "Cassinga Day" - self[date(year, MAY, 25)] = "Africa Day" - self[date(year, AUG, 26)] = "Heroes' Day" - - dt = date(year, SEP, 10) - if year >= 2005: - # http://www.lac.org.na/laws/2004/3348.pdf - self[dt] = "Day of the Namibian Women and Intr. Human Rights Day" - else: - self[dt] = "International Human Rights Day" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" + self[easter_date + td(days=+39)] = "Ascension Day" + + _add_with_observed(date(year, MAY, 1), "Workers' Day") + _add_with_observed(date(year, MAY, 4), "Cassinga Day") + _add_with_observed(date(year, MAY, 25), "Africa Day") + _add_with_observed(date(year, AUG, 26), "Heroes' Day") + + # http://www.lac.org.na/laws/2004/3348.pdf + _add_with_observed( + date(year, SEP, 10), + "Day of the Namibian Women and International Human Rights Day" + if year >= 2005 + else "International Human Rights Day", + ) self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Family Day" - - # https://tinyurl.com/lacorg5835 - # As of 1991/2/1, whenever a public holiday falls on a Sunday, - # it rolls over to the monday, unless that monday is already - # a public holiday. - if self.observed: - for k, v in list(self.items()): - if k.weekday() == SUN and k.year == year: - self[k + rd(days=+1)] = v + " (Observed)" + _add_with_observed(date(year, DEC, 26), "Family Day") class NA(Namibia): diff --git a/holidays/countries/netherlands.py b/holidays/countries/netherlands.py index 72f92ef48..cc65ccbd2 100644 --- a/holidays/countries/netherlands.py +++ b/holidays/countries/netherlands.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, APR, MAY, AUG, DEC, SUN +from holidays.constants import JAN, APR, MAY, AUG, DEC from holidays.holiday_base import HolidayBase @@ -37,19 +37,19 @@ def _populate(self, year): self[easter_date] = "Eerste paasdag" # Good friday - self[easter_date + rd(days=-2)] = "Goede Vrijdag" + self[easter_date + td(days=-2)] = "Goede Vrijdag" # Second easter day - self[easter_date + rd(days=+1)] = "Tweede paasdag" + self[easter_date + td(days=+1)] = "Tweede paasdag" # Ascension day - self[easter_date + rd(days=+39)] = "Hemelvaart" + self[easter_date + td(days=+39)] = "Hemelvaart" # Pentecost - self[easter_date + rd(days=+49)] = "Eerste Pinksterdag" + self[easter_date + td(days=+49)] = "Eerste Pinksterdag" # Pentecost monday - self[easter_date + rd(days=+50)] = "Tweede Pinksterdag" + self[easter_date + td(days=+50)] = "Tweede Pinksterdag" # First christmas self[date(year, DEC, 25)] = "Eerste Kerstdag" @@ -64,8 +64,8 @@ def _populate(self, year): # Kingsday if year >= 2014: kings_day = date(year, APR, 27) - if kings_day.weekday() == SUN: - kings_day += rd(days=-1) + if self._is_sunday(kings_day): + kings_day += td(days=-1) self[kings_day] = "Koningsdag" @@ -75,8 +75,8 @@ def _populate(self, year): if year <= 1948: queens_day = date(year, AUG, 31) - if queens_day.weekday() == SUN: - queens_day += rd(days=1) if year < 1980 else rd(days=-1) + if self._is_sunday(queens_day): + queens_day += td(days=1) if year < 1980 else td(days=-1) self[queens_day] = "Koninginnedag" diff --git a/holidays/countries/new_zealand.py b/holidays/countries/new_zealand.py index f4dc5f30b..6a4b057af 100644 --- a/holidays/countries/new_zealand.py +++ b/holidays/countries/new_zealand.py @@ -10,18 +10,17 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, TU, WE from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAR, APR, JUN, JUL, SEP, OCT, NOV -from holidays.constants import DEC, FRI +from holidays.constants import JAN, FEB, MAR, APR, JUN, JUL, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase class NewZealand(HolidayBase): - country = "NZ" special_holidays = {2022: ((SEP, 26, "Queen Elizabeth II Memorial Day"),)} subdivisions = [ @@ -64,18 +63,18 @@ class NewZealand(HolidayBase): "WTL", # Correct code is WTC ] - @staticmethod - def _get_nearest_monday(d: date) -> date: - if d.weekday() < FRI: - return d + rd(weekday=MO(-1)) - else: - return d + rd(weekday=MO) + def _get_nearest_monday(self, dt: date) -> date: + return ( + dt + rd(weekday=MO(-1)) + if not self._is_friday(dt) and not self._is_weekend(dt) + else dt + rd(weekday=MO) + ) def _add_observed(self, dt: date) -> None: if self.observed and self._is_weekend(dt): obs_date = dt + rd(weekday=MO) if self.get(obs_date): - obs_date += rd(days=+1) + obs_date += td(days=+1) self[obs_date] = f"{self[dt]} (Observed)" def _populate(self, year): @@ -91,7 +90,8 @@ def _populate(self, year): # Holidays Act 1981, 2003 if year <= 1893: - return + return None + super()._populate(year) # New Year's Day @@ -122,8 +122,8 @@ def _populate(self, year): # Easter easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" # Sovereign's Birthday if year >= 1902: @@ -215,7 +215,7 @@ def _populate(self, year): elif self.subdiv in {"Hawke's Bay", "HKB"}: self[ - (date(year, OCT, 1) + rd(weekday=MO(+4)) + rd(days=-3)) + (date(year, OCT, 1) + rd(weekday=MO(+4)) + td(days=-3)) ] = "Hawke's Bay Anniversary Day" elif self.subdiv in {"WGN", "Wellington"}: @@ -225,7 +225,7 @@ def _populate(self, year): elif self.subdiv in {"Marlborough", "MBH"}: self[ - (date(year, OCT, 1) + rd(weekday=MO(+4)) + rd(days=+7)) + (date(year, OCT, 1) + rd(weekday=MO(+4)) + td(days=+7)) ] = "Marlborough Anniversary Day" elif self.subdiv in {"Nelson", "NSN"}: @@ -235,7 +235,7 @@ def _populate(self, year): elif self.subdiv in {"CAN", "Canterbury"}: self[ - (date(year, NOV, 1) + rd(weekday=TU) + rd(days=+10)) + (date(year, NOV, 1) + rd(weekday=TU) + td(days=+10)) ] = "Canterbury Anniversary Day" elif self.subdiv in {"South Canterbury", "STC"}: @@ -254,14 +254,14 @@ def _populate(self, year): elif self.subdiv in {"OTA", "Otago"}: # there is no easily determined single day of local observance?!?! dt = self._get_nearest_monday(date(year, MAR, 23)) - if dt == easter_date + rd(days=+1): # Avoid Easter Monday - dt += rd(days=+1) + if dt == easter_date + td(days=+1): # Avoid Easter Monday + dt += td(days=+1) self[dt] = "Otago Anniversary Day" elif self.subdiv in {"STL", "Southland"}: name = "Southland Anniversary Day" if year >= 2012: - self[easter_date + rd(days=+2)] = name + self[easter_date + td(days=+2)] = name else: self[self._get_nearest_monday(date(year, JAN, 17))] = name diff --git a/holidays/countries/nicaragua.py b/holidays/countries/nicaragua.py index 797e4b46f..c2403e85d 100644 --- a/holidays/countries/nicaragua.py +++ b/holidays/countries/nicaragua.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUL, AUG, SEP, DEC from holidays.holiday_base import HolidayBase @@ -35,9 +35,9 @@ def _populate(self, year): self[date(year, JAN, 1)] = "Año Nuevo [New Year's Day]" # Maundy Thursday easter_date = easter(year) - self[easter_date + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Maundy Thursday]" # Good Friday - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" # Labor Day self[date(year, MAY, 1)] = "Día del Trabajo [Labour Day]" # Revolution Day diff --git a/holidays/countries/nigeria.py b/holidays/countries/nigeria.py index 067f4180b..1eca09322 100644 --- a/holidays/countries/nigeria.py +++ b/holidays/countries/nigeria.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUN, OCT, DEC from holidays.holiday_base import HolidayBase @@ -36,7 +36,8 @@ def _add_holiday(dt: date, hol: str) -> None: self[dt] = hol if year <= 1978: - return + return None + super()._populate(year) # New Year's Day @@ -45,8 +46,8 @@ def _add_holiday(dt: date, hol: str) -> None: # Calculate Easter for given year # followed by easter related holidays easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = "Easter Monday" # Worker's day if year >= 1981: @@ -58,7 +59,7 @@ def _add_holiday(dt: date, hol: str) -> None: for yr in (year - 1, year): for hol_date in _islamic_to_gre(yr, 10, 1): _add_holiday(hol_date, "Eid al-Fitr") - _add_holiday(hol_date + rd(days=+1), "Eid al-Fitr Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Fitr Holiday") # Arafat Day & Eid al-Adha - Scarfice Festive # This is an estimate @@ -66,7 +67,7 @@ def _add_holiday(dt: date, hol: str) -> None: for yr in (year - 1, year): for hol_date in _islamic_to_gre(yr, 12, 10): _add_holiday(hol_date, "Eid al-Adha") - _add_holiday(hol_date + rd(days=+1), "Eid al-Adha Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Adha Holiday") # Birthday of Prophet Muhammad for hol_date in _islamic_to_gre(year, 3, 12): @@ -94,11 +95,11 @@ def _add_holiday(dt: date, hol: str) -> None: if self.observed and year >= 2016: for k, v in list(self.items()): if self._is_weekend(k) and k.year == year: - next_workday = k + rd(days=+1) + next_workday = k + td(days=+1) while self._is_weekend(next_workday) or self.get( next_workday ): - next_workday += rd(days=+1) + next_workday += td(days=+1) self[next_workday] = v + " (Observed)" diff --git a/holidays/countries/north_macedonia.py b/holidays/countries/north_macedonia.py index d6786ab09..feda3d682 100644 --- a/holidays/countries/north_macedonia.py +++ b/holidays/countries/north_macedonia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, SEP, AUG, OCT, DEC from holidays.holiday_base import HolidayBase @@ -33,7 +33,7 @@ def _populate(self, year): self[date(year, JAN, 7)] = "Christmas Day (Orthodox)" easter_date = easter(year, method=EASTER_ORTHODOX) - self[easter_date + rd(days=+1)] = "Easter Monday(Orthodox)" + self[easter_date + td(days=+1)] = "Easter Monday(Orthodox)" self[date(year, MAY, 1)] = "Labour Day" self[date(year, MAY, 24)] = "Saints Cyril and Methodius Day" self[date(year, AUG, 2)] = "Republic Day" diff --git a/holidays/countries/northern_mariana_islands.py b/holidays/countries/northern_mariana_islands.py new file mode 100644 index 000000000..0ff9e1c64 --- /dev/null +++ b/holidays/countries/northern_mariana_islands.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysMP(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "MP" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "MP" + super()._populate(year) + + +class MP(HolidaysMP): + pass + + +class MNP(HolidaysMP): + pass + + +class NorthernMarianaIslands(HolidaysMP): + pass diff --git a/holidays/countries/norway.py b/holidays/countries/norway.py index 594cbe42c..5d5e1b337 100644 --- a/holidays/countries/norway.py +++ b/holidays/countries/norway.py @@ -10,11 +10,11 @@ # License: MIT (see LICENSE file) from datetime import date, datetime +from datetime import timedelta as td from dateutil import rrule from dateutil.easter import easter from dateutil.relativedelta import SU -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, DEC from holidays.holiday_base import HolidayBase @@ -85,13 +85,13 @@ def _populate(self, year): # "(...) has been celebrated for over 1000 years (...)" (in Norway) easter_date = easter(year) - self[easter_date + rd(days=-3)] = "Skjærtorsdag" - self[easter_date + rd(days=-2)] = "Langfredag" + self[easter_date + td(days=-3)] = "Skjærtorsdag" + self[easter_date + td(days=-2)] = "Langfredag" self[easter_date] = "Første påskedag" - self[easter_date + rd(days=+1)] = "Andre påskedag" - self[easter_date + rd(days=+39)] = "Kristi himmelfartsdag" - self[easter_date + rd(days=+49)] = "Første pinsedag" - self[easter_date + rd(days=+50)] = "Andre pinsedag" + self[easter_date + td(days=+1)] = "Andre påskedag" + self[easter_date + td(days=+39)] = "Kristi himmelfartsdag" + self[easter_date + td(days=+49)] = "Første pinsedag" + self[easter_date + td(days=+50)] = "Andre pinsedag" class NO(Norway): diff --git a/holidays/countries/pakistan.py b/holidays/countries/pakistan.py index 0ab278307..93c35eb6c 100644 --- a/holidays/countries/pakistan.py +++ b/holidays/countries/pakistan.py @@ -10,10 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from typing import Dict, Tuple, List -from dateutil.relativedelta import relativedelta as rd - from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -29,7 +28,8 @@ def _add_holiday(dt: date, hol: str) -> None: self[dt] = hol if year <= 1947: - return + return None + super()._populate(year) # Kashmir Solidarity Day @@ -80,8 +80,8 @@ def _add_holiday(dt: date, hol: str) -> None: hol_dates = self._get_islamic_holiday(name, year, 10, 1, dates_obs) for hol_date, hol_name in hol_dates: _add_holiday(hol_date, hol_name) - _add_holiday(hol_date + rd(days=+1), hol_name) - _add_holiday(hol_date + rd(days=+2), hol_name) + _add_holiday(hol_date + td(days=+1), hol_name) + _add_holiday(hol_date + td(days=+2), hol_name) # Eid-ul-Adha # https://www.timeanddate.com/holidays/pakistan/eid-ul-azha @@ -112,8 +112,8 @@ def _add_holiday(dt: date, hol: str) -> None: hol_dates = self._get_islamic_holiday(name, year, 12, 10, dates_obs) for hol_date, hol_name in hol_dates: _add_holiday(hol_date, hol_name) - _add_holiday(hol_date + rd(days=+1), hol_name) - _add_holiday(hol_date + rd(days=+2), hol_name) + _add_holiday(hol_date + td(days=+1), hol_name) + _add_holiday(hol_date + td(days=+2), hol_name) # Eid Milad-un-Nabi, Birth of the Prophet # https://www.timeanddate.com/holidays/pakistan/eid-milad-un-nabi @@ -171,7 +171,7 @@ def _add_holiday(dt: date, hol: str) -> None: hol_dates = self._get_islamic_holiday(name, year, 1, 10, dates_obs) for hol_date, hol_name in hol_dates: _add_holiday(hol_date, hol_name) - _add_holiday(hol_date + rd(days=+1), hol_name) + _add_holiday(hol_date + td(days=+1), hol_name) @staticmethod def _get_islamic_holiday( diff --git a/holidays/countries/panama.py b/holidays/countries/panama.py new file mode 100644 index 000000000..ec4318836 --- /dev/null +++ b/holidays/countries/panama.py @@ -0,0 +1,86 @@ +# 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-2022 +# 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 dateutil.easter import easter + +from holidays.constants import JAN, MAY, NOV, DEC +from holidays.holiday_base import HolidayBase + + +class Panama(HolidayBase): + """ + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Panama + - https://publicholidays.com.pa/ + """ + + country = "PA" + + def _populate(self, year: int) -> None: + def _add_with_observed(hol_date: date, hol_name: str) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + + super()._populate(year) + + # New Year's Day + _add_with_observed(date(year, JAN, 1), "New Year's Day") + + # Martyrs' Day + _add_with_observed(date(year, JAN, 9), "Martyrs' Day") + + easter_date = easter(year) + + # Carnival + self[easter_date + td(days=-47)] = "Carnival" + + # Good Friday + self[easter_date + td(days=-2)] = "Good Friday" + + # Labour Day + _add_with_observed(date(year, MAY, 1), "Labour Day") + + # Separation Day + self[date(year, NOV, 3)] = "Separation Day" + + # National Symbols Day + self[date(year, NOV, 4)] = "National Symbols Day" + + # Colon Day + self[date(year, NOV, 5)] = "Colon Day" + + # Los Santos Uprising Day + self[date(year, NOV, 10)] = "Los Santos Uprising Day" + + # Independence Day + _add_with_observed(date(year, NOV, 28), "Independence Day") + + # Mother's Day + _add_with_observed(date(year, DEC, 8), "Mother's Day") + + # National Mourning Day + if year >= 2022: + _add_with_observed(date(year, DEC, 20), "National Mourning Day") + + # Christmas Day + _add_with_observed(date(year, DEC, 25), "Christmas Day") + + +class PA(Panama): + pass + + +class PAN(Panama): + pass diff --git a/holidays/countries/paraguay.py b/holidays/countries/paraguay.py index dc7b79339..798a5c9ba 100644 --- a/holidays/countries/paraguay.py +++ b/holidays/countries/paraguay.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP from holidays.constants import OCT, DEC @@ -160,8 +160,8 @@ def _populate(self, year): # Holy Week easter_date = easter(year) - self[easter_date + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" self._add_holiday(easter_date, "Día de Pascuas [Easter Day]") # Labor Day diff --git a/holidays/countries/peru.py b/holidays/countries/peru.py index 76882ff4c..d8e1dbf0f 100644 --- a/holidays/countries/peru.py +++ b/holidays/countries/peru.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUN, JUL, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -53,13 +53,13 @@ def _populate(self, year): easter_date = easter(year) # Holy Thursday - self[easter_date + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Maundy Thursday]" # Good Friday - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" # Holy Saturday - self[easter_date + rd(days=-1)] = "Sábado de Gloria [Holy Saturday]" + self[easter_date + td(days=-1)] = "Sábado de Gloria [Holy Saturday]" # Easter Sunday self[easter_date] = "Domingo de Resurrección [Easter Sunday]" diff --git a/holidays/countries/philippines.py b/holidays/countries/philippines.py index ee7bd8232..e48cf03cd 100644 --- a/holidays/countries/philippines.py +++ b/holidays/countries/philippines.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO @@ -51,11 +52,11 @@ def _populate(self, year): easter_date = easter(year) # Maundy Thursday. - self[easter_date + rd(days=-3)] = "Maundy Thursday" + self[easter_date + td(days=-3)] = "Maundy Thursday" # Good Friday. - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-2)] = "Good Friday" # Black Saturday. - self[easter_date + rd(days=-1)] = "Black Saturday" + self[easter_date + td(days=-1)] = "Black Saturday" # Labour Day. self[date(year, MAY, 1)] = "Labour Day" diff --git a/holidays/countries/poland.py b/holidays/countries/poland.py index d0140fd47..f6e723ed0 100644 --- a/holidays/countries/poland.py +++ b/holidays/countries/poland.py @@ -10,11 +10,12 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td +from gettext import gettext as tr from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAY, AUG, NOV, DEC +from holidays.constants import JAN, FEB, MAY, JUN, JUL, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -24,37 +25,88 @@ class Poland(HolidayBase): """ country = "PL" + default_language = "pl" special_holidays = { - 2018: ((NOV, 12, "Narodowe Święto Niepodległości - 100-lecie"),) + 2018: ((NOV, 12, tr("Narodowe Święto Niepodległości - 100-lecie")),) } def _populate(self, year): + if year <= 1924: + return None + super()._populate(year) - self[date(year, JAN, 1)] = "Nowy Rok" - if year >= 2011: - self[date(year, JAN, 6)] = "Święto Trzech Króli" + self[date(year, JAN, 1)] = self.tr("Nowy Rok") + + if year <= 1960 or year >= 2011: + self[date(year, JAN, 6)] = self.tr("Święto Trzech Króli") + + if year <= 1950: + self[date(year, FEB, 2)] = self.tr( + "Oczyszczenie Najświętszej Marii Panny" + ) easter_date = easter(year) - self[easter_date] = "Niedziela Wielkanocna" - self[easter_date + rd(days=+1)] = "Poniedziałek Wielkanocny" + self[easter_date] = self.tr("Niedziela Wielkanocna") + + self[easter_date + td(days=+1)] = self.tr("Poniedziałek Wielkanocny") if year >= 1950: - self[date(year, MAY, 1)] = "Święto Państwowe" - if year >= 1919: - self[date(year, MAY, 3)] = "Święto Narodowe Trzeciego Maja" + self[date(year, MAY, 1)] = self.tr("Święto Państwowe") + + if year <= 1950 or year >= 1990: + self[date(year, MAY, 3)] = self.tr( + "Święto Narodowe Trzeciego Maja" + ) + + if 1946 <= year <= 1950: + self[date(year, MAY, 9)] = self.tr( + "Narodowe Święto Zwycięstwa i Wolności" + ) + + if year <= 1950: + self[easter_date + td(days=+40)] = self.tr( + "Wniebowstąpienie Pańskie" + ) + + self[easter_date + td(days=+49)] = self.tr("Zielone Świątki") + + if year <= 1950: + self[easter_date + td(days=+50)] = self.tr( + "Drugi dzień Zielonych Świątek" + ) + + self[easter_date + td(days=+60)] = self.tr("Dzień Bożego Ciała") + + if year <= 1950: + self[date(year, JUN, 29)] = self.tr( + "Uroczystość Świętych Apostołów Piotra i Pawła" + ) + + if 1945 <= year <= 1989: + self[date(year, JUL, 22)] = self.tr( + "Narodowe Święto Odrodzenia Polski" + ) + + if year <= 1960 or year >= 1989: + self[date(year, AUG, 15)] = self.tr( + "Wniebowzięcie Najświętszej Marii Panny" + ) - self[easter_date + rd(days=+49)] = "Zielone Świątki" - self[easter_date + rd(days=+60)] = "Dzień Bożego Ciała" + self[date(year, NOV, 1)] = self.tr("Uroczystość Wszystkich Świętych") - self[date(year, AUG, 15)] = "Wniebowzięcie Najświętszej Marii Panny" + if 1937 <= year <= 1944 or year >= 1989: + self[date(year, NOV, 11)] = self.tr( + "Narodowe Święto Niepodległości" + ) - self[date(year, NOV, 1)] = "Uroczystość Wszystkich Świętych" - if (1937 <= year <= 1945) or year >= 1989: - self[date(year, NOV, 11)] = "Narodowe Święto Niepodległości" + if year <= 1950: + self[date(year, DEC, 8)] = self.tr( + "Niepokalane Poczęcie Najświętszej Marii Panny" + ) - self[date(year, DEC, 25)] = "Boże Narodzenie (pierwszy dzień)" - self[date(year, DEC, 26)] = "Boże Narodzenie (drugi dzień)" + self[date(year, DEC, 25)] = self.tr("Boże Narodzenie (pierwszy dzień)") + self[date(year, DEC, 26)] = self.tr("Boże Narodzenie (drugi dzień)") class PL(Poland): diff --git a/holidays/countries/portugal.py b/holidays/countries/portugal.py index 376c1d425..a5d5726c2 100644 --- a/holidays/countries/portugal.py +++ b/holidays/countries/portugal.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT from holidays.constants import NOV, DEC @@ -59,13 +59,13 @@ def _populate(self, year): # carnival is no longer a holiday, but some companies let workers off. # @todo recollect the years in which it was a public holiday - # self[e + rd(days=-47)] = "Carnaval" - self[easter_date + rd(days=-2)] = "Sexta-feira Santa" + # self[e + td(days=-47)] = "Carnaval" + self[easter_date + td(days=-2)] = "Sexta-feira Santa" self[easter_date] = "Páscoa" # Revoked holidays in 2013–2015 if year < 2013 or year > 2015: - self[easter_date + rd(days=+60)] = "Corpo de Deus" + self[easter_date + td(days=+60)] = "Corpo de Deus" self[date(year, OCT, 5)] = "Implantação da República" self[date(year, NOV, 1)] = "Dia de Todos os Santos" self[date(year, DEC, 1)] = "Restauração da Independência" @@ -88,7 +88,7 @@ def _populate(self, year): - Lisbon's city holiday """ - self[easter_date + rd(days=-47)] = "Carnaval" + self[easter_date + td(days=-47)] = "Carnaval" self[date(year, DEC, 24)] = "Véspera de Natal" self[date(year, DEC, 26)] = "26 de Dezembro" self[date(year, DEC, 31)] = "Véspera de Ano Novo" @@ -102,14 +102,14 @@ def _populate(self, year): if self.subdiv == "01": self[date(year, MAY, 12)] = "Dia de Santa Joana" if self.subdiv == "02": - self[easter_date + rd(days=+39)] = "Quinta-feira da Ascensão" + self[easter_date + td(days=+39)] = "Quinta-feira da Ascensão" if self.subdiv in {"03", "13"}: self[date(year, JUN, 24)] = "Dia de São João" if self.subdiv == "04": self[date(year, AUG, 22)] = "Dia de Nossa Senhora das Graças" if self.subdiv == "05": self[ - easter_date + rd(days=+16) + easter_date + td(days=+16) ] = "Dia de Nossa Senhora de Mércoles" if self.subdiv == "06": self[date(year, JUL, 4)] = "Dia de Santa Isabel" diff --git a/holidays/countries/puerto_rico.py b/holidays/countries/puerto_rico.py new file mode 100644 index 000000000..2a1e2f280 --- /dev/null +++ b/holidays/countries/puerto_rico.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysPR(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "PR" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "PR" + super()._populate(year) + + +class PR(HolidaysPR): + pass + + +class PRI(HolidaysPR): + pass + + +class PuertoRico(HolidaysPR): + pass diff --git a/holidays/countries/romania.py b/holidays/countries/romania.py index 69ae46335..1b0e08600 100644 --- a/holidays/countries/romania.py +++ b/holidays/countries/romania.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUN, AUG, NOV, DEC from holidays.holiday_base import HolidayBase @@ -39,7 +39,7 @@ def _populate(self, year): # Easter (Friday, Sunday and Monday) for day_after_easter in (-2, 0, 1): - self[easter_date + rd(days=day_after_easter)] = "Paștele" + self[easter_date + td(days=day_after_easter)] = "Paștele" # Labour Day self[date(year, MAY, 1)] = "Ziua Muncii" @@ -50,7 +50,7 @@ def _populate(self, year): # Whit Monday for day_after_easter in (49, 50): - self[easter_date + rd(days=day_after_easter)] = "Rusaliile" + self[easter_date + td(days=day_after_easter)] = "Rusaliile" # Assumption of Mary self[date(year, AUG, 15)] = "Adormirea Maicii Domnului" diff --git a/holidays/countries/russia.py b/holidays/countries/russia.py index 3cb00931b..13df150dc 100644 --- a/holidays/countries/russia.py +++ b/holidays/countries/russia.py @@ -21,40 +21,41 @@ class Russia(HolidayBase): """ country = "RU" + default_language = "ru" def _populate(self, year): super()._populate(year) - # New Year Holidays - name = "Новогодние каникулы" + # New Year Holidays. + name = self.tr("Новогодние каникулы") for day in range(1, 7): self[date(year, JAN, day)] = name self[date(year, JAN, 8)] = name - # Christmas Day (Orthodox) - self[date(year, JAN, 7)] = "Рождество Христово" + # Orthodox Christmas Day. + self[date(year, JAN, 7)] = self.tr("Рождество Христово") - # Defender of the Fatherland Day - self[date(year, FEB, 23)] = "День защитника Отечества" + # Defender of the Fatherland Day. + self[date(year, FEB, 23)] = self.tr("День защитника Отечества") - # International Women's Day - self[date(year, MAR, 8)] = "Международный женский день" + # International Women's Day. + self[date(year, MAR, 8)] = self.tr("Международный женский день") - # Labour Day - self[date(year, MAY, 1)] = "Праздник Весны и Труда" + # Labour Day. + self[date(year, MAY, 1)] = self.tr("Праздник Весны и Труда") - # Victory Day - self[date(year, MAY, 9)] = "День Победы" + # Victory Day. + self[date(year, MAY, 9)] = self.tr("День Победы") - # Russia's Day - self[date(year, JUN, 12)] = "День России" + # Russia's Day. + self[date(year, JUN, 12)] = self.tr("День России") if year >= 2005: - # Unity Day - self[date(year, NOV, 4)] = "День народного единства" + # Unity Day. + self[date(year, NOV, 4)] = self.tr("День народного единства") else: - # October Revolution Day - self[date(year, NOV, 7)] = "День Октябрьской революции" + # October Revolution Day. + self[date(year, NOV, 7)] = self.tr("День Октябрьской революции") class RU(Russia): diff --git a/holidays/countries/san_marino.py b/holidays/countries/san_marino.py index ac0afe078..73a2747aa 100644 --- a/holidays/countries/san_marino.py +++ b/holidays/countries/san_marino.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, MAY, JUL, AUG, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -47,13 +47,13 @@ def _populate(self, year: int) -> None: self[easter_sunday] = "Easter Sunday" # Easter Monday. - self[easter_sunday + rd(days=+1)] = "Easter Monday" + self[easter_sunday + td(days=+1)] = "Easter Monday" # Labour Day. self[date(year, MAY, 1)] = "Labour Day" # Corpus Cristi. - self[easter_sunday + rd(days=+60)] = "Corpus Cristi" + self[easter_sunday + td(days=+60)] = "Corpus Cristi" # Liberation from Fascism Day. self[date(year, JUL, 28)] = "Liberation from Fascism Day" diff --git a/holidays/countries/saudi_arabia.py b/holidays/countries/saudi_arabia.py index 4bdf57f0c..b24319683 100644 --- a/holidays/countries/saudi_arabia.py +++ b/holidays/countries/saudi_arabia.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import FEB, SEP, THU, FRI, SAT from holidays.holiday_base import HolidayBase @@ -41,13 +40,11 @@ class SaudiArabia(HolidayBase): def _populate(self, year): super()._populate(year) - if year < 2013: - # Weekend used to be THU, FRI before June 28th, 2013 - # On that year both Eids were after that date, and foudning - # day holiday started at 2022; so what below works, - self.weekend = (THU, FRI) - else: - self.weekend = (FRI, SAT) + # Weekend used to be THU, FRI before June 28th, 2013. + # On that year both Eids were after that date, and founding + # day holiday started at 2022; so what below works. + # It has to be a tuple (subscriptable) due to a business logic below. + self.weekend = (THU, FRI) if year < 2013 else (FRI, SAT) observed_str = " (observed)" @@ -69,17 +66,17 @@ def _add_holiday(dt: date, hol: str) -> None: holiday_name = "Eid al-Fitr Holiday" for yr in (year - 1, year): for hijri_date in _islamic_to_gre(yr, 9, 29): - hijri_date += rd(days=+1) + hijri_date += td(days=+1) for dys in range(4): - _add_holiday((hijri_date + rd(days=dys)), holiday_name) + _add_holiday((hijri_date + td(days=dys)), holiday_name) if self.observed: weekend_days = sum( - (hijri_date + rd(days=dys)).weekday() in self.weekend + (hijri_date + td(days=dys)).weekday() in self.weekend for dys in range(4) ) for dys in range(weekend_days): _add_holiday( - hijri_date + rd(days=4 + dys), + hijri_date + td(days=4 + dys), holiday_name + observed_str, ) @@ -95,15 +92,15 @@ def _add_holiday(dt: date, hol: str) -> None: for hijri_date in _islamic_to_gre(yr, 12, 9): _add_holiday(hijri_date, "Arafat Day Holiday") for dys in range(1, 4): - _add_holiday((hijri_date + rd(days=dys)), holiday_name) + _add_holiday((hijri_date + td(days=dys)), holiday_name) if self.observed: weekend_days = sum( - (hijri_date + rd(days=dys)).weekday() in self.weekend + (hijri_date + td(days=dys)).weekday() in self.weekend for dys in range(4) ) for dys in range(weekend_days): _add_holiday( - hijri_date + rd(days=4 + dys), + hijri_date + td(days=4 + dys), holiday_name + observed_str, ) @@ -117,13 +114,13 @@ def _add_holiday(dt: date, hol: str) -> None: self[national_day] = holiday_name # First weekend day(Thursaday before 2013 and Friday otherwise) if self.observed and national_day.weekday() == self.weekend[0]: - national_day += rd(days=-1) + national_day += td(days=-1) self[national_day] = holiday_name + observed_str # Second weekend day(Friday before 2013 and Saturday otherwise) elif ( self.observed and national_day.weekday() == self.weekend[1] ): - national_day += rd(days=+1) + national_day += td(days=+1) self[national_day] = holiday_name + observed_str # Founding Day holiday (started 2022). @@ -136,13 +133,13 @@ def _add_holiday(dt: date, hol: str) -> None: self[founding_day] = holiday_name # First weekend day(Thursaday before 2013 and Friday otherwise) if self.observed and founding_day.weekday() == self.weekend[0]: - founding_day += rd(days=-1) + founding_day += td(days=-1) self[founding_day] = holiday_name + observed_str # Second weekend day(Friday before 2013 and Saturday otherwise) elif ( self.observed and founding_day.weekday() == self.weekend[1] ): - founding_day += rd(days=+1) + founding_day += td(days=+1) self[founding_day] = holiday_name + observed_str diff --git a/holidays/countries/serbia.py b/holidays/countries/serbia.py index 673cc0c48..34efd8f19 100644 --- a/holidays/countries/serbia.py +++ b/holidays/countries/serbia.py @@ -10,59 +10,71 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAY, NOV, SUN +from holidays.constants import JAN, FEB, MAY, NOV from holidays.holiday_base import HolidayBase class Serbia(HolidayBase): """ - https://en.wikipedia.org/wiki/Public_holidays_in_Serbia + Serbia holidays. + + References: + - https://en.wikipedia.org/wiki/Public_holidays_in_Serbia """ country = "RS" + default_language = "sr" def _populate(self, year): super()._populate(year) - # New Year's Day - name = "Нова година" + # New Year's Day. + name = self.tr("Нова година") self[date(year, JAN, 1)] = name self[date(year, JAN, 2)] = name if self.observed and self._is_weekend(year, JAN, 1): - self[date(year, JAN, 3)] = name + " (Observed)" - # Orthodox Christmas - name = "Божић" - self[date(year, JAN, 7)] = name - # Statehood day - name = "Дан државности Србије" + self[date(year, JAN, 3)] = self.tr("%s (Слободан дан)") % name + + # Orthodox Christmas. + self[date(year, JAN, 7)] = self.tr("Божић") + + # Statehood Day. + name = self.tr("Дан државности Србије") self[date(year, FEB, 15)] = name self[date(year, FEB, 16)] = name if self.observed and self._is_weekend(year, FEB, 15): - self[date(year, FEB, 17)] = name + " (Observed)" - # International Workers' Day - name = "Празник рада" + self[date(year, FEB, 17)] = self.tr("%s (Слободан дан)") % name + + easter_date = easter(year, method=EASTER_ORTHODOX) + + # International Workers' Day. + name = self.tr("Празник рада") self[date(year, MAY, 1)] = name self[date(year, MAY, 2)] = name - easter_date = easter(year, method=EASTER_ORTHODOX) if self.observed and self._is_weekend(date(year, MAY, 1)): if date(year, MAY, 2) == easter_date: - self[date(year, MAY, 4)] = name + " (Observed)" + self[date(year, MAY, 4)] = self.tr("%s (Слободан дан)") % name else: - self[date(year, MAY, 3)] = name + " (Observed)" - # Armistice day - name = "Дан примирја у Првом светском рату" + self[date(year, MAY, 3)] = self.tr("%s (Слободан дан)") % name + + # Armistice Day. + name = self.tr("Дан примирја у Првом светском рату") self[date(year, NOV, 11)] = name - if self.observed and date(year, NOV, 11).weekday() == SUN: - self[date(year, NOV, 12)] = name + " (Observed)" - # Easter - self[easter_date + rd(days=-2)] = "Велики петак" - self[easter_date + rd(days=-1)] = "Велика субота" - self[easter_date] = "Васкрс" - self[easter_date + rd(days=+1)] = "Други дан Васкрса" + if self.observed and self._is_sunday(year, NOV, 11): + self[date(year, NOV, 12)] = self.tr("%s (Слободан дан)") % name + + # Good Friday. + self[easter_date + td(days=-2)] = self.tr("Велики петак") + # Easter Saturday. + self[easter_date + td(days=-1)] = self.tr("Велика субота") + # Easter Sunday. + self[easter_date] = self.tr("Васкрс") + # Easter Monday. + self[easter_date + td(days=+1)] = self.tr("Други дан Васкрса") class RS(Serbia): diff --git a/holidays/countries/singapore.py b/holidays/countries/singapore.py index 2dc63ff50..e8c6a9809 100644 --- a/holidays/countries/singapore.py +++ b/holidays/countries/singapore.py @@ -10,13 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from typing import Dict, Iterable, Optional, Tuple, Union from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, SEP, AUG -from holidays.constants import OCT, NOV, DEC, SUN +from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _ChineseLuniSolar, _islamic_to_gre @@ -45,6 +45,7 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: """ A subclass of :py:class:`HolidayBase` representing public holidays in @@ -81,22 +82,31 @@ def __init__( """ self.cnls = _ChineseLuniSolar() - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) def _populate(self, year) -> None: - def _add_holiday(dt: date, hol: str) -> None: - if dt.year == year: - self[dt] = hol + # Implement Section 4(2) of the Holidays Act: + # "if any day specified in the Schedule falls on a Sunday, + # the day next following not being itself a public holiday + # is declared a public holiday in Singapore." + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date) and year >= 1998: + self[hol_date + td(days=days)] = f"{hol_name} (Observed)" super()._populate(year) # New Year's Day - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") # Chinese New Year (two days) hol_date = self.cnls.lunar_n_y_date(year) - self[hol_date] = "Chinese New Year" - self[hol_date + rd(days=+1)] = "Chinese New Year" + _add_with_observed(hol_date, "Chinese New Year", days=+2) + _add_with_observed(hol_date + td(days=+1), "Chinese New Year") # Hari Raya Puasa # aka Eid al-Fitr @@ -130,19 +140,18 @@ def _add_holiday(dt: date, hol: str) -> None: if year in dates_fixed_multiple_obs: for month_day in dates_fixed_multiple_obs[year]: hol_date = date(year, *month_day) - self[hol_date] = "Hari Raya Puasa" + _add_with_observed(hol_date, "Hari Raya Puasa") # Second day of Hari Raya Puasa (up to and including 1968) # Removed since we don't have Hari Raya Puasa dates for the - # the years <= 1968: + # the years <= 1968. else: for hol_date in _islamic_to_gre(year, 10, 1): - self[hol_date] = "Hari Raya Puasa* (*estimated)" + _add_with_observed(hol_date, "Hari Raya Puasa* (*estimated)") # Second day of Hari Raya Puasa (up to and including 1968) if year <= 1968: - _add_holiday( - hol_date + rd(days=+1), - "Second day of Hari Raya Puasa* (*estimated)", - ) + self[ + hol_date + td(days=+1) + ] = "Second day of Hari Raya Puasa* (*estimated)" # Hari Raya Haji # aka Eid al-Adha @@ -176,24 +185,27 @@ def _add_holiday(dt: date, hol: str) -> None: if year in dates_fixed_multiple_obs: for month_day in dates_fixed_multiple_obs[year]: hol_date = date(year, *month_day) - self[hol_date] = "Hari Raya Haji" + if year == 2006: + self[hol_date] = "Hari Raya Haji" + else: + _add_with_observed(hol_date, "Hari Raya Haji") else: for hol_date in _islamic_to_gre(year, 12, 10): - self[hol_date] = "Hari Raya Haji* (*estimated)" + _add_with_observed(hol_date, "Hari Raya Haji* (*estimated)") easter_date = easter(year) # Good Friday - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-2)] = "Good Friday" if year <= 1968: # Holy Saturday - self[easter_date + rd(days=-1)] = "Holy Saturday" + self[easter_date + td(days=-1)] = "Holy Saturday" # Easter Monday - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=+1)] = "Easter Monday" # Labour Day - self[date(year, MAY, 1)] = "Labour Day" + _add_with_observed(date(year, MAY, 1), "Labour Day") # Vesak Day # date of observance is announced yearly @@ -227,13 +239,13 @@ def _add_holiday(dt: date, hol: str) -> None: } if year in dates_fixed_obs: hol_date = date(year, *dates_fixed_obs[year]) - self[hol_date] = "Vesak Day" + _add_with_observed(hol_date, "Vesak Day") else: hol_date = self.cnls.vesak_date(year) - self[hol_date] = "Vesak Day* (*estimated)" + _add_with_observed(hol_date, "Vesak Day* (*estimated)") # National Day - self[date(year, AUG, 9)] = "National Day" + _add_with_observed(date(year, AUG, 9), "National Day") # Deepavali # aka Diwali @@ -265,37 +277,26 @@ def _add_holiday(dt: date, hol: str) -> None: } if year in dates_fixed_obs: hol_date = date(year, *dates_fixed_obs[year]) - self[hol_date] = "Deepavali" + _add_with_observed(hol_date, "Deepavali") else: hol_date = self.cnls.s_diwali_date(year) - self[hol_date] = "Deepavali* (*estimated)" + _add_with_observed(hol_date, "Deepavali* (*estimated)") # Christmas Day - self[date(year, DEC, 25)] = "Christmas Day" + _add_with_observed( + date(year, DEC, 25), "Christmas Day", +2 if year == 2039 else +1 + ) # Boxing day (up to and including 1968) if year <= 1968: self[date(year, DEC, 26)] = "Boxing Day" - # Check for holidays that fall on a Sunday and implement Section 4(2) - # of the Holidays Act: "if any day specified in the Schedule falls on - # a Sunday, the day next following not being itself a public holiday - # is declared a public holiday in Singapore." - if self.observed and year >= 1998: - for (hol_date, hol_name) in list(self.items()): - if hol_date.year == year and hol_date.weekday() == SUN: - in_lieu_date = hol_date + rd(days=+1) - while in_lieu_date.year == year and in_lieu_date in self: - in_lieu_date += rd(days=+1) - _add_holiday(in_lieu_date, f"{hol_name} (Observed)") - # special case (observed from previuos year) if self.observed and year == 2007: self[date(2007, JAN, 2)] = "Hari Raya Haji (Observed)" class SG(Singapore): - # __init__ required for IDE typing and inheritance of docstring. def __init__( self, @@ -305,12 +306,14 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) class SGP(Singapore): - # __init__ required for IDE typing and inheritance of docstring. def __init__( self, @@ -320,5 +323,8 @@ def __init__( subdiv: Optional[str] = None, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> None: - super().__init__(years, expand, observed, subdiv, prov, state) + super().__init__( + years, expand, observed, subdiv, prov, state, language + ) diff --git a/holidays/countries/slovakia.py b/holidays/countries/slovakia.py index bea96ccbb..d24fbdd8d 100644 --- a/holidays/countries/slovakia.py +++ b/holidays/countries/slovakia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAY, JUL, AUG, SEP, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -42,8 +42,8 @@ def _populate(self, year): ) easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Veľký piatok" - self[easter_date + rd(days=+1)] = "Veľkonočný pondelok" + self[easter_date + td(days=-2)] = "Veľký piatok" + self[easter_date + td(days=+1)] = "Veľkonočný pondelok" self[date(year, MAY, 1)] = "Sviatok práce" diff --git a/holidays/countries/slovenia.py b/holidays/countries/slovenia.py index 7a336ccca..8a2dd659e 100644 --- a/holidays/countries/slovenia.py +++ b/holidays/countries/slovenia.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, APR, MAY, JUN, AUG, OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -32,10 +32,10 @@ class Slovenia(HolidayBase): country = "SI" def _populate(self, year): - super()._populate(year) - if year <= 1990: - return + return None + + super()._populate(year) self[date(year, JAN, 1)] = "novo leto" @@ -48,7 +48,7 @@ def _populate(self, year): self[date(year, FEB, 8)] = "Prešernov dan" # Easter monday is the only easter related work-free day - self[easter(year) + rd(days=+1)] = "Velikonočni ponedeljek" + self[easter(year) + td(days=+1)] = "Velikonočni ponedeljek" # Day of uprising against occupation self[date(year, APR, 27)] = "dan upora proti okupatorju" diff --git a/holidays/countries/south_africa.py b/holidays/countries/south_africa.py index 7afac5c6e..e5740e7e1 100644 --- a/holidays/countries/south_africa.py +++ b/holidays/countries/south_africa.py @@ -10,13 +10,14 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, FR from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT -from holidays.constants import NOV, DEC, SUN +from holidays.constants import NOV, DEC from holidays.holiday_base import HolidayBase @@ -52,20 +53,26 @@ class SouthAfrica(HolidayBase): } def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + # As of 1995/1/1, whenever a public holiday falls on a Sunday, + # it rolls over to the following Monday + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date) and year >= 1995: + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" + # Observed since 1910, with a few name changes if year <= 1909: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - if year >= 1980: - name = "Family Day" - else: - name = "Easter Monday" - self[easter_date + rd(days=+1)] = name + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=+1)] = ( + "Family Day" if year >= 1980 else "Easter Monday" + ) if year <= 1951: name = "Dingaan's Day" @@ -75,35 +82,27 @@ def _populate(self, year): name = "Day of the Vow" else: name = "Day of Reconciliation" - self[date(year, DEC, 16)] = name + _add_with_observed(date(year, DEC, 16), name) self[date(year, DEC, 25)] = "Christmas Day" - if year >= 1980: - name = "Day of Goodwill" - else: - name = "Boxing Day" - self[date(year, DEC, 26)] = name + _add_with_observed( + date(year, DEC, 26), + "Day of Goodwill" if year >= 1980 else "Boxing Day", + ) # Observed since 1995/1/1 if year >= 1995: - self[date(year, MAR, 21)] = "Human Rights Day" - self[date(year, APR, 27)] = "Freedom Day" - self[date(year, MAY, 1)] = "Workers' Day" - self[date(year, JUN, 16)] = "Youth Day" - self[date(year, AUG, 9)] = "National Women's Day" - self[date(year, SEP, 24)] = "Heritage Day" - - # As of 1995/1/1, whenever a public holiday falls on a Sunday, - # it rolls over to the following Monday - if self.observed and year >= 1995: - for k, v in list(self.items()): - if k.weekday() != SUN or k.year != year: - continue - dt = k + rd(days=+1) - if dt in self: - continue - self[dt] = v + " (Observed)" + _add_with_observed(date(year, MAR, 21), "Human Rights Day") + _add_with_observed(date(year, APR, 27), "Freedom Day") + _add_with_observed(date(year, MAY, 1), "Workers' Day") + _add_with_observed(date(year, JUN, 16), "Youth Day") + _add_with_observed(date(year, AUG, 9), "National Women's Day") + _add_with_observed(date(year, SEP, 24), "Heritage Day") + + # Special holiday http://tiny.cc/za_y2k + if self.observed and year == 2000: + self[date(2000, JAN, 3)] = "Y2K changeover (Observed)" # Historic public holidays no longer observed if 1952 <= year <= 1973: @@ -113,10 +112,10 @@ def _populate(self, year): if 1987 <= year <= 1989: # observed on first Friday in May - self[(date(year, MAY, 1) + rd(weekday=FR))] = "Workers' Day" + self[date(year, MAY, 1) + rd(weekday=FR)] = "Workers' Day" if year <= 1993: - self[easter_date + rd(days=+40)] = "Ascension Day" + self[easter_date + td(days=+40)] = "Ascension Day" if year <= 1951: self[date(year, MAY, 24)] = "Empire Day" @@ -128,20 +127,18 @@ def _populate(self, year): if 1952 <= year <= 1960: # observed on second Monday in July - self[ - (date(year, JUL, 1) + rd(weekday=MO(+2))) - ] = "Queen's Birthday" + self[date(year, JUL, 1) + rd(weekday=MO(+2))] = "Queen's Birthday" if 1961 <= year <= 1973: self[date(year, JUL, 10)] = "Family Day" if year <= 1951: # observed on first Monday in August - self[(date(year, AUG, 1) + rd(weekday=MO))] = "King's Birthday" + self[date(year, AUG, 1) + rd(weekday=MO)] = "King's Birthday" if 1952 <= year <= 1979: # observed on first Monday in September - self[(date(year, SEP, 1) + rd(weekday=MO))] = "Settlers' Day" + self[date(year, SEP, 1) + rd(weekday=MO)] = "Settlers' Day" if 1952 <= year <= 1993: self[date(year, OCT, 10)] = "Kruger Day" diff --git a/holidays/countries/south_korea.py b/holidays/countries/south_korea.py index 8b10d10f3..85750f74b 100644 --- a/holidays/countries/south_korea.py +++ b/holidays/countries/south_korea.py @@ -12,10 +12,9 @@ import warnings from datetime import date +from datetime import timedelta as td from typing import Tuple -from dateutil.relativedelta import relativedelta as rd - # Installation: pip install korean_lunar_calendar # URL: https://github.com/usingsky/korean_lunar_calendar_py/ from korean_lunar_calendar import KoreanLunarCalendar @@ -68,9 +67,9 @@ def _populate(self, year): dt = self.get_solar_date(year, 1, 1) new_year_date = date(dt.year, dt.month, dt.day) - self[new_year_date + rd(days=-1)] = preceding_day_lunar + self[new_year_date + td(days=-1)] = preceding_day_lunar self[new_year_date] = name - self[new_year_date + rd(days=+1)] = second_day_lunar + self[new_year_date + td(days=+1)] = second_day_lunar if self.observed and year >= 2015: for cur_rd, cur_name in [ @@ -78,7 +77,7 @@ def _populate(self, year): (0, name), (+1, second_day_lunar), ]: - target_date = new_year_date + rd(days=cur_rd) + target_date = new_year_date + td(days=cur_rd) is_alt, alt_date = self.get_next_first_non_holiday( cur_name, target_date ) @@ -168,9 +167,9 @@ def _populate(self, year): dt = self.get_solar_date(year, 8, 15) chuseok_date = date(dt.year, dt.month, dt.day) - self[chuseok_date + rd(days=-1)] = preceding_day_chuseok + self[chuseok_date + td(days=-1)] = preceding_day_chuseok self[chuseok_date] = name - self[chuseok_date + rd(days=+1)] = second_day_chuseok + self[chuseok_date + td(days=+1)] = second_day_chuseok if self.observed and year >= 2014: for cur_rd, cur_name in [ @@ -178,7 +177,7 @@ def _populate(self, year): (0, name), (+1, second_day_chuseok), ]: - target_date = chuseok_date + rd(days=cur_rd) + target_date = chuseok_date + td(days=cur_rd) is_alt, alt_date = self.get_next_first_non_holiday( cur_name, target_date ) @@ -261,15 +260,15 @@ def get_next_first_non_holiday( """ start_value = cur - target_weekday = [SUN] + target_weekday = {SUN} if include_sat: - target_weekday.append(SAT) + target_weekday.add(SAT) check_1 = cur.weekday() in target_weekday # Exclude weekends check_2 = ( cur in self and name != self[cur] ) # Exclude if already a holiday while check_1 or check_2: - cur += rd(days=+1) + cur += td(days=+1) check_1 = cur.weekday() in target_weekday check_2 = cur in self and name != self[cur] diff --git a/holidays/countries/spain.py b/holidays/countries/spain.py index e32ab1a8b..5ab318ae5 100644 --- a/holidays/countries/spain.py +++ b/holidays/countries/spain.py @@ -10,17 +10,22 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC, SUN +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase from holidays.utils import _islamic_to_gre class Spain(HolidayBase): + """ + References: + - https://administracion.gob.es/pag_Home/atencionCiudadana/calendarios.html # noqa: E501 + """ + country = "ES" subdivisions = [ "AN", @@ -45,78 +50,85 @@ class Spain(HolidayBase): ] def _is_observed(self, date_holiday, name_holiday): - if self.observed and date_holiday.weekday() == SUN: - self[date_holiday + rd(days=+1)] = name_holiday + " (Trasladado)" + if self.observed and self._is_sunday(date_holiday): + self[date_holiday + td(days=+1)] = name_holiday + " (Trasladado)" else: self[date_holiday] = name_holiday def _populate(self, year): super()._populate(year) - self._is_observed(date(year, JAN, 1), "Año nuevo") + if year == 2023 and self.subdiv in { + "AN", + "AR", + "AS", + "CL", + "MC", + }: + self._is_observed(date(year, JAN, 1), "Año nuevo") + if year != 2023: + self._is_observed(date(year, JAN, 1), "Año nuevo") self._is_observed(date(year, JAN, 6), "Epifanía del Señor") easter_date = easter(year) - if ( - year < 2015 - and self.subdiv - and self.subdiv - in { - "AR", - "CL", - "CM", - "EX", - "GA", - "MC", - "MD", - "ML", - "NC", - "PV", - "VC", - } - ): + if year < 2015 and self.subdiv in { + "AR", + "CL", + "CM", + "EX", + "GA", + "MC", + "MD", + "ML", + "NC", + "PV", + "VC", + }: self._is_observed(date(year, MAR, 19), "San José") - elif ( - year == 2015 - and self.subdiv - and self.subdiv in {"CM", "MC", "MD", "ML", "NC", "PV", "VC"} - ): + elif year == 2015 and self.subdiv in { + "CM", + "MC", + "MD", + "ML", + "NC", + "PV", + "VC", + }: self._is_observed(date(year, MAR, 19), "San José") - elif ( - year == 2016 - and self.subdiv - and self.subdiv in {"MC", "ML", "PV", "VC"} - ): + elif year == 2016 and self.subdiv in {"MC", "ML", "PV", "VC"}: self._is_observed(date(year, MAR, 19), "San José") elif year == 2017 and self.subdiv in {"PV"}: self._is_observed(date(year, MAR, 19), "San José") - elif ( - 2018 <= year <= 2019 - and self.subdiv - and self.subdiv in {"GA", "MC", "NC", "PV", "VC"} - ): + elif 2018 <= year <= 2019 and self.subdiv in { + "GA", + "MC", + "NC", + "PV", + "VC", + }: self._is_observed(date(year, MAR, 19), "San José") - elif ( - 2020 <= year <= 2021 - and self.subdiv - and self.subdiv in {"CM", "GA", "MC", "NC", "PV", "VC"} - ): + elif 2020 <= year <= 2021 and self.subdiv in { + "CM", + "GA", + "MC", + "NC", + "PV", + "VC", + }: + self._is_observed(date(year, MAR, 19), "San José") + elif year == 2022 and self.subdiv and self.subdiv == "VC": self._is_observed(date(year, MAR, 19), "San José") - elif year >= 2022 and self.subdiv and self.subdiv == "VC": + elif year == 2023 and self.subdiv and self.subdiv == "MD": self._is_observed(date(year, MAR, 19), "San José") - if year != 2022 and self.subdiv not in {"CT", "VC"}: - self[easter_date + rd(days=-3)] = "Jueves Santo" + if year <= 2022 and self.subdiv not in {"CT", "VC"}: + self[easter_date + td(days=-3)] = "Jueves Santo" elif year == 2022 and self.subdiv and self.subdiv not in {"CT"}: - self[easter_date + rd(days=-3)] = "Jueves Santo" - self[easter_date + rd(days=-2)] = "Viernes Santo" - if ( - 2022 == year - and self.subdiv - and self.subdiv in {"CT", "IB", "NC", "PV", "RI", "VC"} - ): - self[easter_date + rd(days=+1)] = "Lunes de Pascua" - elif 2022 > year and self.subdiv in { + self[easter_date + td(days=-3)] = "Jueves Santo" + elif year >= 2023: + self[easter_date + td(days=-3)] = "Jueves Santo" + self[easter_date + td(days=-2)] = "Viernes Santo" + if year < 2022 and self.subdiv in { "CM", "CT", "IB", @@ -124,11 +136,17 @@ def _populate(self, year): "PV", "VC", }: - self[easter(year) + rd(days=+1)] = "Lunes de Pascua" - - if 2022 != year: - self._is_observed(date(year, MAY, 1), "Día del Trabajador") - elif 2022 == year and self.subdiv in { + self[easter(year) + td(days=+1)] = "Lunes de Pascua" + elif year >= 2022 and self.subdiv in { + "CT", + "IB", + "NC", + "PV", + "RI", + "VC", + }: + self[easter(year) + td(days=+1)] = "Lunes de Pascua" + if year == 2022 and self.subdiv in { "AN", "AR", "AS", @@ -137,7 +155,11 @@ def _populate(self, year): "MC", }: self._is_observed(date(year, MAY, 1), "Día del Trabajador") - if self.subdiv in {"CT", "GA", "VC"}: + if year != 2022: + self._is_observed(date(year, MAY, 1), "Día del Trabajador") + if self.subdiv in {"CT", "VC"} or ( + year != 2023 and self.subdiv == "GA" + ): self._is_observed(date(year, JUN, 24), "San Juan") self._is_observed(date(year, AUG, 15), "Asunción de la Virgen") self._is_observed(date(year, OCT, 12), "Día de la Hispanidad") @@ -146,12 +168,10 @@ def _populate(self, year): date(year, DEC, 6), "Día de la Constitución Española" ) self._is_observed(date(year, DEC, 8), "La Inmaculada Concepción") - if year != 2022: + if year == 2022 and self.subdiv not in {"CE", "GA", "PV", "VC"}: + self._is_observed(date(year, DEC, 25), "Navidad") + elif year != 2022: self._is_observed(date(year, DEC, 25), "Navidad") - elif year == 2022 and self.subdiv not in {"CE", "GA", "PV", "VC"}: - self._is_observed(date(year, DEC, 26), "Navidad (Trasladado)") - if self.subdiv in {"CT", "IB"}: - self._is_observed(date(year, DEC, 26), "San Esteban") # Provinces festive day if self.subdiv == "AN": @@ -171,24 +191,35 @@ def _populate(self, year): self._is_observed( date(year, SEP, 2), "Día de la Ciudad Autónoma de Ceuta" ) - if year >= 2022: - self._is_observed(_islamic_to_gre(year, 12, 10)[0], "Eid Adha") + if year == 2022: + for dt in _islamic_to_gre(year, 12, 10): + self._is_observed(dt, "Eid al-Adha") + elif year == 2023: + for dt in _islamic_to_gre(year, 12, 10): + self._is_observed(dt + td(days=+1), "Eid al-Adha") elif self.subdiv == "CM": if year >= 2022: - self._is_observed(date(year, JUN, 16), "Corpus Christi") + self._is_observed(easter_date + td(days=+60), "Corpus Christi") self._is_observed(date(year, MAY, 31), "Día de Castilla La Mancha") elif self.subdiv == "CN": self._is_observed(date(year, MAY, 30), "Día de Canarias") elif self.subdiv == "CL": self._is_observed(date(year, APR, 23), "Día de Castilla y Leon") + if year == 2023: + self._is_observed( + date(year, JUL, 25), "Día de Santiago Apóstol" + ) elif self.subdiv == "CT": - if year >= 2022: + if year == 2022: self._is_observed( date(year, JUN, 6), "Día de la Pascua Granada" ) self._is_observed(date(year, SEP, 11), "Día Nacional de Catalunya") + self._is_observed(date(year, DEC, 26), "San Esteban") elif self.subdiv == "EX": self._is_observed(date(year, SEP, 8), "Día de Extremadura") + if year == 2023: + self._is_observed(date(year, FEB, 21), "Carnaval") elif self.subdiv == "GA": if year >= 2022: self._is_observed( @@ -197,9 +228,11 @@ def _populate(self, year): self._is_observed(date(year, JUL, 25), "Día Nacional de Galicia") elif self.subdiv == "IB": self._is_observed(date(year, MAR, 1), "Día de las Islas Baleares") + if year <= 2020: + self._is_observed(date(year, DEC, 26), "San Esteban") elif self.subdiv == "MD": self._is_observed(date(year, MAY, 2), "Día de Comunidad de Madrid") - if year >= 2022: + if year == 2022: self._is_observed( date(year, JUL, 25), "Día de Santiago Apóstol" ) @@ -209,32 +242,26 @@ def _populate(self, year): self._is_observed(date(year, SEP, 8), "Vírgen de la victoria") self._is_observed(date(year, SEP, 17), "Día de Melilla") if year == 2022: - self._is_observed( - _islamic_to_gre(year, 10, 1)[0] + rd(days=+1), - "Aid Al-Fitr", - ) - self._is_observed( - _islamic_to_gre(year, 12, 10)[0] + rd(days=+2), - "Aid Al-Adha", - ) - else: - self._is_observed( - _islamic_to_gre(year, 10, 1)[0], "Aid Al-Fitr" - ) - self._is_observed( - _islamic_to_gre(year, 12, 10)[0], "Aid Al-Adha" - ) + for dt in _islamic_to_gre(year, 10, 1): + self._is_observed(dt + td(days=+1), "Eid al-Fitr") + for dt in _islamic_to_gre(year, 12, 10): + self._is_observed(dt + td(days=+2), "Eid al-Adha") + elif year == 2023: + for dt in _islamic_to_gre(year, 10, 1): + self._is_observed(dt, "Eid al-Fitr") + for dt in _islamic_to_gre(year, 12, 10): + self._is_observed(dt + td(days=+1), "Eid al-Adha") elif self.subdiv == "NC": if year >= 2022: self._is_observed( date(year, JUL, 25), "Día de Santiago Apóstol" ) - self._is_observed(date(year, SEP, 27), "Día de Navarra") elif self.subdiv == "PV": if year >= 2022: self._is_observed( date(year, JUL, 25), "Día de Santiago Apóstol" ) + if year < 2023: self._is_observed(date(year, SEP, 6), "Día de Elcano") if 2011 <= year <= 2013: self._is_observed(date(year, OCT, 25), "Día del País Vasco") diff --git a/holidays/countries/sweden.py b/holidays/countries/sweden.py index e61d3a16f..e7fc8d52d 100644 --- a/holidays/countries/sweden.py +++ b/holidays/countries/sweden.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date, datetime +from datetime import timedelta as td from dateutil import rrule from dateutil.easter import easter @@ -79,13 +80,13 @@ def _populate(self, year): # ========= Moving holidays ========= easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Långfredagen" + self[easter_date + td(days=-2)] = "Långfredagen" self[easter_date] = "Påskdagen" - self[easter_date + rd(days=+1)] = "Annandag påsk" - self[easter_date + rd(days=+39)] = "Kristi himmelsfärdsdag" - self[easter_date + rd(days=+49)] = "Pingstdagen" + self[easter_date + td(days=+1)] = "Annandag påsk" + self[easter_date + td(days=+39)] = "Kristi himmelsfärdsdag" + self[easter_date + td(days=+49)] = "Pingstdagen" if year <= 2004: - self[easter_date + rd(days=+50)] = "Annandag pingst" + self[easter_date + td(days=+50)] = "Annandag pingst" # Source: # https://sv.wikipedia.org/wiki/Midsommarafton diff --git a/holidays/countries/switzerland.py b/holidays/countries/switzerland.py index f7b6606c4..f54147387 100644 --- a/holidays/countries/switzerland.py +++ b/holidays/countries/switzerland.py @@ -10,6 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import TH, SU @@ -88,8 +89,8 @@ def _populate(self, year): # Näfelser Fahrt (first Thursday in April but not in Holy Week) if self.subdiv == "GL" and year >= 1835: dt = date(year, APR, 1) + rd(weekday=TH) - if dt == easter_date + rd(days=-3): - dt += rd(days=+7) + if dt == easter_date + td(days=-3): + dt += td(days=+7) self[dt] = "Näfelser Fahrt" # it's a Holiday on a Sunday @@ -97,8 +98,8 @@ def _populate(self, year): # VS don't have easter if self.subdiv != "VS": - self[easter_date + rd(days=-2)] = "Karfreitag" - self[easter_date + rd(days=+1)] = "Ostermontag" + self[easter_date + td(days=-2)] = "Karfreitag" + self[easter_date + td(days=+1)] = "Ostermontag" if self.subdiv in { "BL", @@ -113,12 +114,12 @@ def _populate(self, year): }: self[date(year, MAY, 1)] = "Tag der Arbeit" - self[easter_date + rd(days=+39)] = "Auffahrt" + self[easter_date + td(days=+39)] = "Auffahrt" # it's a Holiday on a Sunday - self[easter_date + rd(days=+49)] = "Pfingsten" + self[easter_date + td(days=+49)] = "Pfingsten" - self[easter_date + rd(days=+50)] = "Pfingstmontag" + self[easter_date + td(days=+50)] = "Pfingstmontag" if self.subdiv in { "AI", @@ -132,7 +133,7 @@ def _populate(self, year): "VS", "ZG", }: - self[easter_date + rd(days=+60)] = "Fronleichnam" + self[easter_date + td(days=+60)] = "Fronleichnam" if self.subdiv == "JU": self[date(year, JUN, 23)] = "Fest der Unabhängigkeit" @@ -159,12 +160,12 @@ def _populate(self, year): if self.subdiv == "VD": # Monday after the third Sunday of September - dt = date(year, SEP, 1) + rd(weekday=SU(+3)) + rd(days=+1) + dt = date(year, SEP, 1) + rd(weekday=SU(+3)) + td(days=+1) self[dt] = "Lundi du Jeûne" if self.subdiv == "GE": # Thursday after the first Sunday of September - dt = date(year, SEP, 1) + rd(weekday=SU) + rd(days=+4) + dt = date(year, SEP, 1) + rd(weekday=SU) + td(days=+4) self[dt] = "Jeûne genevois" if self.subdiv == "OW": diff --git a/holidays/countries/taiwan.py b/holidays/countries/taiwan.py index 31eaa24f9..c910ff3ad 100644 --- a/holidays/countries/taiwan.py +++ b/holidays/countries/taiwan.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, FEB, APR, OCT from holidays.holiday_base import HolidayBase @@ -38,10 +37,10 @@ def _populate(self, year): date(year, JAN, 1) ] = "Founding of the Republic of China (New Year's Day)" hol_date = self.cnls.lunar_n_y_date(year) - self[hol_date + rd(days=-1)] = "Chinese New Year's Eve" + self[hol_date + td(days=-1)] = "Chinese New Year's Eve" self[hol_date] = "Spring Festival" - self[hol_date + rd(days=+1)] = "Spring Festival" - self[hol_date + rd(days=+2)] = "Spring Festival" + self[hol_date + td(days=+1)] = "Spring Festival" + self[hol_date + td(days=+2)] = "Spring Festival" self[date(year, APR, 4)] = "Children's Day" self[self.cnls.lunar_to_gre(year, 5, 5)] = "Dragon Boat Festival" self[self.cnls.lunar_to_gre(year, 8, 15)] = "Mid-Autumn Festival" @@ -51,8 +50,8 @@ def _populate(self, year): self[date(year, FEB, 28)] = "Peace Memorial Day" if year == 2021: hol_date = self.cnls.lunar_n_y_date(year) - self[hol_date + rd(days=+3)] = "Spring Festival" - self[hol_date + rd(days=+4)] = "Spring Festival" + self[hol_date + td(days=+3)] = "Spring Festival" + self[hol_date + td(days=+4)] = "Spring Festival" class TW(Taiwan): diff --git a/holidays/countries/thailand.py b/holidays/countries/thailand.py index 35bf901cf..dec4220a2 100644 --- a/holidays/countries/thailand.py +++ b/holidays/countries/thailand.py @@ -10,159 +10,633 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td -from dateutil.relativedelta import relativedelta as rd - -from holidays.constants import FEB, MAR, APR, MAY, JUN, JUL, AUG, OCT, DEC, SAT +from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase -from holidays.utils import _ChineseLuniSolar +from holidays.utils import _ThaiLuniSolar class Thailand(HolidayBase): """ - Thailand holidays. + A subclass of :py:class:`HolidayBase` representing public holidays + in Thailand. (Based on South Korean and Singaporean Implementation) + References: - - https://en.wikipedia.org/wiki/Public_holidays_in_Thailand + + - Based on: https://en.wikipedia.org/wiki/Public_holidays_in_Thailand + - Checked with: (Bank of Thailand 's wbm) http://tiny.cc/wa_bot_2023 + - [In Lieus] + (isranews.org 's wbm) http://tiny.cc/wa_isranews_inlieu_hist + https://resolution.soc.go.th/?prep_id=99159317 + https://resolution.soc.go.th/?prep_id=196007 + https://github.com/dr-prodigy/python-holidays/pull/929 + - [New Year's Day] + (wikisource.org 's wbm) http://tiny.cc/wa_wiki_thai_newyear_2483 + - [Chakri Memorial Day] + (ocac.got.th 's wbm) http://tiny.cc/wa_ocac_chakri + - [Songkran Festival] + (museumsiam.org 's wbm) http://tiny.cc/wa_museumsiam_songkran + https://resolution.soc.go.th/?prep_id=123659 + - [National Labour Day] + https://www.thairath.co.th/lifestyle/culture/1832869 + - [National Day (24 June: Defunct)] + (Ministry of Culture 's wbm) http://tiny.cc/wa_mincul_nat_day + - [Coronation Day] + https://www.matichon.co.th/politics/news_526200 + https://workpointtoday.com/news1-5/ + - [HM Queen Suthida's Birthday] + https://www.thairath.co.th/news/politic/1567418 + - [HM Maha Vajiralongkorn's Birthday] + https://www.matichon.co.th/politics/news_526200 + - [HM Queen Sirikit the Queen Mother's Birthday] + https://hilight.kapook.com/view/14164 + - [National Mother's Day] + https://www.brh.go.th/index.php/2019-02-27-04-11-52/542-12-2564 + - [HM King Bhumibol Adulyadej Memorial Day] + https://www.matichon.co.th/politics/news_526200 + - [Chulalongkorn Memorial Day] + https://th.wikipedia.org/wiki/วันปิยมหาราช + - [HM King Bhumibol Adulyadej's Birthday] + (Ministry of Culture 's wbm) http://tiny.cc/wa_mincul_nat_day + https://hilight.kapook.com/view/148862 + - [National Father's Day] + https://www.brh.go.th/index.php/2019-02-27-04-12-21/594-5-5 + - [Constitution Day] + https://hilight.kapook.com/view/18208 + (Bank of Thailand 's wbm) http://tiny.cc/wa_bot_1992 + https://www.myhora.com/ปฏิทิน/ปฏิทิน-พ.ศ.2475.aspx + - [New Year's Eve] + (Bank of Thailand 's wbm) http://tiny.cc/wa_bot_1992 + https://resolution.soc.go.th/?prep_id=205799 + https://resolution.soc.go.th/?prep_id=210744 + - [Makha Bucha] + https://www.onab.go.th/th/content/category/detail/id/73/iid/3403 + - [Visakha Bucha] + https://www.onab.go.th/th/content/category/detail/id/73/iid/3401 + - [Asarnha Bucha] + https://www.onab.go.th/th/content/category/detail/id/73/iid/3397 + - [Buddhist Lent Day] + https://www.onab.go.th/th/content/category/detail/id/73/iid/3395 + - [Royal Ploughing Ceremony] + https://en.wikipedia.org/wiki/Royal_Ploughing_Ceremony + https://www.lib.ru.ac.th/journal/may/may_phauchmongkol.html + https://www.myhora.com/ปฏิทิน/ปฏิทิน-พ.ศ.2540.aspx + + + Limitations: + + - This is only 100% accurate for 1997-2023; any future dates are up to the + Royal Thai Government Gazette which updates on a year-by-year basis. + + - Approx. date only goes as far back as 1941 (B.E. 2484) as the Thai + calendar for B.E. 2483 as we only have nine months from switching + New Year Date (April 1st to January 1st). + + - Thai Lunar Calendar Holidays only work from 1941 (B.E. 2484) onwards + until 2057 (B.E. 2600) as we only have Thai year-type data for + cross-checking until then. + + - Royal Ploughing Ceremony Day is date is announced on an annual basis + by the Court Astrologers, thus need an annual update to the library here + + - This doesn't cover Thai regional public holidays yet, only stubs added + + + Country created by: `arkid15r `__ + + Country maintained by: `PPsyrius `__ """ country = "TH" - def __init__(self, **kwargs): - self.cnls = _ChineseLuniSolar() - HolidayBase.__init__(self, **kwargs) + # วันหยุดพิเศษ (เพิ่มเติม) - see Bank of Thailand's DB for Cross-Check + thai_special_in_lieu_holidays = "Special In Lieu Holiday" + thai_election = "Thai Election Day" + thai_election_in_lieu = "Thai Election Day (in lieu)" + thai_bridge_public_holiday = "Bridge Public Holiday" + + # Special Cases + rama_ix_golden_jubilee = "HM King Bhumibol Adulyadej's Golden Jubilee" + rama_ix_sixty_accession = ( + "HM King Bhumibol Adulyadej's 60th Anniversary of Accession Event" + ) + thai_military_emergency_lockdown = ( + "Emergency Lockdown (Thai Military Coup d'état)" + ) + thai_political_emergency_lockdown = ( + "Emergency Lockdown (Thai Political Unrest)" + ) + thai_flood_2011_emergency_lockdown = ( + "Emergency Lockdown (2011 Thailand Floods)" + ) + rama_ix_mourning = "Day of Mourning for HM King Bhumibol Adulyadej" + rama_ix_cremation = "HM King Bhumibol Adulyadej's Royal Cremation Ceremony" + rama_x_coronation_celebrations = ( + "HM King Maha Vajiralongkorn's Coronation Celebrations" + ) + songkran_festival_in_lieu_covid = "Songkran Festival (in lieu)" + + special_holidays = { + # 1992-1994 (include In Lieus, Checked with Bank of Thailand Data) + 1992: ( + (MAY, 18, thai_special_in_lieu_holidays), + (DEC, 7, thai_special_in_lieu_holidays), + ), + 1993: ( + (MAR, 8, thai_special_in_lieu_holidays), + (MAY, 3, thai_special_in_lieu_holidays), + (OCT, 25, thai_special_in_lieu_holidays), + (DEC, 6, thai_special_in_lieu_holidays), + ), + 1994: ( + (JAN, 3, thai_special_in_lieu_holidays), + (MAY, 2, thai_special_in_lieu_holidays), + (JUL, 25, thai_special_in_lieu_holidays), + (OCT, 24, thai_special_in_lieu_holidays), + (DEC, 12, thai_special_in_lieu_holidays), + ), + # 1995-1997 (Bank of Thailand Data) + 1996: ((JUN, 10, rama_ix_golden_jubilee),), + # 1998-2000 (include In Lieus, Checked with Bank of Thailand Data) + 1998: ( + (MAY, 11, thai_special_in_lieu_holidays), + (DEC, 7, thai_special_in_lieu_holidays), + ), + 1999: ( + (MAY, 3, thai_special_in_lieu_holidays), + (MAY, 31, thai_special_in_lieu_holidays), + (OCT, 25, thai_special_in_lieu_holidays), + (DEC, 6, thai_special_in_lieu_holidays), + ), + 2000: ( + (JAN, 3, thai_special_in_lieu_holidays), + (FEB, 21, thai_special_in_lieu_holidays), + (AUG, 14, thai_special_in_lieu_holidays), + (DEC, 11, thai_special_in_lieu_holidays), + (DEC, 29, thai_election), + ), + # From 2001 Onwards (Checked with Bank of Thailand Data) + 2006: ( + (APR, 19, thai_election), + (JUN, 9, rama_ix_sixty_accession), + (JUN, 12, rama_ix_sixty_accession), + (JUN, 13, rama_ix_sixty_accession), + (SEP, 20, thai_military_emergency_lockdown), + ), + 2007: ((DEC, 24, thai_election_in_lieu),), + 2009: ( + (JAN, 2, thai_bridge_public_holiday), + (APR, 10, thai_political_emergency_lockdown), + (APR, 16, thai_political_emergency_lockdown), + (APR, 17, thai_political_emergency_lockdown), + (JUL, 6, thai_bridge_public_holiday), + ), + 2010: ( + (MAY, 20, thai_bridge_public_holiday), + (MAY, 21, thai_bridge_public_holiday), + (AUG, 13, thai_bridge_public_holiday), + ), + 2011: ( + (MAY, 16, thai_bridge_public_holiday), + (OCT, 27, thai_flood_2011_emergency_lockdown), + (OCT, 28, thai_flood_2011_emergency_lockdown), + (OCT, 31, thai_flood_2011_emergency_lockdown), + ), + 2012: ((APR, 9, thai_bridge_public_holiday),), + 2013: ((DEC, 30, thai_bridge_public_holiday),), + 2014: ((AUG, 11, thai_bridge_public_holiday),), + 2015: ( + (JAN, 2, thai_bridge_public_holiday), + (MAY, 4, thai_bridge_public_holiday), + ), + 2016: ( + (MAY, 6, thai_bridge_public_holiday), + (JUL, 18, thai_bridge_public_holiday), + (OCT, 14, rama_ix_mourning), + ), + 2017: ((OCT, 26, rama_ix_cremation),), + 2019: ((MAY, 6, rama_x_coronation_celebrations),), + 2020: ( + (JUL, 27, songkran_festival_in_lieu_covid), + (SEP, 4, songkran_festival_in_lieu_covid), + (SEP, 7, songkran_festival_in_lieu_covid), + (NOV, 19, thai_bridge_public_holiday), + (NOV, 20, thai_bridge_public_holiday), + (DEC, 11, thai_bridge_public_holiday), + ), + 2021: ( + (FEB, 12, thai_bridge_public_holiday), + (APR, 12, thai_bridge_public_holiday), + (SEP, 24, thai_bridge_public_holiday), + ), + 2022: ( + (JUL, 15, thai_bridge_public_holiday), + (JUL, 29, thai_bridge_public_holiday), + (OCT, 14, thai_bridge_public_holiday), + (DEC, 30, thai_bridge_public_holiday), + ), + 2023: ((MAY, 5, thai_bridge_public_holiday),), + } + + def __init__(self, **kwargs) -> None: + self.thls = _ThaiLuniSolar() + super().__init__(**kwargs) def _populate(self, year): - def add_holiday(dt, holiday_name): - if dt.year != year: - return - + # Due to Thai Calendar Migration, this is capped off at 1941 + # But certain holidays were implemented before 1941 + if year <= 1940: + return None + + def _add_with_observed(dt, holiday_name) -> None: + # TODO: add `if dt.year == year` check for Islamic holidays + # which can straddle across gregorian years in southern region. self[dt] = holiday_name - if self.observed and self._is_weekend(dt): - in_lieu = dt + rd(days=2 if dt.weekday() == SAT else 1) - while in_lieu.year == year and in_lieu in self: - in_lieu += rd(days=+1) - add_holiday(in_lieu, f"{holiday_name} (in lieu)") + """ + !!! If Public Holiday falls on weekends, (in lieu) on workday !!! + Despite the wording, this usually only applies to Monday only for + holidays, consecutive holidays all have their own special in lieu + declared separately. + + Data from 1992-1994 and 1998-2000 are declared discretely in + special_holidays declarations above. + + Applied Automatically for Monday if on Weekends: 1961-1973 + **NOTE: No New Year's Eve (in lieu) for this period + No In Lieu days available: 1974-1988 + Case-by-Case application for Workday if on Weekends: 1989-1994 + Applied Automatically for Workday if on Weekends: 1995-1997 + Case-by-Case application for Workday if on Weekends: 1998-2000 + Applied Automatically for Workday if on Weekends: 2001-Present + """ + if 1961 <= year <= 1973 or 1995 <= year <= 1997 or year >= 2001: + if self.observed and self._is_weekend(dt): + in_lieu = dt + td(days=+2 if self._is_saturday(dt) else +1) + self[in_lieu] = f"{holiday_name} (in lieu)" super()._populate(year) - # New Year's Day. - add_holiday(date(year, 1, 1), "New Year's Day") - - # Magha Pujab. - # TODO(ark): research Buddhist calendar options. - magha_puja = { - 2016: (FEB, 22), - 2017: (FEB, 11), - 2018: (MAR, 1), - 2019: (FEB, 19), - 2020: (FEB, 26), - 2021: (FEB, 26), - 2022: (FEB, 16), - 2023: (MAR, 6), - } - if year in magha_puja: - add_holiday(date(year, *magha_puja[year]), "Makha Bucha") - - # Chakri Memorial Day. - add_holiday(date(year, APR, 6), "Chakri Memorial Day") - - # Songkran Festival. + ######################## + # + # FIXED DATED HOLIDAYS + # + ######################## + + # !!! New Year's Day !!! + # วันขึ้นปีใหม่ + # Status: In-Use + # Starts in the present form in 1941 (B.E. 2484) + # TODO: Add check for 1941 if we support earlier dates. + + _add_with_observed(date(year, JAN, 1), "New Year's Day") + + # !!! New Year's Eve (in lieu) !!! + # วันหยุดชดเชยวันสิ้นปี + # Status: In-Use + # Added separately from New Year's Eve itself so that it would't + # go over the next year + # - CASE 1: SAT-SUN -> 1 in-lieu on TUE + # - CASE 2: SUN-MON -> 1 in-lieu on TUE + # See in lieu logic in `_add_with_observed(dt, holiday_name)` + new_years_eve_in_lieu = "New Year's Eve (in lieu)" + + if self.observed and (1995 <= year <= 1997 or year >= 2001): + if self._is_saturday(date(year - 1, DEC, 31)): + self[date(year, JAN, 3)] = new_years_eve_in_lieu + elif self._is_sunday(date(year - 1, DEC, 31)): + self[date(year, JAN, 2)] = new_years_eve_in_lieu + + # !!! Chakri Memorial Day !!! + # วันจักรี + # Status: In-Use + # Starts in present form in 1918 (B.E. 2461) + # TODO: Add check for 1918 if we support earlier dates. + + _add_with_observed(date(year, APR, 6), "Chakri Memorial Day") + + # !!! Songkran Festival !!! + # วันสงกรานต์ + # Status: In-Use + # Used to be April 1st as Thai New Year Day + # Initially abandoned in 1941 (B.E. 2484), declared again as + # public holidays in 1948 (2491 B.E) + # - 1948-1953, celebrated on Apr 13-15 + # - 1954-1956, abandoned as a public holiday + # - 1957-1988, only celebrated on Apr 13 + # - 1989-1997, celebrated on Apr 12-14 + # - 1998-Present, celebrated on Apr 13-15 + # (Except for 2020 due to Covid-19 outbreaks) + # This has its own in-lieu trigger songkran_festival = "Songkran Festival" - add_holiday(date(year, APR, 13), songkran_festival) - add_holiday(date(year, APR, 14), songkran_festival) - add_holiday(date(year, APR, 15), songkran_festival) - - # Labour day. - add_holiday(date(year, MAY, 1), "Labour Day") - # Buddha's Birthday. - add_holiday(self.cnls.vesak_may_date(year), "Buddha's Birthday") - - # Coronation Day. - if year <= 2016: - add_holiday(date(year, MAY, 5), "Coronation Day") + if 1948 <= year <= 1953: + self[date(year, APR, 13)] = songkran_festival + self[date(year, APR, 14)] = songkran_festival + self[date(year, APR, 15)] = songkran_festival + elif 1957 <= year <= 1988: + _add_with_observed(date(year, APR, 13), songkran_festival) + elif 1989 <= year <= 1997: + self[date(year, APR, 12)] = songkran_festival + self[date(year, APR, 13)] = songkran_festival + self[date(year, APR, 14)] = songkran_festival + elif year >= 1998 and year != 2020: + self[date(year, APR, 13)] = songkran_festival + self[date(year, APR, 14)] = songkran_festival + self[date(year, APR, 15)] = songkran_festival + + # !!! Songkran Festival (in lieu) !!! + # วันหยุดชดเชยวันสงกรานต์ + # If Songkran happened to be held on the weekends, only one in-lieu + # public holiday is added, No in lieus for SUN-MON-TUE case + # - CASE 1: THU-FRI-SAT -> 1 in-lieu on MON + # - CASE 2: FRI-SAT-SUN -> 1 in-lieu on MON + # - CASE 3: SAT-SUN-MON -> 1 in-lieu on TUE + # See in lieu logic in `_add_with_observed(dt, holiday_name)` + # Status: In Use + + songkran_festival_in_lieu = "Songkran Festival (in lieu)" + + if self.observed and (1995 <= year <= 1997 or year >= 2001): + dt = date(year, APR, 15) if year >= 2001 else date(year, APR, 14) + + if self._is_saturday(dt): + self[dt + td(days=+2)] = songkran_festival_in_lieu + elif self._is_sunday(dt): + self[dt + td(days=+1)] = songkran_festival_in_lieu + elif self._is_monday(dt): + self[dt + td(days=+1)] = songkran_festival_in_lieu + + # !!! National Labour day !!! + # วันแรงงานแห่งชาติ + # Status: In-Use + # Starts in the present form in 1974 (B.E. 2517) + # Does existed officially since 1956 (B.E. 2499), + # but wasn't a public holiday until then + # *** NOTE: only observed by financial and private sectors + + if year >= 1974: + _add_with_observed(date(year, MAY, 1), "National Labour Day") + + # !!! National Day (24 June) !!! + # วันชาติ + # Status: Defunct (Historical) + # Starts in 1939 (B.E. 2482) by Plaek Phibunsongkhram + # Replaced by Rama IX's birthday in 1960 (B.E. 2503) by Sarit Thanarat + # TODO: Add check for 1939 if we support earlier dates. + + if year <= 1959: + _add_with_observed(date(year, JUN, 24), "National Day") + + # !!! Coronation Day !!! + # วันฉัตรมงคล + # Starts in 1958 (B.E. 2501) for Rama IX's Coronation: May 5th + # No celebration in 2017-2019 (B.E 2560-2562) + # Reestablished with Rama X's Coronation in 2020: May 4th + coronation_day = "Coronation Day" + + if 1958 <= year <= 2016: + _add_with_observed(date(year, MAY, 5), coronation_day) elif year >= 2020: - add_holiday(date(year, MAY, 4), "Coronation Day") - - # Queen's Birthday. - add_holiday(date(year, JUN, 3), "Queen Suthida's Birthday") - - # King's Birthday. - add_holiday(date(year, JUL, 28), "King's Birthday") - - # Asalha Puja. - asalha_puja = { - 2006: (JUL, 11), - 2007: (JUN, 30), - 2008: (JUL, 18), - 2009: (JUL, 7), - 2010: (JUL, 25), - 2011: (JUL, 15), - 2012: (AUG, 2), - 2013: (JUL, 30), - 2014: (JUL, 13), - 2015: (JUL, 30), - 2016: (JUL, 15), - 2017: (JUL, 9), - 2018: (JUL, 29), - 2019: (JUL, 16), - 2020: (JUL, 5), - 2021: (JUL, 24), - 2022: (JUL, 13), - 2023: (JUL, 3), - 2024: (JUL, 21), - 2025: (JUL, 10), - } - if year in asalha_puja: - add_holiday(date(year, *asalha_puja[year]), "Asalha Puja") - - # Beginning of Vassa. - vassa = { - 2006: (JUL, 12), - 2007: (JUL, 31), - 2008: (JUL, 19), - 2009: (JUL, 8), - 2010: (JUL, 27), - 2011: (JUL, 16), - 2012: (AUG, 3), - 2013: (JUL, 23), - 2014: (JUL, 13), - 2015: (AUG, 1), - 2016: (JUL, 20), - 2017: (JUL, 9), - 2018: (JUL, 28), - 2019: (JUL, 17), - 2020: (JUL, 6), - 2021: (JUL, 25), - 2022: (JUL, 14), - 2023: (AUG, 2), - 2024: (JUL, 21), - 2025: (JUL, 23), + _add_with_observed(date(year, MAY, 4), coronation_day) + + # !!! HM Queen Suthida's Birthday !!! + # วันเฉลิมพระชนมพรรษา พระราชินี + # Status: In-Use + # Starts in 2019 (B.E. 2562) + + if year >= 2019: + _add_with_observed( + date(year, JUN, 3), "HM Queen Suthida's Birthday" + ) + + # !!! HM King Maha Vajiralongkorn's Birthday !!! + # วันเฉลิมพระชนมพรรษา รัชกาลที่ 10 + # Status: In-Use + # Started in 2017 (B.E 2560) + + if year >= 2017: + _add_with_observed( + date(year, JUL, 28), "HM King Maha Vajiralongkorn's Birthday" + ) + + # !!! HM Queen Sirikit the Queen Mother's Birthday !!! + # วันเฉลิมพระชนมพรรษา พระบรมราชินีนาถ ( 1976-2017), + # วันเฉลิมพระชนมพรรษา พระบรมราชชนนีพันปีหลวง (2017-Present) + # Status: In-Use + # Started in 1976 (B.E. 2519) alongside Mother's Day + # Initial celebration as HM Queen Sirikit's Birthday + # Now acts as the Queen Mother from 2017 onwards. + + if 1976 <= year <= 2016: + _add_with_observed( + date(year, AUG, 12), "HM Queen Sirikit's Birthday" + ) + elif year >= 2017: + _add_with_observed( + date(year, AUG, 12), + "HM Queen Sirikit The Queen Mother's Birthday", + ) + + # !!! National Mother's Day !!! + # วันแม่แห่งชาติ + # Status: In-Use + # Started 1950 (B.E 2493) initially as April 15 and cancelled in + # 1958 (B.E 2501) when the Min. of Culture was abolished. + # Restarts again in 1976 (B.E. 2519) on Queen Sirikit's Birthday + # (August 12) and stay that way from that point onwards. + thai_mothers_day = "National Mother's Day" + + if 1950 <= year <= 1957: + _add_with_observed(date(year, APR, 15), thai_mothers_day) + elif year >= 1976: + _add_with_observed(date(year, AUG, 12), thai_mothers_day) + + # !!! Anniversary for the Death of King Bhumibol Adulyadej !!! + # วันคล้ายวันสวรรคตพระบาทสมเด็จพระปรมินทร มหาภูมิพลอดุลยเดช บรมนาถบพิตร + # Status: In-Use + # Started in 2017 (B.E 2560) + + if year >= 2017: + _add_with_observed( + date(year, OCT, 13), "HM King Bhumibol Adulyadej Memorial Day" + ) + + # !!! Chulalongkorn Memorial Day !!! + # วันปิยมหาราช + # Status: In-Use + # Started in 1911 (B.E. 2454) + # TODO: Add check for 1911 if we support earlier dates. + + _add_with_observed(date(year, OCT, 23), "Chulalongkorn Memorial Day") + + # !!! HM King Bhumibol Adulyadej's Birthday Anniversary !!! + # วันเฉลิมพระชนมพรรษา รัชกาลที่ 9 (1960-2016), + # วันคล้ายยวันเฉลิมพระชนมพรรษา รัชกาลที่ 9 (2017-Present) + # Status: In-Use + # Replaced Nataion Day (26 June) in 1960 (B.E. 2503) by Sarit Thanarat + # Confirmed as still in-use in 2017 + + if year >= 1960: + _add_with_observed( + date(year, DEC, 5), "HM King Bhumibol Adulyadej's Birthday" + ) + + # !!! National Father's Day !!! + # วันพ่อแห่งชาติ + # Status: In-Use + # Starts in 1980 (B.E 2523) + # Technically, a replication of HM King Bhumibol Adulyadej's Birthday + # but it's in the official calendar, so may as well have this here + + if year >= 1980: + _add_with_observed(date(year, DEC, 5), "National Father's Day") + + # !!! Constitution Day !!! + # วันรัฐธรรมนูญ + # Status: In-Use + # Presumed to starts in 1932 (B.E. 2475) ??? + # Last known official record is Bank of Thailand's in 1992 (B.E. 2535) + # TODO: Add check for 1932 if we support earlier dates. + + _add_with_observed(date(year, DEC, 10), "Constitution Day") + + # !!! New Year's Eve !!! + # วันสิ้นปี + # Status: In-Use + # Presumed to start in the present form in 1941 (B.E. 2484) ??? + # Last known official record is Bank of Thailand's in 1992 (B.E. 2535) + # TODO: Add check for 1941 if we support earlier dates. + # This has its own in-lieu trigger + + self[date(year, DEC, 31)] = "New Year's Eve" + + ################################ + # + # THAI LUNAR CALENDAR HOLIDAYS + # + ################################ + + """ + See `_ThaiLuniSolar` in holidays/utils.py for more details. + + Thai Lunar Calendar Holidays only work from 1941 (B.E. 2484) onwards + until 2057 (B.E. 2600). + """ + # !!! Makha Bucha !!! + # วันมาฆบูชา + # Status: In-Use + + makha_bucha_date = self.thls.makha_bucha_date(year) + if makha_bucha_date: + _add_with_observed(makha_bucha_date, "Makha Bucha") + + # !!! Visakha Bucha !!! + # วันวิสาขบูชา + # Status: In-Use + + visakha_bucha_date = self.thls.visakha_bucha_date(year) + if visakha_bucha_date: + _add_with_observed(visakha_bucha_date, "Visakha Bucha") + + # !!! Asarnha Bucha !!! + # วันอาสาฬหบูชา + # Status: In-Use + # This has its own in-lieu trigger + + asarnha_bucha_date = self.thls.asarnha_bucha_date(year) + if asarnha_bucha_date: + self[asarnha_bucha_date] = "Asarnha Bucha" + + # !!! Buddhist Lent Day !!! + # วันเข้าพรรษา + # Status: In-Use + # This has its own in-lieu trigger + + khao_phansa_date = self.thls.khao_phansa_date(year) + if khao_phansa_date: + self[khao_phansa_date] = "Buddhist Lent Day" + + # !!! Asarnha Bucha/Buddhist Lent Day (in lieu) !!! + # วันหยุดชดเชยวันอาสาฬหบูชา + # วันหยุดชดเชยวันเข้าพรรษา + # Status: In Use + # - CASE 1: FRI-SAT -> 1 in-lieu on MON + # - CASE 2: SAT-SUN -> 1 in-lieu on MON + # - CASE 3: SUN-MON -> 1 in-lieu on TUE + # See in lieu logic in `_add_with_observed(dt, holiday_name)` + + if ( + asarnha_bucha_date + and self.observed + and (1961 <= year <= 1973 or 1995 <= year <= 1997 or year >= 2001) + ): + if self._is_friday(asarnha_bucha_date): + self[ + asarnha_bucha_date + td(days=+3) + ] = "Buddhist Lent Day (in lieu)" + elif self._is_weekend(asarnha_bucha_date): + self[ + asarnha_bucha_date + td(days=+2) + ] = "Asarnha Bucha (in lieu)" + + ################################# + # + # NO FUTURE FIXED DATE HOLIDAYS + # + ################################# + + # !!! Royal Ploughing Ceremony !!! + # วันพืชมงคล + # Restarts in 1957 (B.E. 2500) + # Is dated on an annual basis by the Royal Palace + # This isn't even fixed even by the Thai Lunar Calendar, but instead + # by Court Astrologers; All chosen dates are all around May, so we + # can technically assign it to 13 May for years prior with no data. + # *** NOTE: only observed by government sectors + # TODO: Update this annually around Dec of each year + raeknakhwan = "Royal Ploughing Ceremony" + + raeknakhwan_dates = { + 1997: (MAY, 13), + 1998: (MAY, 13), + # Not held in 1999 date + 2000: (MAY, 15), + 2001: (MAY, 16), + 2002: (MAY, 9), + 2003: (MAY, 8), + 2004: (MAY, 7), + 2005: (MAY, 11), + 2006: (MAY, 11), + 2007: (MAY, 10), + 2008: (MAY, 9), + 2009: (MAY, 11), + 2010: (MAY, 10), + 2011: (MAY, 13), + 2012: (MAY, 9), + 2013: (MAY, 13), + 2014: (MAY, 9), + 2015: (MAY, 13), + 2016: (MAY, 9), + 2017: (MAY, 12), + 2018: (MAY, 14), + 2019: (MAY, 9), + 2020: (MAY, 11), + 2021: (MAY, 13), + 2022: (MAY, 17), + 2023: (MAY, 11), } - if year in vassa: - add_holiday(date(year, *vassa[year]), "Beginning of Vassa") - - # The Queen Sirikit's Birthday. - add_holiday(date(year, AUG, 12), "The Queen Mother's Birthday") - - # Anniversary for the Death of King Bhumibol Adulyadej. - add_holiday( - date(year, OCT, 13), "King Bhumibol Adulyadej Memorial Day" - ) - - # King Chulalongkorn Day - add_holiday(date(year, OCT, 23), "King Chulalongkorn Day") - - # King Bhumibol Adulyadej's Birthday Anniversary. - add_holiday(date(year, DEC, 5), "King Bhumibol Adulyadej's Birthday") - - # Constitution Day. - add_holiday(date(year, DEC, 10), "Constitution Day") - - # New Year's Eve. - add_holiday(date(year, DEC, 31), "New Year's Eve") + # For years with exact date data + if year in raeknakhwan_dates: + _add_with_observed( + date(year, *raeknakhwan_dates[year]), raeknakhwan + ) + # Approx. otherwise for 1957-2013 + elif 1957 <= year <= 1996: + _add_with_observed(date(year, MAY, 13), raeknakhwan) class TH(Thailand): diff --git a/holidays/countries/tunisia.py b/holidays/countries/tunisia.py index ae15a9955..2bbe7adbc 100644 --- a/holidays/countries/tunisia.py +++ b/holidays/countries/tunisia.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, MAR, APR, MAY, JUL, AUG, OCT from holidays.holiday_base import HolidayBase @@ -78,8 +77,8 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 10, 1): hol_date = date_obs _add_holiday(hol_date, "Eid al-Fitr") - _add_holiday(hol_date + rd(days=+1), "Eid al-Fitr Holiday") - _add_holiday(hol_date + rd(days=+2), "Eid al-Fitr Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Fitr Holiday") + _add_holiday(hol_date + td(days=+2), "Eid al-Fitr Holiday") # Arafat Day & Eid al-Adha - Scarfice Festive # date of observance is announced yearly @@ -87,9 +86,9 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 12, 9): hol_date = date_obs _add_holiday(hol_date, "Arafat Day") - _add_holiday(hol_date + rd(days=+1), "Eid al-Adha") - _add_holiday(hol_date + rd(days=+2), "Eid al-Adha Holiday") - _add_holiday(hol_date + rd(days=+3), "Eid al-Adha Holiday") + _add_holiday(hol_date + td(days=+1), "Eid al-Adha") + _add_holiday(hol_date + td(days=+2), "Eid al-Adha Holiday") + _add_holiday(hol_date + td(days=+3), "Eid al-Adha Holiday") # Islamic New Year - (hijari_year, 1, 1) for date_obs in _islamic_to_gre(year, 1, 1): diff --git a/holidays/countries/turkey.py b/holidays/countries/turkey.py index c68a62c87..b73801e00 100644 --- a/holidays/countries/turkey.py +++ b/holidays/countries/turkey.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, APR, MAY, JUL, AUG, OCT from holidays.holiday_base import HolidayBase @@ -67,8 +66,8 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 10, 1): hol_date = date_obs _add_holiday(hol_date, "Ramadan Feast") - _add_holiday(hol_date + rd(days=+1), "Ramadan Feast Holiday") - _add_holiday(hol_date + rd(days=+2), "Ramadan Feast Holiday") + _add_holiday(hol_date + td(days=+1), "Ramadan Feast Holiday") + _add_holiday(hol_date + td(days=+2), "Ramadan Feast Holiday") # Sacrifice Feast # Date of observance is announced yearly, This is an estimate. @@ -76,9 +75,9 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in _islamic_to_gre(yr, 12, 10): hol_date = date_obs _add_holiday(hol_date, "Sacrifice Feast") - _add_holiday(hol_date + rd(days=+1), "Sacrifice Feast Holiday") - _add_holiday(hol_date + rd(days=+2), "Sacrifice Feast Holiday") - _add_holiday(hol_date + rd(days=+3), "Sacrifice Feast Holiday") + _add_holiday(hol_date + td(days=+1), "Sacrifice Feast Holiday") + _add_holiday(hol_date + td(days=+2), "Sacrifice Feast Holiday") + _add_holiday(hol_date + td(days=+3), "Sacrifice Feast Holiday") class TR(Turkey): diff --git a/holidays/countries/ukraine.py b/holidays/countries/ukraine.py index f53e9ab81..4fa6f1459 100644 --- a/holidays/countries/ukraine.py +++ b/holidays/countries/ukraine.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import EASTER_ORTHODOX, easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAR, MAY, JUN, JUL, AUG, SEP, OCT from holidays.constants import NOV, DEC @@ -26,128 +26,166 @@ class Ukraine(HolidayBase): """ country = "UA" + default_language = "uk" def _populate(self, year): + def _add_with_observed( + hol_date: date, hol_name: str, days: int = 1 + ) -> None: + self[hol_date] = hol_name + # 27.01.1995: holiday on weekend move to next workday + # https://zakon.rada.gov.ua/laws/show/35/95-вр + # 10.01.1998: cancelled + # https://zakon.rada.gov.ua/laws/show/785/97-вр + # 23.04.1999: holiday on weekend move to next workday + # https://zakon.rada.gov.ua/laws/show/576-14 + if ( + self.observed + and self._is_weekend(hol_date) + and ( + date(1995, JAN, 27) <= hol_date <= date(1998, JAN, 9) + or hol_date >= date(1999, APR, 23) + ) + ): + obs_date = hol_date + td( + days=2 if self._is_saturday(hol_date) else days + ) + self[obs_date] = self.tr("Вихідний за %s") % hol_name + # The current set of holidays came into force in 1991 # But most holiday days were implemented in 1918 if year <= 1917: - return + return None + super()._populate(year) # New Year's Day if year <= 1929 or year >= 1948: - self[date(year, JAN, 1)] = "Новий рік" + _add_with_observed(date(year, JAN, 1), self.tr("Новий рік")) # Christmas Day (Julian calendar) if year >= 1991: - self[ - date(year, JAN, 7) - ] = "Різдво Христове (за юліанським календарем)" + _add_with_observed( + date(year, JAN, 7), + self.tr("Різдво Христове (за юліанським календарем)"), + ) # Women's Day if year >= 1966: - self[date(year, MAR, 8)] = "Міжнародний жіночий день" + _add_with_observed( + date(year, MAR, 8), self.tr("Міжнародний жіночий день") + ) if year >= 1991: # Easter easter_date = easter(year, method=EASTER_ORTHODOX) - self[easter_date] = "Великдень (Пасха)" + name = self.tr("Великдень (Пасха)") + if year == 2000: + _add_with_observed(easter_date, name, days=3) + elif year in { + 2005, + 2016, + 2021, + 2027, + 2032, + 2062, + 2073, + 2078, + 2084, + }: + _add_with_observed(easter_date, name, days=2) + else: + _add_with_observed(easter_date, name) # Holy trinity - self[easter_date + rd(days=+49)] = "Трійця" + _add_with_observed(easter_date + td(days=+49), self.tr("Трійця")) # Labour Day - name = "День міжнародної солідарності трудящих" + dt = date(year, MAY, 1) if year >= 2018: - name = "День праці" - self[date(year, MAY, 1)] = name - - # Labour Day in past - if 1929 <= year <= 2017: - self[date(year, MAY, 2)] = "День міжнародної солідарності трудящих" + name = self.tr("День праці") + _add_with_observed(dt, name) + else: + name = self.tr("День міжнародної солідарності трудящих") + if year >= 1929: + _add_with_observed(dt, name, days=2) + _add_with_observed(dt + td(days=+1), name, days=2) + else: + self[dt] = name # Victory Day - name = "День перемоги" dt = date(year, MAY, 9) - if year >= 2016: - name = ( + name = ( + self.tr( "День перемоги над нацизмом у Другій світовій війні " "(День перемоги)" ) + if year >= 2016 + else self.tr("День перемоги") + ) + if year >= 1965: - self[dt] = name + _add_with_observed(dt, name) elif 1945 <= year <= 1946: self[dt] = name - self[date(year, SEP, 3)] = "День перемоги над Японією" + self[date(year, SEP, 3)] = self.tr("День перемоги над Японією") # Constitution Day if year >= 1997: - self[date(year, JUN, 28)] = "День Конституції України" + _add_with_observed( + date(year, JUN, 28), self.tr("День Конституції України") + ) # Day of Ukrainian Statehood if year >= 2022: - self[date(year, JUL, 28)] = "День Української Державності" + _add_with_observed( + date(year, JUL, 28), self.tr("День Української Державності") + ) # Independence Day - name = "День незалежності України" + name = self.tr("День незалежності України") if year >= 1992: - self[date(year, AUG, 24)] = name + _add_with_observed(date(year, AUG, 24), name) elif year == 1991: self[date(year, JUL, 16)] = name # Day of the defender of Ukraine if year >= 2015: - name = "День захисника України" - if year >= 2021: - name = "День захисників і захисниць України" - self[date(year, OCT, 14)] = name + name = ( + self.tr("День захисників і захисниць України") + if year >= 2021 + else self.tr("День захисника України") + ) + _add_with_observed(date(year, OCT, 14), name) # October Revolution if year <= 1999: - name = "Річниця Великої Жовтневої соціалістичної революції" - self[date(year, NOV, 7)] = name - self[date(year, NOV, 8)] = name + name = self.tr( + "Річниця Великої Жовтневої соціалістичної революції" + ) + _add_with_observed(date(year, NOV, 7), name, days=2) + _add_with_observed(date(year, NOV, 8), name, days=2) # Christmas Day (Gregorian calendar) if year >= 2017: - self[ - date(year, DEC, 25) - ] = "Різдво Христове (за григоріанським календарем)" - - # 27.01.1995: holiday on weekend move to next workday - # https://zakon.rada.gov.ua/laws/show/35/95-вр - # 10.01.1998: cancelled - # https://zakon.rada.gov.ua/laws/show/785/97-вр - # 23.04.1999: holiday on weekend move to next workday - # https://zakon.rada.gov.ua/laws/show/576-14 - if self.observed: - for k, v in list(self.items()): - if ( - self._is_weekend(k) - and k.year == year - and ( - date(1995, JAN, 27) <= k <= date(1998, JAN, 9) - or k >= date(1999, APR, 23) - ) - ): - next_workday = k + rd(days=+1) - while self._is_weekend(next_workday) or self.get( - next_workday - ): - next_workday += rd(days=+1) - self[next_workday] = "Вихідний за " + v + _add_with_observed( + date(year, DEC, 25), + self.tr("Різдво Христове (за григоріанським календарем)"), + ) # USSR holidays # Bloody_Sunday_(1905) if year <= 1950: - self[date(year, JAN, 22)] = "День пам’яті 9 січня 1905 року" + self[date(year, JAN, 22)] = self.tr( + "День пам'яті 9 січня 1905 року" + ) # Paris_Commune if year <= 1928: - self[date(year, MAR, 18)] = "День Паризької Комуни" + self[date(year, MAR, 18)] = self.tr("День Паризької Комуни") # USSR Constitution day - name = "День Конституції СРСР" + name = self.tr("День Конституції СРСР") if 1981 <= year <= 1990: self[date(year, OCT, 7)] = name elif 1937 <= year <= 1980: diff --git a/holidays/countries/united_arab_emirates.py b/holidays/countries/united_arab_emirates.py index ba4df710f..33825d87f 100644 --- a/holidays/countries/united_arab_emirates.py +++ b/holidays/countries/united_arab_emirates.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, SEP, NOV, DEC from holidays.constants import FRI, SAT @@ -20,7 +19,6 @@ class UnitedArabEmirates(HolidayBase): - # Holidays are regulated by the Article 74 # of Federal Law No. 08 for the year 1980: # https://www.ilo.org/dyn/natlex/docs/ELECTRONIC/11956/69376/F417089305/ARE11956.pdf @@ -87,19 +85,19 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in dates_obs[year]: hol_date = date(year, *date_obs) self[hol_date] = fitr - self[hol_date + rd(days=+1)] = f"{fitr} Holiday" - self[hol_date + rd(days=+2)] = f"{fitr} Holiday" + self[hol_date + td(days=+1)] = f"{fitr} Holiday" + self[hol_date + td(days=+2)] = f"{fitr} Holiday" else: for yr in (year - 1, year): for date_obs in _islamic_to_gre(yr, 10, 1): hol_date = date_obs _add_holiday(hol_date, f"{fitr}* (*estimated)") _add_holiday( - hol_date + rd(days=+1), + hol_date + td(days=+1), f"{fitr} Holiday* (*estimated)", ) _add_holiday( - hol_date + rd(days=+2), + hol_date + td(days=+2), f"{fitr} Holiday* (*estimated)", ) @@ -116,23 +114,23 @@ def _add_holiday(dt: date, hol: str) -> None: for date_obs in dates_obs[year]: hol_date = date(year, *date_obs) self[hol_date] = hajj - self[hol_date + rd(days=+1)] = adha - self[hol_date + rd(days=+2)] = f"{adha} Holiday" - self[hol_date + rd(days=+3)] = f"{adha} Holiday" + self[hol_date + td(days=+1)] = adha + self[hol_date + td(days=+2)] = f"{adha} Holiday" + self[hol_date + td(days=+3)] = f"{adha} Holiday" else: for yr in (year - 1, year): for date_obs in _islamic_to_gre(yr, 12, 9): hol_date = date_obs _add_holiday(hol_date, f"{hajj}* (*estimated)") _add_holiday( - hol_date + rd(days=+1), f"{adha}* (*estimated)" + hol_date + td(days=+1), f"{adha}* (*estimated)" ) _add_holiday( - hol_date + rd(days=+2), + hol_date + td(days=+2), f"{adha}* Holiday* (*estimated)", ) _add_holiday( - hol_date + rd(days=+3), + hol_date + td(days=+3), f"{adha} Holiday* (*estimated)", ) diff --git a/holidays/countries/united_kingdom.py b/holidays/countries/united_kingdom.py index 0f020e773..3bd4fc041 100644 --- a/holidays/countries/united_kingdom.py +++ b/holidays/countries/united_kingdom.py @@ -8,15 +8,16 @@ # 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 Any from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import MON, JAN, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import NOV, DEC +from holidays.constants import JAN, MAR, APR, MAY, JUN, JUL, AUG, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -69,9 +70,9 @@ def _populate(self, year: int) -> None: name += " [Scotland]" self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" - elif self.observed and dt.weekday() == MON: - self[dt + rd(days=+1)] = name + " (Observed)" + self[dt + td(days=+2)] = name + " (Observed)" + elif self.observed and self._is_monday(dt): + self[dt + td(days=+1)] = name + " (Observed)" # St. Patrick's Day if self.subdiv in {"Northern Ireland", "UK"}: @@ -109,7 +110,7 @@ def _populate(self, year: int) -> None: dt = date(year, DEC, 25) self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" + self[dt + td(days=+2)] = name + " (Observed)" # Overwrite to modify country specific holidays self._country_specific(year) @@ -121,14 +122,14 @@ def _country_specific(self, year: int) -> None: easter_date = easter(year) # Good Friday - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-2)] = "Good Friday" # Easter Monday if self.subdiv != "Scotland": name = "Easter Monday" if self.subdiv == "UK": name += " [England/Wales/Northern Ireland]" - self[easter_date + rd(days=+1)] = name + self[easter_date + td(days=+1)] = name # May Day bank holiday (first Monday in May) if year >= 1978: @@ -161,7 +162,7 @@ def _country_specific(self, year: int) -> None: dt = date(year, DEC, 26) self[dt] = name if self.observed and self._is_weekend(dt): - self[dt + rd(days=+2)] = name + " (Observed)" + self[dt + td(days=+2)] = name + " (Observed)" class UK(UnitedKingdom): diff --git a/holidays/countries/united_states.py b/holidays/countries/united_states.py index 0d2e70911..8fdfb8427 100644 --- a/holidays/countries/united_states.py +++ b/holidays/countries/united_states.py @@ -10,19 +10,24 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, TU, TH, FR from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC, MON, WED, FRI, SAT, SUN +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase class UnitedStates(HolidayBase): """ https://en.wikipedia.org/wiki/Public_holidays_in_the_United_States + + For Northern Mariana Islands (subdivision MP): + https://governor.gov.mp/archived-news/executive-actions-archive/memorandum-2022-legal-holidays/ + https://webcache.googleusercontent.com/search?q=cache:C17_7FBgPtQJ:https://governor.gov.mp/archived-news/executive-actions-archive/memorandum-2022-legal-holidays/&hl=en&gl=sg&strip=1&vwsrc=0 """ country = "US" @@ -78,6 +83,7 @@ class UnitedStates(HolidayBase): "SD", "TN", "TX", + "UM", "UT", "VT", "VA", @@ -93,11 +99,12 @@ def _add_with_observed( ) -> None: self[dt] = name if not self.observed: - return - if dt.weekday() == SAT and before: - self[dt + rd(days=-1)] = f"{name} (Observed)" - elif dt.weekday() == SUN and after: - self[dt + rd(days=+1)] = f"{name} (Observed)" + return None + + if self._is_saturday(dt) and before: + self[dt + td(days=-1)] = f"{name} (Observed)" + elif self._is_sunday(dt) and after: + self[dt + td(days=+1)] = f"{name} (Observed)" def _populate(self, year): super()._populate(year) @@ -108,7 +115,7 @@ def _populate(self, year): self._add_with_observed(date(year, JAN, 1), name, before=False) # The following year's observed New Year's Day can be in this year # when it falls on a Friday (Jan 1st is a Saturday). - if self.observed and date(year, DEC, 31).weekday() == FRI: + if self.observed and self._is_friday(date(year, DEC, 31)): self[date(year, DEC, 31)] = f"{name} (Observed)" # Epiphany @@ -123,7 +130,7 @@ def _populate(self, year): if self.subdiv == "VA" and year <= 2020: name = "Lee Jackson Day" if year >= 2000: - dt = date(year, JAN, 1) + rd(weekday=MO(+3)) + rd(days=-3) + dt = date(year, JAN, 1) + rd(weekday=MO(+3)) + td(days=-3) self[dt] = name elif year >= 1983: self[date(year, JAN, 1) + rd(weekday=MO(+3))] = name @@ -191,7 +198,7 @@ def _populate(self, year): elif year >= 1879: self[date(year, FEB, 22)] = name elif self.subdiv == "GA": - if date(year, DEC, 24).weekday() != WED: + if not self._is_wednesday(year, DEC, 24): self[date(year, DEC, 24)] = name else: self[date(year, DEC, 26)] = name @@ -201,7 +208,7 @@ def _populate(self, year): easter_date = easter(year) # Mardi Gras if self.subdiv == "LA" and year >= 1857: - self[easter_date + rd(days=-47)] = "Mardi Gras" + self[easter_date + td(days=-47)] = "Mardi Gras" # Guam Discovery Day if self.subdiv == "GU" and year >= 1970: @@ -233,6 +240,12 @@ def _populate(self, year): date(year, MAR, 22), "Emancipation Day", before=False ) + # Commonwealth Covenant Day in Northern Mariana Islands + if self.subdiv == "MP": + self._add_with_observed( + date(year, MAR, 24), "Commonwealth Covenant Day" + ) + # Prince Jonah Kuhio Kalanianaole Day if self.subdiv == "HI" and year >= 1949: self._add_with_observed( @@ -273,7 +286,7 @@ def _populate(self, year): # Holy Thursday if self.subdiv == "VI": - self[easter_date + rd(days=-3)] = "Holy Thursday" + self[easter_date + td(days=-3)] = "Holy Thursday" # Good Friday if self.subdiv in { @@ -283,6 +296,7 @@ def _populate(self, year): "IN", "KY", "LA", + "MP", "NC", "NJ", "PR", @@ -290,11 +304,11 @@ def _populate(self, year): "TX", "VI", }: - self[easter_date + rd(days=-2)] = "Good Friday" + self[easter_date + td(days=-2)] = "Good Friday" # Easter Monday if self.subdiv == "VI": - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=+1)] = "Easter Monday" # Confederate Memorial Day name = "Confederate Memorial Day" @@ -325,7 +339,7 @@ def _populate(self, year): (year >= 2006 and year % 2 == 0) or year >= 2015 ): self[ - (date(year, MAY, 1) + rd(weekday=MO) + rd(days=+1)) + (date(year, MAY, 1) + rd(weekday=MO) + td(days=+1)) ] = "Primary Election Day" # Truman Day @@ -423,6 +437,12 @@ def _populate(self, year): elif year >= 1937: self[date(year, OCT, 12)] = name + # Commonwealth Cultural Day in Northern Mariana Islands + if self.subdiv == "MP": + self[ + date(year, OCT, 1) + rd(weekday=MO(+2)) + ] = "Commonwealth Cultural Day" + # Alaska Day if self.subdiv == "AK" and year >= 1867: self._add_with_observed(date(year, OCT, 18), "Alaska Day") @@ -441,18 +461,34 @@ def _populate(self, year): # Election Day if ( self.subdiv - in {"DE", "HI", "IL", "IN", "LA", "MT", "NH", "NJ", "NY", "WV"} + in { + "DE", + "HI", + "IL", + "IN", + "LA", + "MP", + "MT", + "NH", + "NJ", + "NY", + "WV", + } and year >= 2008 and year % 2 == 0 ) or (self.subdiv in {"IN", "NY"} and year >= 2015): self[ - date(year, NOV, 1) + rd(weekday=MO) + rd(days=+1) + date(year, NOV, 1) + rd(weekday=MO) + td(days=+1) ] = "Election Day" # All Souls' Day if self.subdiv == "GU": self[date(year, NOV, 2)] = "All Souls' Day" + # Citizenship Day in Northern Mariana Islands + if self.subdiv == "MP": + self._add_with_observed(date(year, NOV, 4), "Citizenship Day") + # Veterans Day if year >= 1954: name = "Veterans Day" @@ -500,7 +536,7 @@ def _populate(self, year): name = "Family Day" if self.subdiv == "NM": name = "Presidents' Day" - self[date(year, NOV, 1) + rd(weekday=TH(+4)) + rd(days=+1)] = name + self[date(year, NOV, 1) + rd(weekday=TH(+4)) + td(days=+1)] = name # Robert E. Lee's Birthday if self.subdiv == "GA" and year >= 1986: @@ -514,6 +550,10 @@ def _populate(self, year): if self.subdiv == "GU": self[date(year, DEC, 8)] = "Lady of Camarin Day" + # Constitution Day in Northern Mariana Islands + if self.subdiv == "MP": + self._add_with_observed(date(year, DEC, 8), "Constitution Day") + # Christmas Eve if ( self.subdiv == "AS" @@ -525,8 +565,8 @@ def _populate(self, year): dt = date(year, DEC, 24) self[dt] = name # If on Friday, observed on Thursday - if self.observed and dt.weekday() == FRI: - self[dt + rd(days=-1)] = f"{name} (Observed)" + if self.observed and self._is_friday(dt): + self[dt + td(days=-1)] = f"{name} (Observed)" # If on Saturday or Sunday, observed on Friday elif self.observed and self._is_weekend(dt): self[dt + rd(weekday=FR(-1))] = f"{name} (Observed)" @@ -544,8 +584,8 @@ def _populate(self, year): if self.observed and self._is_weekend(dt): self[dt + rd(weekday=MO)] = f"{name} (Observed)" # If on Monday, observed on Tuesday - elif self.observed and dt.weekday() == MON: - self[dt + rd(days=+1)] = f"{name} (Observed)" + elif self.observed and self._is_monday(dt): + self[dt + td(days=+1)] = f"{name} (Observed)" elif self.subdiv == "TX" and year >= 1981: self[dt] = "Day After Christmas" elif self.subdiv == "VI": diff --git a/holidays/countries/united_states_minor_outlying_islands.py b/holidays/countries/united_states_minor_outlying_islands.py new file mode 100644 index 000000000..57995dcfe --- /dev/null +++ b/holidays/countries/united_states_minor_outlying_islands.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysUM(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "UM" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "UM" + super()._populate(year) + + +class UM(HolidaysUM): + pass + + +class UMI(HolidaysUM): + pass + + +class UnitedStatesMinorOutlyingIslands(HolidaysUM): + pass diff --git a/holidays/countries/united_states_virgin_islands.py b/holidays/countries/united_states_virgin_islands.py new file mode 100644 index 000000000..c348340dd --- /dev/null +++ b/holidays/countries/united_states_virgin_islands.py @@ -0,0 +1,37 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.united_states import US + + +class HolidaysVI(US): + # Alias of a US subdivision that is also officially assigned its own + # country code in ISO 3166-1. See + # https://en.wikipedia.org/wiki/ISO_3166-2:US#Subdivisions_included_in_ISO_3166-1 + + country = "VI" + subdivisions = [] # Override US subdivisions. + + def _populate(self, year: int) -> None: + self.subdiv = "VI" + super()._populate(year) + + +class VI(HolidaysVI): + pass + + +class VIR(HolidaysVI): + pass + + +class UnitedStatesVirginIslands(HolidaysVI): + pass diff --git a/holidays/countries/uruguay.py b/holidays/countries/uruguay.py index 1f4fc2465..ca78df24b 100644 --- a/holidays/countries/uruguay.py +++ b/holidays/countries/uruguay.py @@ -10,13 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAY, JUN, JUL, AUG, OCT, NOV, DEC -from holidays.constants import TUE, WED, THU, FRI from holidays.holiday_base import HolidayBase @@ -74,12 +74,12 @@ def _populate(self, year): # Carnival days # revisar este día para futuros casos name = "Día de Carnaval [Carnival's Day]" - self[easter_date + rd(days=-48)] = name - self[easter_date + rd(days=-47)] = name + self[easter_date + td(days=-48)] = name + self[easter_date + td(days=-47)] = name # Holy Week. - self[easter_date + rd(days=-3)] = "Jueves Santo [Holy Thursday]" - self[easter_date + rd(days=-2)] = "Viernes Santo [Holy Friday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Holy Thursday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Holy Friday]" self[easter_date] = "Día de Pascuas [Easter Day]" @@ -104,9 +104,9 @@ def _populate(self, year): ) for dt, name in holiday_pairs: - if dt.weekday() in {TUE, WED}: + if self._is_tuesday(dt) or self._is_wednesday(dt): self[dt + rd(weekday=MO(-1))] = name - elif dt.weekday() in {THU, FRI}: + elif self._is_thursday(dt) or self._is_friday(dt): self[dt + rd(weekday=MO(+1))] = name else: self[dt] = name diff --git a/holidays/countries/vatican_city.py b/holidays/countries/vatican_city.py index 7b6848b54..b106de9b7 100644 --- a/holidays/countries/vatican_city.py +++ b/holidays/countries/vatican_city.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, AUG, SEP, NOV, DEC from holidays.holiday_base import HolidayBase @@ -52,7 +52,7 @@ def _populate(self, year: int) -> None: self[easter_sunday] = "Easter Sunday" # Easter Monday. - self[easter_sunday + rd(days=+1)] = "Easter Monday" + self[easter_sunday + td(days=+1)] = "Easter Monday" # Saint George's Day. self[date(year, APR, 23)] = "Saint George's Day" diff --git a/holidays/countries/venezuela.py b/holidays/countries/venezuela.py index 42a47e88b..893c2158e 100644 --- a/holidays/countries/venezuela.py +++ b/holidays/countries/venezuela.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, APR, MAY, JUN, JUL, OCT, DEC from holidays.holiday_base import HolidayBase @@ -43,16 +43,16 @@ def _populate(self, year): easter_date = easter(year) self[ - easter_date + rd(days=-48) + easter_date + td(days=-48) ] = "Lunes de Carnaval [Monday of Carnival]" self[ - easter_date + rd(days=-47) + easter_date + td(days=-47) ] = "Martes de Carnaval [Tuesday of Carnival]" - self[easter_date + rd(days=-3)] = "Jueves Santo [Maundy Thursday]" + self[easter_date + td(days=-3)] = "Jueves Santo [Maundy Thursday]" - self[easter_date + rd(days=-2)] = "Viernes Santo [Good Friday]" + self[easter_date + td(days=-2)] = "Viernes Santo [Good Friday]" # Note: not sure about the start year, but this event happened in 1811 if year >= 1811: diff --git a/holidays/countries/vietnam.py b/holidays/countries/vietnam.py index 6edf3b826..a03b6382d 100644 --- a/holidays/countries/vietnam.py +++ b/holidays/countries/vietnam.py @@ -10,8 +10,7 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td # Installation: pip install korean_lunar_calendar # URL: https://github.com/usingsky/korean_lunar_calendar_py/ @@ -36,9 +35,9 @@ def __init__(self, **kwargs): def _add_observed(self, holiday: date) -> None: if self._is_weekend(holiday): - next_workday = holiday + rd(days=+1) + next_workday = holiday + td(days=+1) while self._is_weekend(next_workday) or self.get(next_workday): - next_workday += rd(days=+1) + next_workday += td(days=+1) self[next_workday] = self[holiday] + " observed" def _populate(self, year): @@ -78,7 +77,7 @@ def _populate(self, year): ) hol_date = self.get_solar_date(year, 1, 1) for d, name in names: - self[(hol_date + rd(days=+d))] = name + self[(hol_date + td(days=+d))] = name # convert lunar calendar date to solar def get_solar_date(self, year, month, day): diff --git a/holidays/countries/zambia.py b/holidays/countries/zambia.py index 4e59f4ed3..81c61729a 100644 --- a/holidays/countries/zambia.py +++ b/holidays/countries/zambia.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, MAR, APR, MAY, JUL, AUG, SEP, OCT, DEC, SUN +from holidays.constants import JAN, MAR, APR, MAY, JUL, AUG, SEP, OCT, DEC from holidays.holiday_base import HolidayBase @@ -53,52 +54,50 @@ class Zambia(HolidayBase): } def _populate(self, year): + def _add_with_observed(hol_date: date, hol_name: str) -> None: + # whenever a public holiday falls on a Sunday, + # it rolls over to the following Monday + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=+1)] = f"{hol_name} (Observed)" # Observed since 1965 if year <= 1964: - return + return None super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") if year >= 1991: - self[date(year, MAR, 8)] = "International Women's Day" + _add_with_observed(date(year, MAR, 8), "International Women's Day") - self[date(year, MAR, 12)] = "Youth Day" + _add_with_observed(date(year, MAR, 12), "Youth Day") easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=-1)] = "Holy Saturday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=-1)] = "Holy Saturday" + self[easter_date + td(days=+1)] = "Easter Monday" if year >= 2022: - self[date(year, APR, 28)] = "Kenneth Kaunda Day" + _add_with_observed(date(year, APR, 28), "Kenneth Kaunda Day") - self[date(year, MAY, 1)] = "Labour Day" - self[date(year, MAY, 25)] = "Africa Freedom Day" + _add_with_observed(date(year, MAY, 1), "Labour Day") + _add_with_observed(date(year, MAY, 25), "Africa Freedom Day") # 1st Monday of July = "Heroes' Day" dt = date(year, JUL, 1) + rd(weekday=MO) self[dt] = "Heroes' Day" - self[dt + rd(days=+1)] = "Unity Day" + self[dt + td(days=+1)] = "Unity Day" # 1st Monday of Aug = "Farmers' Day" - dt = date(year, AUG, 1) + rd(weekday=MO) - self[dt] = "Farmers' Day" + self[date(year, AUG, 1) + rd(weekday=MO)] = "Farmers' Day" if year >= 2015: - self[date(year, OCT, 18)] = "National Prayer Day" + _add_with_observed(date(year, OCT, 18), "National Prayer Day") - self[date(year, OCT, 24)] = "Independence Day" - self[date(year, DEC, 25)] = "Christmas Day" - - # whenever a public holiday falls on a Sunday, - # it rolls over to the following Monday - if self.observed: - for k, v in list(self.items()): - if k.year == year and k.weekday() == SUN: - self[k + rd(days=+1)] = v + " (Observed)" + _add_with_observed(date(year, OCT, 24), "Independence Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day") class ZM(Zambia): diff --git a/holidays/countries/zimbabwe.py b/holidays/countries/zimbabwe.py index 44580274f..309bf5ce6 100644 --- a/holidays/countries/zimbabwe.py +++ b/holidays/countries/zimbabwe.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd -from holidays.constants import JAN, FEB, APR, MAY, AUG, DEC, SUN +from holidays.constants import JAN, FEB, APR, MAY, AUG, DEC from holidays.holiday_base import HolidayBase @@ -28,47 +29,52 @@ class Zimbabwe(HolidayBase): country = "ZW" def _populate(self, year): + def _add_with_observed( + hol_date: date, hol_name: str, days: int = +1 + ) -> None: + self[hol_date] = hol_name + if self.observed and self._is_sunday(hol_date): + self[hol_date + td(days=days)] = f"{hol_name} (Observed)" + if year <= 1987: - return + return None + super()._populate(year) - self[date(year, JAN, 1)] = "New Year's Day" + _add_with_observed(date(year, JAN, 1), "New Year's Day") # https://en.wikipedia.org/wiki/Robert_Gabriel_Mugabe_National_Youth_Day if year >= 2018: - self[ - date(year, FEB, 21) - ] = "Robert Gabriel Mugabe National Youth Day" + _add_with_observed( + date(year, FEB, 21), "Robert Gabriel Mugabe National Youth Day" + ) easter_date = easter(year) - self[easter_date + rd(days=-2)] = "Good Friday" - self[easter_date + rd(days=-1)] = "Easter Saturday" - self[easter_date + rd(days=+1)] = "Easter Monday" + self[easter_date + td(days=-2)] = "Good Friday" + self[easter_date + td(days=-1)] = "Easter Saturday" + self[easter_date + td(days=+1)] = "Easter Monday" - self[date(year, APR, 18)] = "Independence Day" + # In 2049, 2055, 2060 Apr 19 is Easter Monday, + # so observed on Apr 20 (Tue) + _add_with_observed( + date(year, APR, 18), + "Independence Day", + +2 if year in {2049, 2055, 2060} else +1, + ) - self[date(year, MAY, 1)] = "Workers' Day" - self[date(year, MAY, 25)] = "Africa Day" + _add_with_observed(date(year, MAY, 1), "Workers' Day") + _add_with_observed(date(year, MAY, 25), "Africa Day") # 2nd Monday of August zimbabwe_heroes_day = date(year, AUG, 1) + rd(weekday=MO(+2)) self[zimbabwe_heroes_day] = "Zimbabwe Heroes' Day" # Tuesday after 2nd Monday of August - defence_forces_day = zimbabwe_heroes_day + rd(days=+1) - self[defence_forces_day] = "Defense Forces Day" - - self[date(year, DEC, 22)] = "Unity Day" - self[date(year, DEC, 25)] = "Christmas Day" - self[date(year, DEC, 26)] = "Boxing Day" - - if self.observed: - for k, v in list(self.items()): - if k.weekday() == SUN and k.year == year: - dt = k + rd(days=+1) - while self.get(dt): - dt += rd(days=+1) - self[dt] = v + " (Observed)" + self[zimbabwe_heroes_day + td(days=+1)] = "Defense Forces Day" + + _add_with_observed(date(year, DEC, 22), "Unity Day") + _add_with_observed(date(year, DEC, 25), "Christmas Day", days=+2) + _add_with_observed(date(year, DEC, 26), "Boxing Day") class ZW(Zimbabwe): diff --git a/holidays/financial/european_central_bank.py b/holidays/financial/european_central_bank.py index ec10bdb07..4e6c01c78 100644 --- a/holidays/financial/european_central_bank.py +++ b/holidays/financial/european_central_bank.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter -from dateutil.relativedelta import relativedelta as rd from holidays.constants import DEC, JAN, MAY from holidays.holiday_base import HolidayBase @@ -32,8 +32,8 @@ def _populate(self, year): self[date(year, JAN, 1)] = "New Year's Day" e = easter(year) - self[e + rd(days=-2)] = "Good Friday" - self[e + rd(days=+1)] = "Easter Monday" + self[e + td(days=-2)] = "Good Friday" + self[e + td(days=+1)] = "Easter Monday" self[date(year, MAY, 1)] = "1 May (Labour Day)" self[date(year, DEC, 25)] = "Christmas Day" self[date(year, DEC, 26)] = "26 December" diff --git a/holidays/financial/ny_stock_exchange.py b/holidays/financial/ny_stock_exchange.py index 9de054e46..33512bf25 100644 --- a/holidays/financial/ny_stock_exchange.py +++ b/holidays/financial/ny_stock_exchange.py @@ -10,13 +10,14 @@ # License: MIT (see LICENSE file) from datetime import date +from datetime import timedelta as td from dateutil.easter import easter from dateutil.relativedelta import MO, TH, FR from dateutil.relativedelta import relativedelta as rd from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP -from holidays.constants import OCT, NOV, DEC, WED, FRI +from holidays.constants import OCT, NOV, DEC from holidays.holiday_base import HolidayBase @@ -62,8 +63,8 @@ def _populate(self, year): # As per Rule 7.2.: check if next year's NYD falls on Saturday and # needs to be observed on Friday (Dec 31 of previous year). dec_31 = date(year, DEC, 31) - if dec_31.weekday() == FRI: - self._set_observed_date(dec_31 + rd(days=+1), "New Year's Day") + if self._is_friday(dec_31): + self._set_observed_date(dec_31 + td(days=+1), "New Year's Day") # MLK - observed 1998 - 3rd Monday of Jan if year >= 1998: @@ -88,7 +89,7 @@ def _populate(self, year): # GOOD FRIDAY - closed every year except 1898, 1906, and 1907 e = easter(year) if year not in {1898, 1906, 1907}: - self[e + rd(days=-2)] = "Good Friday" + self[e + td(days=-2)] = "Good Friday" # MEM DAY (May 30) - closed every year since 1873 # last Mon in May since 1971 @@ -127,7 +128,7 @@ def _populate(self, year): # closed until 1969, then closed pres years 1972-80 if year <= 1968 or year in {1972, 1976, 1980}: self[ - date(year, NOV, 1) + rd(weekday=MO) + rd(days=+1) + date(year, NOV, 1) + rd(weekday=MO) + td(days=+1) ] = "Election Day" # VETERAN'S DAY: Nov 11 - closed 1918, 1921, 1934-1953 @@ -178,7 +179,7 @@ def _populate(self, year): begin = date(year, JUL, 31) end = date(year, NOV, 27) for d in ( - begin + rd(days=n) for n in range((end - begin).days + 1) + begin + td(days=n) for n in range((end - begin).days + 1) ): if self._is_weekend(d): continue @@ -209,7 +210,7 @@ def _populate(self, year): begin = date(year, MAR, 6) end = date(year, MAR, 14) for d in ( - begin + rd(days=n) for n in range((end - begin).days + 1) + begin + td(days=n) for n in range((end - begin).days + 1) ): if self._is_weekend(d): continue @@ -238,9 +239,9 @@ def _populate(self, year): begin = date(year, JUN, 12) end = date(year, DEC, 31) for d in ( - begin + rd(days=n) for n in range((end - begin).days + 1) + begin + td(days=n) for n in range((end - begin).days + 1) ): - if d.weekday() != WED: # Wednesday special holiday + if not self._is_wednesday(d): # Wednesday special holiday continue self[d] = "Paper Crisis" elif year == 1969: diff --git a/holidays/holiday_base.py b/holidays/holiday_base.py index 88587eaab..501d9d128 100644 --- a/holidays/holiday_base.py +++ b/holidays/holiday_base.py @@ -1,6 +1,6 @@ # python-holidays # --------------- -# A fast, efficient Python library for generating country and subdivision +# 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. # @@ -11,14 +11,19 @@ __all__ = ("DateLike", "HolidayBase", "HolidaySum") +import copy +import os import warnings +from calendar import isleap from datetime import date, datetime, timedelta +from gettext import NullTranslations, gettext, translation +from pathlib import Path from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple from typing import Union, cast from dateutil.parser import parse -from dateutil.relativedelta import relativedelta as rd +from holidays.constants import HOLIDAY_NAME_DELIMITER, MON, TUE, WED, THU, FRI from holidays.constants import SAT, SUN DateLike = Union[date, datetime, str, float, int] @@ -45,7 +50,7 @@ class HolidayBase(Dict[date, str]): To maximize speed, the list of holidays is built as needed on the fly, one calendar year at a time. When you instantiate the object, it is empty, but the moment a key is accessed it will build that entire year's list of - holidays. To prepopulate holidays, instantiate the class with the years + holidays. To pre-populate holidays, instantiate the class with the years argument: us_holidays = holidays.US(years=2020) @@ -81,7 +86,7 @@ class HolidayBase(Dict[date, str]): >>> from holidays import country_holidays >>> us_holidays = country_holidays('US') # For a specific subdivisions (e.g. state or province): - >>> calif_holidays = country_holidays('US', subdiv='CA') + >>> california_holidays = country_holidays('US', subdiv='CA') The below will cause 2015 holidays to be calculated on the fly: @@ -208,13 +213,23 @@ def __init__( expand: bool = True, observed: bool = True, subdiv: Optional[str] = None, - prov: Optional[str] = None, # deprecated - state: Optional[str] = None, # deprecated + prov: Optional[str] = None, # Deprecated. + state: Optional[str] = None, # Deprecated. + language: Optional[str] = None, ) -> None: """ :param years: The year(s) to pre-calculate public holidays for at instantiation. + :param expand: + Whether the entire year is calculated when one date from that year + is requested. + + :param observed: + Whether to include the dates when public holiday are observed + (e.g. a holiday falling on a Sunday being observed the + following Monday). This doesn't work for all countries. + :param subdiv: The subdivision (e.g. state or province); not implemented for all countries (see documentation). @@ -225,28 +240,31 @@ def __init__( :param state: *deprecated* use subdiv instead. - :param expand: - Whether the entire year is calculated when one date from that year - is requested. - - :param observed: - Whether to include the dates when public holiday are observed - (e.g. a holiday falling on a Sunday being observed the - following Monday). This doesn't work for all countries. + :param language: + The language which the returned holiday names will be translated + into. It must be an ISO 639-1 (2-letter) language code. If the + language translation is not supported the original holiday names + will be used. :return: A :class:`HolidayBase` object matching the **country**. """ super().__init__() - self.observed = observed + self.expand = expand + self.language = language.lower() if language else None + self.observed = observed self.subdiv = subdiv or prov or state + + self.tr = gettext # Default translation method. + if prov or state: warnings.warn( "Arguments prov and state are deprecated, use subdiv=" f"'{prov or state}' instead.", DeprecationWarning, ) + if not isinstance(self, HolidaySum): if ( subdiv @@ -254,39 +272,58 @@ def __init__( not in self.subdivisions + self._deprecated_subdivisions ): if hasattr(self, "market"): - raise NotImplementedError( - f"Market {self.market} does not have subdivision " + error = ( + f"Market '{self.market}' does not have subdivision " f"'{subdiv}'" ) else: - raise NotImplementedError( - f"Country {self.country} does not have subdivision " + error = ( + f"Country '{self.country}' does not have subdivision " f"'{subdiv}'" ) + raise NotImplementedError(error) + + name = getattr(self, "country", getattr(self, "market", None)) + if name: + locale_dir = os.path.join(os.path.dirname(__file__), "locale") + translator: NullTranslations + translations = sorted( + ( + # Collect `language` part from + # holidays/locale//LC_MESSAGES/country.po + str(translation).split(os.sep)[-3] + for translation in Path(locale_dir).rglob(f"{name}.mo") + ) + ) + if language and language in translations: + translator = translation( + name, + languages=[language], + localedir=locale_dir, + ) + else: + translator = translation( + name, + fallback=True, + localedir=locale_dir, + ) + self.tr = translator.gettext # Replace `self.tr()`. + if isinstance(years, int): self.years = {years} else: self.years = set(years) if years is not None else set() - for year in self.years.copy(): + + for year in self.years: self._populate(year) def __setattr__(self, key: str, value: Any) -> None: - if key == "observed" and len(self) > 0: - dict.__setattr__(self, key, value) - if value is True: - # Add (Observed) dates - years = list(self.years) - self.years = set() - self.clear() - for year in years: - self._populate(year) - else: - # Remove (Observed) dates - for k, v in list(self.items()): - if v.find("Observed") >= 0: - del self[k] - else: - return dict.__setattr__(self, key, value) + dict.__setattr__(self, key, value) + + if self and key == "observed": + self.clear() + for year in self.years: # Re-populate holidays for each year. + self._populate(year) def __keytransform__(self, key: DateLike) -> date: """Transforms the date from one of the following types: @@ -298,24 +335,43 @@ def __keytransform__(self, key: DateLike) -> date: * or a :class:`float` or :class:`int` representing a POSIX timestamp to :class:`datetime.date`, which is how it's stored by the class.""" - if isinstance(key, datetime): - out_key = key.date() - elif isinstance(key, date): - out_key = key - elif isinstance(key, int) or isinstance(key, float): - out_key = datetime.utcfromtimestamp(key).date() - elif isinstance(key, str): + + # Try to catch `date` and `str` type keys first. + if type(key) == date: # Key has `date` type. + dt = key + + elif type(key) == str: # Key has `str` type. try: - out_key = parse(key).date() - except (ValueError, OverflowError): - raise ValueError("Cannot parse date from string '%s'" % key) - else: - raise TypeError("Cannot convert type '%s' to date." % type(key)) + dt = parse(key).date() + except (OverflowError, ValueError): + raise ValueError(f"Cannot parse date from string '{key}'") + + # Check all other types. + elif isinstance(key, datetime): # Key type is derived from `datetime`. + dt = key.date() + + # Must go after the `isinstance(key, datetime)` check + # as datetime is derived from `date`. + elif isinstance(key, date): # Key type is derived from `date`. + dt = key - if self.expand and out_key.year not in self.years: - self.years.add(out_key.year) - self._populate(out_key.year) - return out_key + elif isinstance( + key, (float, int) + ): # Key type is derived from `float` or `int`. + dt = datetime.utcfromtimestamp(key).date() + + else: # Key type is not supported. + raise TypeError(f"Cannot convert type '{type(key)}' to date.") + + # Automatically expand for `expand=True` cases. + if self.expand and dt.year not in self.years: + self.years.add(dt.year) + self._populate(dt.year) + + return dt + + def __bool__(self) -> bool: + return len(self) > 0 def __contains__(self, key: object) -> bool: """Return true if date is in self, false otherwise. Accepts a date in @@ -328,8 +384,8 @@ def __contains__(self, key: object) -> bool: * or a :class:`float` or :class:`int` representing a POSIX timestamp. """ - if not isinstance(key, (date, datetime, str, float, int)): - raise TypeError("Cannot convert type '%s' to date." % type(key)) + if not isinstance(key, (date, datetime, float, int, str)): + raise TypeError(f"Cannot convert type '{type(key)}' to date.") return dict.__contains__( cast("Mapping[Any, Any]", self), self.__keytransform__(key) @@ -351,7 +407,7 @@ def __getitem__(self, key: DateLike) -> Any: step = key.step else: raise TypeError( - "Cannot convert type '%s' to int." % type(key.step) + f"Cannot convert type '{type(key.step)}' to int." ) if step == 0: @@ -363,23 +419,21 @@ def __getitem__(self, key: DateLike) -> Any: days_in_range = [] for delta_days in range(0, date_diff.days, step): - day = start + rd(days=delta_days) - try: - self.__getitem__(day) + day = start + timedelta(days=delta_days) + if day in self: days_in_range.append(day) - except KeyError: - pass + return days_in_range + return dict.__getitem__(self, self.__keytransform__(key)) def __setitem__(self, key: DateLike, value: str) -> None: if key in self: # If there are multiple holidays on the same date # order their names alphabetically. - delimiter = ", " - holiday_names = set(self.get(key).split(delimiter)) + holiday_names = set(self[key].split(HOLIDAY_NAME_DELIMITER)) holiday_names.add(value) - value = delimiter.join(sorted(holiday_names)) + value = HOLIDAY_NAME_DELIMITER.join(sorted(holiday_names)) dict.__setitem__(self, self.__keytransform__(key), value) @@ -403,10 +457,9 @@ def update( # type: ignore[override] * or a :class:`float` or :class:`int` representing a POSIX timestamp. """ - args_list = list(args) - for arg in args_list: + for arg in args: if isinstance(arg, dict): - for key, value in list(arg.items()): + for key, value in arg.items(): self[key] = value elif isinstance(arg, list): for item in arg: @@ -414,6 +467,12 @@ def update( # type: ignore[override] else: self[arg] = "Holiday" + def _add_observed_holiday( + self, dt: DateLike, name: str, suffix: str = "(Observed)" + ) -> None: + """Adds a holiday name with an observance indication.""" + self[dt] = f"{name} {suffix}" + def append( self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike] ) -> None: @@ -463,7 +522,11 @@ def get_list(self, key: DateLike) -> List[str]: * or a :class:`float` or :class:`int` representing a POSIX timestamp. """ - return [h for h in self.get(key, "").split(", ") if h] + return [ + name + for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER) + if name + ] def get_named(self, name: str) -> List[date]: """Return a list of all holiday dates matching the provided holiday @@ -476,13 +539,9 @@ def get_named(self, name: str) -> List[date]: :return: A list of all holiday dates matching the provided holiday name. """ - original_expand = self.expand - self.expand = False - matches = [ - key for key in self if name.lower() in str(self[key]).lower() + return [ + key for key, value in self.items() if name.lower() in value.lower() ] - self.expand = original_expand - return matches def pop( self, @@ -513,6 +572,7 @@ def pop( """ if default is None: return dict.pop(self, self.__keytransform__(key)) + return dict.pop(self, self.__keytransform__(key), default) def pop_named(self, name: str) -> List[date]: @@ -532,18 +592,38 @@ def pop_named(self, name: str) -> List[date]: :raise: KeyError if date is not a holiday and default is not given. """ - to_pop = self.get_named(name) - if not to_pop: + dates = self.get_named(name) + if not dates: raise KeyError(name) - for key in to_pop: - self.pop(key) - return to_pop + + for dt in dates: + self.pop(dt) + + return dates + + def copy(self): + """Return a copy of the object.""" + return copy.copy(self) def __eq__(self, other: object) -> bool: - return dict.__eq__(self, other) and self.__dict__ == other.__dict__ + if not isinstance(other, HolidayBase): + return False + + that, this = copy.copy(other), self.copy() + for obj in (that, this): # Exclude translation objects. + delattr(obj, "tr") + + return dict.__eq__(this, that) and this.__dict__ == that.__dict__ def __ne__(self, other: object) -> bool: - return dict.__ne__(self, other) or self.__dict__ != other.__dict__ + if not isinstance(other, HolidayBase): + return True + + that, this = copy.copy(other), self.copy() + for obj in (that, this): # Exclude translation objects. + delattr(obj, "tr") + + return dict.__ne__(this, that) or this.__dict__ != that.__dict__ def __add__( self, other: Union[int, "HolidayBase", "HolidaySum"] @@ -560,12 +640,14 @@ def __add__( """ if isinstance(other, int) and other == 0: # Required to sum() list of holidays - # sum([h1, h2]) is equivalent to (0 + h1 + h2) + # sum([h1, h2]) is equivalent to (0 + h1 + h2). return self - elif not isinstance(other, (HolidayBase, HolidaySum)): + + if not isinstance(other, (HolidayBase, HolidaySum)): raise TypeError( "Holiday objects can only be added with other Holiday objects" ) + return HolidaySum(self, other) def __radd__(self, other: Any) -> "HolidayBase": @@ -588,9 +670,16 @@ def _populate(self, year: int) -> None: >>> us_holidays.update(country_holidays('US', years=2021)) """ - # Special holidays list. + # Populate items from the special holidays list. for month, day, name in self.special_holidays.get(year, ()): - self[date(year, month, day)] = name + self[date(year, month, day)] = self.tr(name) + + @staticmethod + def _is_leap_year(year: int) -> bool: + """ + Returns True if the year is leap. Returns False otherwise. + """ + return isleap(year) def _is_weekend(self, *args): """ @@ -601,31 +690,74 @@ def _is_weekend(self, *args): return dt.weekday() in self.weekend + @staticmethod + def __is_weekday(weekday, *args): + """ + Returns True if `weekday` equals to the date's week day. + Returns False otherwise. + """ + dt = args[0] if len(args) == 1 else date(*args) + + return dt.weekday() == weekday + + @staticmethod + def _is_monday(*args) -> bool: + return HolidayBase.__is_weekday(MON, *args) + + @staticmethod + def _is_tuesday(*args) -> bool: + return HolidayBase.__is_weekday(TUE, *args) + + @staticmethod + def _is_wednesday(*args) -> bool: + return HolidayBase.__is_weekday(WED, *args) + + @staticmethod + def _is_thursday(*args) -> bool: + return HolidayBase.__is_weekday(THU, *args) + + @staticmethod + def _is_friday(*args) -> bool: + return HolidayBase.__is_weekday(FRI, *args) + + @staticmethod + def _is_saturday(*args) -> bool: + return HolidayBase.__is_weekday(SAT, *args) + + @staticmethod + def _is_sunday(*args) -> bool: + return HolidayBase.__is_weekday(SUN, *args) + def __reduce__(self) -> Union[str, Tuple[Any, ...]]: return super().__reduce__() def __repr__(self) -> str: - _repr = "" - if len(self) == 0: - if hasattr(self, "market"): - _repr = f"holidays.financial_holidays({self.market!r}" - if self.subdiv: - _repr += f", subdiv={self.subdiv!r}" - _repr += ")" - if hasattr(self, "country"): - if _repr: - _repr += " + " - _repr += f"holidays.country_holidays({self.country!r}" - if self.subdiv: - _repr += f", subdiv={self.subdiv!r}" - _repr += ")" - return _repr - return super().__repr__() + if self: + return super().__repr__() + + repr = [] + if hasattr(self, "market"): + repr.append(f"holidays.financial_holidays({self.market!r}") + if self.subdiv: + repr.append(f", subdiv={self.subdiv!r}") + repr.append(")") + elif hasattr(self, "country"): + if repr: + repr.append(" + ") + repr.append(f"holidays.country_holidays({self.country!r}") + if self.subdiv: + repr.append(f", subdiv={self.subdiv!r}") + repr.append(")") + + return "".join(repr) def __str__(self) -> str: - if len(self) == 0: - return str(self.__dict__) - return super().__str__() + if self: + return super().__str__() + + obj = copy.copy(self) + delattr(obj, "tr") + return str(obj.__dict__) class HolidaySum(HolidayBase): @@ -684,27 +816,27 @@ def __init__( (datetime.date(2020, 5, 1), 'Día del Trabajo [Labour Day]'), (datetime.date(2020, 5, 18), 'Victoria Day')] """ - # store originals in the holidays attribute + # Store originals in the holidays attribute. self.holidays = [] for operand in (h1, h2): if isinstance(operand, HolidaySum): - for h in operand.holidays: - self.holidays.append(h) + self.holidays.extend(operand.holidays) else: self.holidays.append(operand) + kwargs: Dict[str, Any] = {} - # join years, expand and observed + # Join years, expand and observed. kwargs["years"] = h1.years | h2.years kwargs["expand"] = h1.expand or h2.expand kwargs["observed"] = h1.observed or h2.observed - # join country and subdivisions data - # TODO this way makes no sense: joining Italy Catania (IT, CA) with + # Join country and subdivisions data. + # TODO: this way makes no sense: joining Italy Catania (IT, CA) with # USA Mississippi (US, MS) and USA Michigan (US, MI) yields # country=["IT", "US"] and subdiv=["CA", "MS", "MI"], which could very # well be California and Messina and Milano, or Catania, Mississippi # and Milano, or ... you get the picture. # Same goes when countries and markets are being mixed (working, yet - # still nonsensical) + # still nonsensical). for attr in ("country", "market", "subdiv"): if ( getattr(h1, attr, None) @@ -721,20 +853,18 @@ def __init__( if isinstance(getattr(h2, attr), list) else [getattr(h2, attr)] ) - kwargs[attr] = a1 + a2 + value = a1 + a2 else: - arg = getattr(h1, attr, None) or getattr(h2, attr, None) - if arg: - kwargs[attr] = arg + value = getattr(h1, attr, None) or getattr(h2, attr, None) - if "country" in kwargs: - self.country = kwargs.pop("country") - if "market" in kwargs: - self.market = kwargs.pop("market") + if attr == "subdiv": + kwargs[attr] = value + else: + setattr(self, attr, value) HolidayBase.__init__(self, **kwargs) def _populate(self, year): - for h in self.holidays[::-1]: - h._populate(year) - self.update(cast("Dict[DateLike, str]", h)) + for operand in self.holidays: + operand._populate(year) + self.update(cast("Dict[DateLike, str]", operand)) diff --git a/holidays/locale/am/LC_MESSAGES/ET.po b/holidays/locale/am/LC_MESSAGES/ET.po new file mode 100644 index 000000000..1be82cbb7 --- /dev/null +++ b/holidays/locale/am/LC_MESSAGES/ET.po @@ -0,0 +1,86 @@ +# Ethiopia holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:15-0800\n" +"PO-Revision-Date: 2023-02-16 08:42-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: am\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. Ethiopian New Year. +#: holidays/countries/ethiopia.py:64 holidays/countries/ethiopia.py:67 +msgid "አዲስ ዓመት እንቁጣጣሽ" +msgstr "" + +#. Finding of True Cross. +#: holidays/countries/ethiopia.py:72 holidays/countries/ethiopia.py:75 +msgid "መስቀል" +msgstr "" + +#. Orthodox Christmas. +#: holidays/countries/ethiopia.py:78 +msgid "ገና" +msgstr "" + +#. Orthodox Epiphany. +#: holidays/countries/ethiopia.py:81 +msgid "ጥምቀት" +msgstr "" + +#. Orthodox Good Friday. +#: holidays/countries/ethiopia.py:85 +msgid "ስቅለት" +msgstr "" + +#. Orthodox Easter Sunday. +#: holidays/countries/ethiopia.py:88 +msgid "ፋሲካ" +msgstr "" + +#. Adwa Victory Day. +#: holidays/countries/ethiopia.py:92 +msgid "አድዋ" +msgstr "" + +#. Labour Day. +#: holidays/countries/ethiopia.py:95 +msgid "የሰራተኞች ቀን" +msgstr "" + +#. Patriots Day. +#: holidays/countries/ethiopia.py:99 +msgid "የአርበኞች ቀን" +msgstr "" + +#. Downfall of Dergue Regime Day. +#: holidays/countries/ethiopia.py:103 +msgid "ደርግ የወደቀበት ቀን" +msgstr "" + +#. Downfall of King Haile Selassie. +#: holidays/countries/ethiopia.py:107 +msgid "ደርግ የመጣበት ቀን" +msgstr "" + +#. Eid al-Fitr. +#: holidays/countries/ethiopia.py:121 +msgid "ኢድ አልፈጥር" +msgstr "" + +#. Eid al-Adha. +#: holidays/countries/ethiopia.py:128 +msgid "አረፋ" +msgstr "" + +#. Prophet Muhammad's Birthday. +#: holidays/countries/ethiopia.py:134 +msgid "መውሊድ" +msgstr "" diff --git a/holidays/locale/be/LC_MESSAGES/BY.po b/holidays/locale/be/LC_MESSAGES/BY.po new file mode 100644 index 000000000..91542cdc1 --- /dev/null +++ b/holidays/locale/be/LC_MESSAGES/BY.po @@ -0,0 +1,61 @@ +# Belarus holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 20:06-0800\n" +"PO-Revision-Date: 2023-02-16 08:45-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/belarus.py:42 +msgid "Новы год" +msgstr "" + +#. Christmas Day (Orthodox). +#: holidays/countries/belarus.py:51 +msgid "Нараджэнне Хрыстова (праваслаўнае Раство)" +msgstr "" + +#. Women's Day. +#: holidays/countries/belarus.py:56 +msgid "Дзень жанчын" +msgstr "" + +#. Radunitsa (Day of Rejoicing). +#: holidays/countries/belarus.py:59 +msgid "Радаўніца" +msgstr "" + +#. Labour Day. +#: holidays/countries/belarus.py:64 +msgid "Свята працы" +msgstr "" + +#. Victory Day +#: holidays/countries/belarus.py:67 +msgid "Дзень Перамогі" +msgstr "" + +#. Independence Day. +#: holidays/countries/belarus.py:70 +msgid "Дзень Незалежнасці Рэспублікі Беларусь (Дзень Рэспублікі)" +msgstr "" + +#. October Revolution Day. +#: holidays/countries/belarus.py:75 +msgid "Дзень Кастрычніцкай рэвалюцыі" +msgstr "" + +#. Christmas Day (Catholic). +#: holidays/countries/belarus.py:78 +msgid "Нараджэнне Хрыстова (каталіцкае Раство)" +msgstr "" diff --git a/holidays/locale/bg/LC_MESSAGES/BG.po b/holidays/locale/bg/LC_MESSAGES/BG.po new file mode 100644 index 000000000..149993558 --- /dev/null +++ b/holidays/locale/bg/LC_MESSAGES/BG.po @@ -0,0 +1,85 @@ +# Bulgaria holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 08:46-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/bulgaria.py:52 +msgid "Нова година" +msgstr "" + +#. Liberation Day. +#: holidays/countries/bulgaria.py:55 +msgid "Ден на Освобождението на България от османско иго" +msgstr "" + +#. International Workers' Day. +#: holidays/countries/bulgaria.py:60 +msgid "Ден на труда и на международната работническа солидарност" +msgstr "" + +#. Saint George's Day. +#: holidays/countries/bulgaria.py:65 +msgid "Гергьовден, Ден на храбростта и Българската армия" +msgstr "" + +#. Bulgarian Education and Culture and Slavonic Literature Day. +#: holidays/countries/bulgaria.py:70 +msgid "" +"Ден на светите братя Кирил и Методий, на българската азбука, просвета и " +"култура и на славянската книжовност" +msgstr "" + +#. Unification Day. +#: holidays/countries/bulgaria.py:76 +msgid "Ден на Съединението" +msgstr "" + +#. Independence Day. +#: holidays/countries/bulgaria.py:79 +msgid "Ден на Независимостта на България" +msgstr "" + +#. National Awakening Day. +#: holidays/countries/bulgaria.py:84 +msgid "Ден на народните будители" +msgstr "" + +#. Christmas Eve. +#: holidays/countries/bulgaria.py:87 +msgid "Бъдни вечер" +msgstr "" + +#. Christmas Day 1. +#. Christmas Day 2. +#: holidays/countries/bulgaria.py:89 holidays/countries/bulgaria.py:91 +msgid "Рождество Христово" +msgstr "" + +#. Good Friday. +#: holidays/countries/bulgaria.py:96 +msgid "Велики петък" +msgstr "" + +#. Easter Saturday. +#: holidays/countries/bulgaria.py:98 +msgid "Велика събота" +msgstr "" + +#. Easter Sunday. +#. Easter Monday. +#: holidays/countries/bulgaria.py:100 holidays/countries/bulgaria.py:102 +msgid "Великден" +msgstr "" diff --git a/holidays/locale/da/LC_MESSAGES/DK.po b/holidays/locale/da/LC_MESSAGES/DK.po new file mode 100644 index 000000000..d7b89ef8a --- /dev/null +++ b/holidays/locale/da/LC_MESSAGES/DK.po @@ -0,0 +1,64 @@ +# Denmark holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 08:48-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/denmark.py:36 +msgid "Nytårsdag" +msgstr "" + +#: holidays/countries/denmark.py:37 +msgid "Palmesøndag" +msgstr "" + +#: holidays/countries/denmark.py:38 +msgid "Skærtorsdag" +msgstr "" + +#: holidays/countries/denmark.py:39 +msgid "Langfredag" +msgstr "" + +#: holidays/countries/denmark.py:40 +msgid "Påskedag" +msgstr "" + +#: holidays/countries/denmark.py:41 +msgid "Anden påskedag" +msgstr "" + +#: holidays/countries/denmark.py:42 +msgid "Store bededag" +msgstr "" + +#: holidays/countries/denmark.py:43 +msgid "Kristi himmelfartsdag" +msgstr "" + +#: holidays/countries/denmark.py:44 +msgid "Pinsedag" +msgstr "" + +#: holidays/countries/denmark.py:45 +msgid "Anden pinsedag" +msgstr "" + +#: holidays/countries/denmark.py:46 +msgid "Juledag" +msgstr "" + +#: holidays/countries/denmark.py:47 +msgid "Anden juledag" +msgstr "" diff --git a/holidays/locale/el/LC_MESSAGES/CY.po b/holidays/locale/el/LC_MESSAGES/CY.po new file mode 100644 index 000000000..ac581a873 --- /dev/null +++ b/holidays/locale/el/LC_MESSAGES/CY.po @@ -0,0 +1,96 @@ +# Cyprus holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 11:50-0800\n" +"PO-Revision-Date: 2023-02-16 08:50-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Years Day. +#: holidays/countries/cyprus.py:38 +msgid "Πρωτοχρονιά" +msgstr "" + +#. Epiphany. +#: holidays/countries/cyprus.py:41 +msgid "Θεοφάνεια" +msgstr "" + +#. Clean Monday. +#: holidays/countries/cyprus.py:44 +msgid "Καθαρά Δευτέρα" +msgstr "" + +#. Greek Independence Day. +#: holidays/countries/cyprus.py:47 +msgid "Εικοστή Πέμπτη Μαρτίου" +msgstr "" + +#. Cyprus National Day. +#: holidays/countries/cyprus.py:50 +msgid "1η Απριλίου" +msgstr "" + +#. Good Friday. +#: holidays/countries/cyprus.py:53 +msgid "Μεγάλη Παρασκευή" +msgstr "" + +#. Easter Sunday. +#: holidays/countries/cyprus.py:56 +msgid "Κυριακή του Πάσχα" +msgstr "" + +#. Easter Monday. +#: holidays/countries/cyprus.py:59 +msgid "Δευτέρα του Πάσχα" +msgstr "" + +#. Labour Day. +#: holidays/countries/cyprus.py:62 +msgid "Εργατική Πρωτομαγιά" +msgstr "" + +#. Monday of the Holy Spirit. +#: holidays/countries/cyprus.py:65 +msgid "Δευτέρα του Αγίου Πνεύματος" +msgstr "" + +#. Assumption of Mary. +#: holidays/countries/cyprus.py:70 +msgid "Κοίμηση της Θεοτόκου" +msgstr "" + +#. Cyprus Independence Day. +#: holidays/countries/cyprus.py:73 +msgid "Ημέρα Ανεξαρτησίας της Κύπρου" +msgstr "" + +#. Ochi Day. +#: holidays/countries/cyprus.py:76 +msgid "Ημέρα του Όχι" +msgstr "" + +#. Christmas Eve. +#: holidays/countries/cyprus.py:79 +msgid "Παραμονή Χριστουγέννων" +msgstr "" + +#. Christmas Day. +#: holidays/countries/cyprus.py:82 +msgid "Χριστούγεννα" +msgstr "" + +#. Day After Christmas. +#: holidays/countries/cyprus.py:85 +msgid "Δεύτερη μέρα Χριστουγέννων" +msgstr "" diff --git a/holidays/locale/el/LC_MESSAGES/GR.po b/holidays/locale/el/LC_MESSAGES/GR.po new file mode 100644 index 000000000..08564da7d --- /dev/null +++ b/holidays/locale/el/LC_MESSAGES/GR.po @@ -0,0 +1,76 @@ +# Greece holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:53-0800\n" +"PO-Revision-Date: 2023-02-16 08:50-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/greece.py:40 +msgid "Πρωτοχρονιά" +msgstr "" + +#. Epiphany. +#: holidays/countries/greece.py:43 +msgid "Θεοφάνεια" +msgstr "" + +#. Clean Monday. +#: holidays/countries/greece.py:46 +msgid "Καθαρά Δευτέρα" +msgstr "" + +#. Independence Day. +#: holidays/countries/greece.py:49 +msgid "Εικοστή Πέμπτη Μαρτίου" +msgstr "" + +#. Easter Monday. +#: holidays/countries/greece.py:52 +msgid "Δευτέρα του Πάσχα" +msgstr "" + +#. Monday of the Holy Spirit. +#: holidays/countries/greece.py:55 +msgid "Δευτέρα του Αγίου Πνεύματος" +msgstr "" + +#. Labour Day. +#: holidays/countries/greece.py:60 +msgid "Εργατική Πρωτομαγιά" +msgstr "" + +#: holidays/countries/greece.py:61 +#, c-format +msgid "%s (παρατηρήθηκε)" +msgstr "" + +#. Assumption of Mary. +#: holidays/countries/greece.py:74 +msgid "Κοίμηση της Θεοτόκου" +msgstr "" + +#. Ochi Day. +#: holidays/countries/greece.py:77 +msgid "Ημέρα του Όχι" +msgstr "" + +#. Christmas Day. +#: holidays/countries/greece.py:80 +msgid "Χριστούγεννα" +msgstr "" + +#. Day after Christmas. +#: holidays/countries/greece.py:83 +msgid "Επόμενη ημέρα των Χριστουγέννων" +msgstr "" diff --git a/holidays/locale/en/LC_MESSAGES/CA.po b/holidays/locale/en/LC_MESSAGES/CA.po new file mode 100644 index 000000000..35ac40aba --- /dev/null +++ b/holidays/locale/en/LC_MESSAGES/CA.po @@ -0,0 +1,150 @@ +# Canada holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:30-0800\n" +"PO-Revision-Date: 2023-02-16 08:51-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/canada.py:63 +msgid "New Year's Day" +msgstr "" + +#: holidays/countries/canada.py:67 holidays/countries/canada.py:168 +#: holidays/countries/canada.py:192 holidays/countries/canada.py:201 +#: holidays/countries/canada.py:278 holidays/countries/canada.py:285 +#: holidays/countries/canada.py:292 +#, c-format +msgid "%s (Observed)" +msgstr "" + +#: holidays/countries/canada.py:78 holidays/countries/canada.py:83 +#: holidays/countries/canada.py:87 +msgid "Family Day" +msgstr "" + +#: holidays/countries/canada.py:91 +msgid "Louis Riel Day" +msgstr "" + +#: holidays/countries/canada.py:95 holidays/countries/canada.py:99 +msgid "Islander Day" +msgstr "" + +#. Heritage Day. +#: holidays/countries/canada.py:105 holidays/countries/canada.py:124 +#: holidays/countries/canada.py:213 +msgid "Heritage Day" +msgstr "" + +#. St. Patrick's Day. +#: holidays/countries/canada.py:131 +msgid "St. Patrick's Day" +msgstr "" + +#. Good Friday. +#: holidays/countries/canada.py:135 +msgid "Good Friday" +msgstr "" + +#. Easter Monday. +#: holidays/countries/canada.py:137 +msgid "Easter Monday" +msgstr "" + +#: holidays/countries/canada.py:148 +msgid "St. George's Day" +msgstr "" + +#: holidays/countries/canada.py:154 +msgid "Victoria Day" +msgstr "" + +#: holidays/countries/canada.py:156 +msgid "National Patriots' Day" +msgstr "" + +#: holidays/countries/canada.py:160 +msgid "National Aboriginal Day" +msgstr "" + +#: holidays/countries/canada.py:164 +msgid "St. Jean Baptiste Day" +msgstr "" + +#: holidays/countries/canada.py:174 holidays/countries/canada.py:176 +msgid "Discovery Day" +msgstr "" + +#: holidays/countries/canada.py:183 +msgid "Memorial Day" +msgstr "" + +#: holidays/countries/canada.py:185 +msgid "Canada Day" +msgstr "" + +#: holidays/countries/canada.py:188 +msgid "Dominion Day" +msgstr "" + +#: holidays/countries/canada.py:196 +msgid "Nunavut Day" +msgstr "" + +#: holidays/countries/canada.py:207 +msgid "Civic Holiday" +msgstr "" + +#. British Columbia Day. +#: holidays/countries/canada.py:217 +msgid "British Columbia Day" +msgstr "" + +#: holidays/countries/canada.py:222 +msgid "New Brunswick Day" +msgstr "" + +#: holidays/countries/canada.py:227 +msgid "Saskatchewan Day" +msgstr "" + +#: holidays/countries/canada.py:233 +msgid "Labour Day" +msgstr "" + +#: holidays/countries/canada.py:246 +msgid "Funeral of Her Majesty the Queen Elizabeth II" +msgstr "" + +#: holidays/countries/canada.py:252 +msgid "National Day for Truth and Reconciliation" +msgstr "" + +#: holidays/countries/canada.py:262 holidays/countries/canada.py:264 +msgid "Thanksgiving" +msgstr "" + +#: holidays/countries/canada.py:270 +msgid "Remembrance Day" +msgstr "" + +#. Christmas Day, +#: holidays/countries/canada.py:281 +msgid "Christmas Day" +msgstr "" + +#. Boxing Day. +#: holidays/countries/canada.py:288 +msgid "Boxing Day" +msgstr "" diff --git a/holidays/locale/en_US/LC_MESSAGES/AM.po b/holidays/locale/en_US/LC_MESSAGES/AM.po new file mode 100644 index 000000000..ea97b1df0 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/AM.po @@ -0,0 +1,92 @@ +# Armenia holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 20:06-0800\n" +"PO-Revision-Date: 2023-02-15 11:03-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/armenia.py:38 +msgid "Նոր տարվա օր" +msgstr "New Year's Day" + +#. Christmas and Epiphany Day. +#: holidays/countries/armenia.py:43 +msgid "Սուրբ Ծնունդ եւ Հայտնություն" +msgstr "Christmas and Epiphany Day" + +#. Christmas Eve. +#: holidays/countries/armenia.py:50 +msgid "Սուրբ Ծննդյան տոներ" +msgstr "Christmas Holidays" + +#. The Day of Remembrance of the Dead. +#: holidays/countries/armenia.py:53 +msgid "Մեռելոց հիշատակի օր" +msgstr "Memorial Day" + +#. Army Day. +#: holidays/countries/armenia.py:57 +msgid "Բանակի օր" +msgstr "Army Day" + +#. Women's Day. +#: holidays/countries/armenia.py:60 +msgid "Կանանց տոն" +msgstr "Women’s Day" + +#. Motherhood and Beauty Day. +#: holidays/countries/armenia.py:64 +msgid "Մայրության և գեղեցկության տոն" +msgstr "A Holiday of Motherhood and Beauty" + +#. Armenian Genocide Remembrance Day, +#: holidays/countries/armenia.py:67 +msgid "Եղեռնի զոհերի հիշատակի օր" +msgstr "Genocide Memorial Day" + +#. International Day of Workers' Solidarity. +#: holidays/countries/armenia.py:71 +msgid "Աշխատավորների համերաշխության միջազգային օր" +msgstr "International Day of Workers' Solidarity" + +#. Labor Day. +#: holidays/countries/armenia.py:74 +msgid "Աշխատանքի օր" +msgstr "Labor day" + +#. Victory and Peace Day. +#: holidays/countries/armenia.py:79 +msgid "Հաղթանակի և Խաղաղության տոն" +msgstr "Victory and Peace Day" + +#. Republic Day. +#: holidays/countries/armenia.py:82 +msgid "Հանրապետության օր" +msgstr "Republic Day" + +#. Constitution Day. +#: holidays/countries/armenia.py:86 +msgid "Սահմանադրության օր" +msgstr "Constitution Day" + +#. Independence Day. +#: holidays/countries/armenia.py:90 +msgid "Անկախության օր" +msgstr "Independence Day" + +#. New Year's Eve. +#: holidays/countries/armenia.py:93 +msgid "Նոր տարվա գիշեր" +msgstr "New Year's Eve" diff --git a/holidays/locale/en_US/LC_MESSAGES/AR.po b/holidays/locale/en_US/LC_MESSAGES/AR.po new file mode 100644 index 000000000..424758ec3 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/AR.po @@ -0,0 +1,100 @@ +# Argentina holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2022-12-15 21:42-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/argentina.py:41 +msgid "Año Nuevo" +msgstr "New Year's Day" + +#. Carnival days +#: holidays/countries/argentina.py:45 +msgid "Día de Carnaval" +msgstr "Carnival" + +#. Memory's National Day for the Truth and Justice +#: holidays/countries/argentina.py:50 +msgid "Día Nacional de la Memoria por la Verdad y la Justicia" +msgstr "Memory's National Day for the Truth and Justice" + +#. Holy Week +#: holidays/countries/argentina.py:60 +msgid "Semana Santa (Jueves Santo)" +msgstr "Holy Thursday" + +#: holidays/countries/argentina.py:61 +msgid "Semana Santa (Viernes Santo)" +msgstr "Holy Friday" + +#: holidays/countries/argentina.py:62 +msgid "Día de Pascuas" +msgstr "Easter Sunday" + +#: holidays/countries/argentina.py:76 +msgid "Día del Veterano y de los Caidos en la Guerra de Malvinas" +msgstr "Veterans Day and the Fallen in the Malvinas War" + +#. Labor Day +#: holidays/countries/argentina.py:81 +msgid "Día del Trabajo" +msgstr "Labor Day" + +#. May Revolution Day +#: holidays/countries/argentina.py:88 +msgid "Día de la Revolución de Mayo" +msgstr "May Revolution Day" + +#. Day Pass to the Immortality of General Martín Miguel de Güemes. +#: holidays/countries/argentina.py:95 +msgid "Día Pase a la Inmortalidad del General Martín Miguel de Güemes" +msgstr "Day Pass to the Immortality of General Martín Miguel de Güemes" + +#. Day Pass to the Immortality of General D. Manuel Belgrano. +#: holidays/countries/argentina.py:104 +msgid "Día Pase a la Inmortalidad del General D. Manuel Belgrano" +msgstr "Day Pass to the Immortality of General D. Manuel Belgrano" + +#. Independence Day +#: holidays/countries/argentina.py:113 +msgid "Día de la Independencia" +msgstr "Independence Day" + +#. Day Pass to the Immortality of General D. José de San Martin +#: holidays/countries/argentina.py:120 +msgid "Día Pase a la Inmortalidad del General D. José de San Martin" +msgstr "Day Pass to the Immortality of General D. José de San Martin" + +#: holidays/countries/argentina.py:132 +msgid "Día de la Raza" +msgstr "Columbus day" + +#: holidays/countries/argentina.py:134 +msgid "Día del Respeto a la Diversidad Cultural" +msgstr "Respect for Cultural Diversity Day" + +#. National Sovereignty Day +#: holidays/countries/argentina.py:138 +msgid "Día Nacional de la Soberanía" +msgstr "National Sovereignty Day" + +#: holidays/countries/argentina.py:148 +msgid "La Inmaculada Concepción" +msgstr "Immaculate Conception" + +#. Christmas +#: holidays/countries/argentina.py:151 +msgid "Navidad" +msgstr "Christmas" diff --git a/holidays/locale/en_US/LC_MESSAGES/BG.po b/holidays/locale/en_US/LC_MESSAGES/BG.po new file mode 100644 index 000000000..d82240b70 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/BG.po @@ -0,0 +1,86 @@ +# Bulgaria holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-14 17:56-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/bulgaria.py:52 +msgid "Нова година" +msgstr "New Year's Day" + +#. Liberation Day. +#: holidays/countries/bulgaria.py:55 +msgid "Ден на Освобождението на България от османско иго" +msgstr "Liberation Day" + +#. International Workers' Day. +#: holidays/countries/bulgaria.py:60 +msgid "Ден на труда и на международната работническа солидарност" +msgstr "Labour Day and International Workers' Solidarity Day" + +#. Saint George's Day. +#: holidays/countries/bulgaria.py:65 +msgid "Гергьовден, Ден на храбростта и Българската армия" +msgstr "St. George's Day (Day of the Bulgarian Army)" + +#. Bulgarian Education and Culture and Slavonic Literature Day. +#: holidays/countries/bulgaria.py:70 +msgid "" +"Ден на светите братя Кирил и Методий, на българската азбука, просвета и " +"култура и на славянската книжовност" +msgstr "Day of Slavonic Alphabet, Bulgarian Enlightenment and Culture" + +#. Unification Day. +#: holidays/countries/bulgaria.py:76 +msgid "Ден на Съединението" +msgstr "Unification Day" + +#. Independence Day. +#: holidays/countries/bulgaria.py:79 +msgid "Ден на Независимостта на България" +msgstr "Independence Day" + +#. National Awakening Day. +#: holidays/countries/bulgaria.py:84 +msgid "Ден на народните будители" +msgstr "The Day of the People's Awakeners" + +#. Christmas Eve. +#: holidays/countries/bulgaria.py:87 +msgid "Бъдни вечер" +msgstr "Christmas Eve" + +#. Christmas Day 1. +#. Christmas Day 2. +#: holidays/countries/bulgaria.py:89 holidays/countries/bulgaria.py:91 +msgid "Рождество Христово" +msgstr "Christmas Day" + +#. Good Friday. +#: holidays/countries/bulgaria.py:96 +msgid "Велики петък" +msgstr "Orthodox Good Friday" + +#. Easter Saturday. +#: holidays/countries/bulgaria.py:98 +msgid "Велика събота" +msgstr "Orthodox Easter Saturday" + +#. Easter Sunday. +#. Easter Monday. +#: holidays/countries/bulgaria.py:100 holidays/countries/bulgaria.py:102 +msgid "Великден" +msgstr "Orthodox Easter" diff --git a/holidays/locale/en_US/LC_MESSAGES/BY.po b/holidays/locale/en_US/LC_MESSAGES/BY.po new file mode 100644 index 000000000..774c9fcfd --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/BY.po @@ -0,0 +1,61 @@ +# Belarus holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 20:06-0800\n" +"PO-Revision-Date: 2023-02-14 17:52-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/belarus.py:42 +msgid "Новы год" +msgstr "New Year's Day" + +#. Christmas Day (Orthodox). +#: holidays/countries/belarus.py:51 +msgid "Нараджэнне Хрыстова (праваслаўнае Раство)" +msgstr "Orthodox Christmas Day" + +#. Women's Day. +#: holidays/countries/belarus.py:56 +msgid "Дзень жанчын" +msgstr "Women's Day" + +#. Radunitsa (Day of Rejoicing). +#: holidays/countries/belarus.py:59 +msgid "Радаўніца" +msgstr "Radunitsa" + +#. Labour Day. +#: holidays/countries/belarus.py:64 +msgid "Свята працы" +msgstr "Labor Day" + +#. Victory Day +#: holidays/countries/belarus.py:67 +msgid "Дзень Перамогі" +msgstr "Victory Day" + +#. Independence Day. +#: holidays/countries/belarus.py:70 +msgid "Дзень Незалежнасці Рэспублікі Беларусь (Дзень Рэспублікі)" +msgstr "Independence Day (Republic Day)" + +#. October Revolution Day. +#: holidays/countries/belarus.py:75 +msgid "Дзень Кастрычніцкай рэвалюцыі" +msgstr "October Revolution Day" + +#. Christmas Day (Catholic). +#: holidays/countries/belarus.py:78 +msgid "Нараджэнне Хрыстова (каталіцкае Раство)" +msgstr "Catholic Christmas Day" diff --git a/holidays/locale/en_US/LC_MESSAGES/CA.po b/holidays/locale/en_US/LC_MESSAGES/CA.po new file mode 100644 index 000000000..b40c8508a --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/CA.po @@ -0,0 +1,150 @@ +# Canada holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:30-0800\n" +"PO-Revision-Date: 2023-02-16 08:52-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/canada.py:63 +msgid "New Year's Day" +msgstr "" + +#: holidays/countries/canada.py:67 holidays/countries/canada.py:168 +#: holidays/countries/canada.py:192 holidays/countries/canada.py:201 +#: holidays/countries/canada.py:278 holidays/countries/canada.py:285 +#: holidays/countries/canada.py:292 +#, c-format +msgid "%s (Observed)" +msgstr "" + +#: holidays/countries/canada.py:78 holidays/countries/canada.py:83 +#: holidays/countries/canada.py:87 +msgid "Family Day" +msgstr "" + +#: holidays/countries/canada.py:91 +msgid "Louis Riel Day" +msgstr "" + +#: holidays/countries/canada.py:95 holidays/countries/canada.py:99 +msgid "Islander Day" +msgstr "" + +#. Heritage Day. +#: holidays/countries/canada.py:105 holidays/countries/canada.py:124 +#: holidays/countries/canada.py:213 +msgid "Heritage Day" +msgstr "" + +#. St. Patrick's Day. +#: holidays/countries/canada.py:131 +msgid "St. Patrick's Day" +msgstr "" + +#. Good Friday. +#: holidays/countries/canada.py:135 +msgid "Good Friday" +msgstr "" + +#. Easter Monday. +#: holidays/countries/canada.py:137 +msgid "Easter Monday" +msgstr "" + +#: holidays/countries/canada.py:148 +msgid "St. George's Day" +msgstr "" + +#: holidays/countries/canada.py:154 +msgid "Victoria Day" +msgstr "" + +#: holidays/countries/canada.py:156 +msgid "National Patriots' Day" +msgstr "" + +#: holidays/countries/canada.py:160 +msgid "National Aboriginal Day" +msgstr "" + +#: holidays/countries/canada.py:164 +msgid "St. Jean Baptiste Day" +msgstr "" + +#: holidays/countries/canada.py:174 holidays/countries/canada.py:176 +msgid "Discovery Day" +msgstr "" + +#: holidays/countries/canada.py:183 +msgid "Memorial Day" +msgstr "" + +#: holidays/countries/canada.py:185 +msgid "Canada Day" +msgstr "" + +#: holidays/countries/canada.py:188 +msgid "Dominion Day" +msgstr "" + +#: holidays/countries/canada.py:196 +msgid "Nunavut Day" +msgstr "" + +#: holidays/countries/canada.py:207 +msgid "Civic Holiday" +msgstr "" + +#. British Columbia Day. +#: holidays/countries/canada.py:217 +msgid "British Columbia Day" +msgstr "" + +#: holidays/countries/canada.py:222 +msgid "New Brunswick Day" +msgstr "" + +#: holidays/countries/canada.py:227 +msgid "Saskatchewan Day" +msgstr "" + +#: holidays/countries/canada.py:233 +msgid "Labour Day" +msgstr "" + +#: holidays/countries/canada.py:246 +msgid "Funeral of Her Majesty the Queen Elizabeth II" +msgstr "" + +#: holidays/countries/canada.py:252 +msgid "National Day for Truth and Reconciliation" +msgstr "" + +#: holidays/countries/canada.py:262 holidays/countries/canada.py:264 +msgid "Thanksgiving" +msgstr "" + +#: holidays/countries/canada.py:270 +msgid "Remembrance Day" +msgstr "" + +#. Christmas Day, +#: holidays/countries/canada.py:281 +msgid "Christmas Day" +msgstr "" + +#. Boxing Day. +#: holidays/countries/canada.py:288 +msgid "Boxing Day" +msgstr "" diff --git a/holidays/locale/en_US/LC_MESSAGES/CY.po b/holidays/locale/en_US/LC_MESSAGES/CY.po new file mode 100644 index 000000000..8d8be9158 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/CY.po @@ -0,0 +1,97 @@ +# Cyprus holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 11:50-0800\n" +"PO-Revision-Date: 2023-02-15 11:58-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Years Day. +#: holidays/countries/cyprus.py:38 +msgid "Πρωτοχρονιά" +msgstr "New Year's Day" + +#. Epiphany. +#: holidays/countries/cyprus.py:41 +msgid "Θεοφάνεια" +msgstr "Epiphany" + +#. Clean Monday. +#: holidays/countries/cyprus.py:44 +msgid "Καθαρά Δευτέρα" +msgstr "Clean Monday" + +#. Greek Independence Day. +#: holidays/countries/cyprus.py:47 +msgid "Εικοστή Πέμπτη Μαρτίου" +msgstr "Greek Independence Day" + +#. Cyprus National Day. +#: holidays/countries/cyprus.py:50 +msgid "1η Απριλίου" +msgstr "Cyprus National Day" + +#. Good Friday. +#: holidays/countries/cyprus.py:53 +msgid "Μεγάλη Παρασκευή" +msgstr "Good Friday" + +#. Easter Sunday. +#: holidays/countries/cyprus.py:56 +msgid "Κυριακή του Πάσχα" +msgstr "Easter Sunday" + +#. Easter Monday. +#: holidays/countries/cyprus.py:59 +msgid "Δευτέρα του Πάσχα" +msgstr "Easter Monday" + +#. Labour Day. +#: holidays/countries/cyprus.py:62 +msgid "Εργατική Πρωτομαγιά" +msgstr "Labor Day" + +#. Monday of the Holy Spirit. +#: holidays/countries/cyprus.py:65 +msgid "Δευτέρα του Αγίου Πνεύματος" +msgstr "Monday of the Holy Spirit" + +#. Assumption of Mary. +#: holidays/countries/cyprus.py:70 +msgid "Κοίμηση της Θεοτόκου" +msgstr "Assumption of Mary" + +#. Cyprus Independence Day. +#: holidays/countries/cyprus.py:73 +msgid "Ημέρα Ανεξαρτησίας της Κύπρου" +msgstr "Cyprus Independence Day" + +#. Ochi Day. +#: holidays/countries/cyprus.py:76 +msgid "Ημέρα του Όχι" +msgstr "Ochi Day" + +#. Christmas Eve. +#: holidays/countries/cyprus.py:79 +msgid "Παραμονή Χριστουγέννων" +msgstr "Christmas Eve" + +#. Christmas Day. +#: holidays/countries/cyprus.py:82 +msgid "Χριστούγεννα" +msgstr "Christmas Day" + +#. Day After Christmas. +#: holidays/countries/cyprus.py:85 +msgid "Δεύτερη μέρα Χριστουγέννων" +msgstr "Day After Christmas" diff --git a/holidays/locale/en_US/LC_MESSAGES/DK.po b/holidays/locale/en_US/LC_MESSAGES/DK.po new file mode 100644 index 000000000..797d43d7d --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/DK.po @@ -0,0 +1,64 @@ +# Denmark holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2022-12-16 12:25-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/denmark.py:36 +msgid "Nytårsdag" +msgstr "New Year's Day" + +#: holidays/countries/denmark.py:37 +msgid "Palmesøndag" +msgstr "Palm Sunday" + +#: holidays/countries/denmark.py:38 +msgid "Skærtorsdag" +msgstr "Maundy Thursday" + +#: holidays/countries/denmark.py:39 +msgid "Langfredag" +msgstr "Good Friday" + +#: holidays/countries/denmark.py:40 +msgid "Påskedag" +msgstr "Easter Sunday" + +#: holidays/countries/denmark.py:41 +msgid "Anden påskedag" +msgstr "Easter Monday" + +#: holidays/countries/denmark.py:42 +msgid "Store bededag" +msgstr "Great day of prayer" + +#: holidays/countries/denmark.py:43 +msgid "Kristi himmelfartsdag" +msgstr "Ascension Day" + +#: holidays/countries/denmark.py:44 +msgid "Pinsedag" +msgstr "Whit Sunday" + +#: holidays/countries/denmark.py:45 +msgid "Anden pinsedag" +msgstr "Whit Monday" + +#: holidays/countries/denmark.py:46 +msgid "Juledag" +msgstr "Christmas Day" + +#: holidays/countries/denmark.py:47 +msgid "Anden juledag" +msgstr "Boxing Day" diff --git a/holidays/locale/en_US/LC_MESSAGES/ET.po b/holidays/locale/en_US/LC_MESSAGES/ET.po new file mode 100644 index 000000000..a04873bda --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/ET.po @@ -0,0 +1,87 @@ +# Ethiopia holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:15-0800\n" +"PO-Revision-Date: 2023-02-15 12:42-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n==0 || n==1);\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. Ethiopian New Year. +#: holidays/countries/ethiopia.py:64 holidays/countries/ethiopia.py:67 +msgid "አዲስ ዓመት እንቁጣጣሽ" +msgstr "Ethiopian New Year's Day" + +#. Finding of True Cross. +#: holidays/countries/ethiopia.py:72 holidays/countries/ethiopia.py:75 +msgid "መስቀል" +msgstr "Finding of True Cross" + +#. Orthodox Christmas. +#: holidays/countries/ethiopia.py:78 +msgid "ገና" +msgstr "Orthodox Christmas Day" + +#. Orthodox Epiphany. +#: holidays/countries/ethiopia.py:81 +msgid "ጥምቀት" +msgstr "Orthodox Epiphany Day" + +#. Orthodox Good Friday. +#: holidays/countries/ethiopia.py:85 +msgid "ስቅለት" +msgstr "Orthodox Good Friday" + +#. Orthodox Easter Sunday. +#: holidays/countries/ethiopia.py:88 +msgid "ፋሲካ" +msgstr "Orthodox Easter Sunday" + +#. Adwa Victory Day. +#: holidays/countries/ethiopia.py:92 +msgid "አድዋ" +msgstr "Adwa Victory Day" + +#. Labour Day. +#: holidays/countries/ethiopia.py:95 +msgid "የሰራተኞች ቀን" +msgstr "Labor Day" + +#. Patriots Day. +#: holidays/countries/ethiopia.py:99 +msgid "የአርበኞች ቀን" +msgstr "Patriots Day" + +#. Downfall of Dergue Regime Day. +#: holidays/countries/ethiopia.py:103 +msgid "ደርግ የወደቀበት ቀን" +msgstr "Downfall of Dergue Regime Day" + +#. Downfall of King Haile Selassie. +#: holidays/countries/ethiopia.py:107 +msgid "ደርግ የመጣበት ቀን" +msgstr "Downfall of King Haile Selassie Day" + +#. Eid al-Fitr. +#: holidays/countries/ethiopia.py:121 +msgid "ኢድ አልፈጥር" +msgstr "Eid al-Fitr" + +#. Eid al-Adha. +#: holidays/countries/ethiopia.py:128 +msgid "አረፋ" +msgstr "Eid al-Adha" + +#. Prophet Muhammad's Birthday. +#: holidays/countries/ethiopia.py:134 +msgid "መውሊድ" +msgstr "Prophet Muhammad's Birthday" diff --git a/holidays/locale/en_US/LC_MESSAGES/GE.po b/holidays/locale/en_US/LC_MESSAGES/GE.po new file mode 100644 index 000000000..5b66f02bd --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/GE.po @@ -0,0 +1,101 @@ +# Georgia holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:15-0800\n" +"PO-Revision-Date: 2023-02-15 14:21-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/georgia.py:36 +msgid "ახალი წელი" +msgstr "New Year's Day" + +#. New Year's Day. +#: holidays/countries/georgia.py:39 +msgid "ბედობა" +msgstr "New Year's Day" + +#. Orthodox Christmas Day. +#: holidays/countries/georgia.py:42 +msgid "ქრისტეშობა" +msgstr "Orthodox Christmas Day" + +#. Baptism Day of our Lord Jesus Christ. +#: holidays/countries/georgia.py:45 +msgid "ნათლისღება" +msgstr "Epiphany Day" + +#. Mother's Day. +#: holidays/countries/georgia.py:48 +msgid "დედის დღე" +msgstr "Mother's Day" + +#. Women's Day. +#: holidays/countries/georgia.py:51 +msgid "ქალთა საერთაშორისო დღე" +msgstr "International Women's ay" + +#. Orthodox Good Friday. +#: holidays/countries/georgia.py:55 +msgid "წითელი პარასკევი" +msgstr "Orthodox Good Friday" + +#. Orthodox Holy Saturday. +#: holidays/countries/georgia.py:58 +msgid "დიდი შაბათი" +msgstr "Orthodox Holy Saturday" + +#. Orthodox Easter Sunday. +#: holidays/countries/georgia.py:61 +msgid "აღდგომა" +msgstr "Orthodox Easter Sunday" + +#. Orthodox Easter Monday. +#: holidays/countries/georgia.py:64 +msgid "შავი ორშაბათი" +msgstr "Orthodox Easter Monday" + +#. National Unity Day. +#: holidays/countries/georgia.py:67 +msgid "ეროვნული ერთიანობის დღე" +msgstr "National Unity Day" + +#. Day of Victory. +#: holidays/countries/georgia.py:70 +msgid "ფაშიზმზე გამარჯვების დღე" +msgstr "Day of Victory over Fascism" + +#. Saint Andrew the First-Called Day. +#: holidays/countries/georgia.py:73 +msgid "წმინდა ანდრია პირველწოდებულის დღე" +msgstr "St. Andrew's Day" + +#. Independence Day. +#: holidays/countries/georgia.py:78 +msgid "დამოუკიდებლობის დღე" +msgstr "Independence Day" + +#. Saint Mary's Day. +#: holidays/countries/georgia.py:81 +msgid "მარიამობა" +msgstr "Saint Mary's Day" + +#. Day of Svetitskhoveli Cathedral. +#: holidays/countries/georgia.py:84 +msgid "სვეტიცხოვლობა" +msgstr "Day of Svetitskhoveli Cathedral" + +#. Saint George's Day. +#: holidays/countries/georgia.py:87 +msgid "გიორგობა" +msgstr "Saint George's Day" diff --git a/holidays/locale/en_US/LC_MESSAGES/GR.po b/holidays/locale/en_US/LC_MESSAGES/GR.po new file mode 100644 index 000000000..9780540b7 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/GR.po @@ -0,0 +1,76 @@ +# Greece holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:53-0800\n" +"PO-Revision-Date: 2023-02-15 14:59-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/greece.py:40 +msgid "Πρωτοχρονιά" +msgstr "New Year’s Day" + +#. Epiphany. +#: holidays/countries/greece.py:43 +msgid "Θεοφάνεια" +msgstr "Epiphany" + +#. Clean Monday. +#: holidays/countries/greece.py:46 +msgid "Καθαρά Δευτέρα" +msgstr "Clean Monday" + +#. Independence Day. +#: holidays/countries/greece.py:49 +msgid "Εικοστή Πέμπτη Μαρτίου" +msgstr "Independence Day" + +#. Easter Monday. +#: holidays/countries/greece.py:52 +msgid "Δευτέρα του Πάσχα" +msgstr "Easter Monday" + +#. Monday of the Holy Spirit. +#: holidays/countries/greece.py:55 +msgid "Δευτέρα του Αγίου Πνεύματος" +msgstr "Easter Monday" + +#. Labour Day. +#: holidays/countries/greece.py:60 +msgid "Εργατική Πρωτομαγιά" +msgstr "Labor Day" + +#: holidays/countries/greece.py:61 +#, c-format +msgid "%s (παρατηρήθηκε)" +msgstr "%s (Observed)" + +#. Assumption of Mary. +#: holidays/countries/greece.py:74 +msgid "Κοίμηση της Θεοτόκου" +msgstr "Assumption of Mary Day" + +#. Ochi Day. +#: holidays/countries/greece.py:77 +msgid "Ημέρα του Όχι" +msgstr "Ochi Day" + +#. Christmas Day. +#: holidays/countries/greece.py:80 +msgid "Χριστούγεννα" +msgstr "Christmas Day" + +#. Day after Christmas. +#: holidays/countries/greece.py:83 +msgid "Επόμενη ημέρα των Χριστουγέννων" +msgstr "Day After Christmas" diff --git a/holidays/locale/en_US/LC_MESSAGES/JP.po b/holidays/locale/en_US/LC_MESSAGES/JP.po new file mode 100644 index 000000000..dd43ea735 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/JP.po @@ -0,0 +1,127 @@ +# Japan holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE 1.0\n" +"POT-Creation-Date: 2023-02-15 08:36-0800\n" +"PO-Revision-Date: 2023-02-14 19:19-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. The Crown Prince marriage ceremony. +#: holidays/countries/japan.py:35 holidays/countries/japan.py:38 +msgid "結婚の儀" +msgstr "The Crown Prince Marriage Ceremony" + +#. State Funeral of Emperor Shōwa. +#: holidays/countries/japan.py:36 +msgid "大喪の礼" +msgstr "Emperor Shōwa Funeral Ceremony" + +#. Enthronement ceremony. +#: holidays/countries/japan.py:37 +msgid "即位礼正殿の儀" +msgstr "Enthronement Ceremony" + +#. Enthronement day. +#: holidays/countries/japan.py:40 +msgid "天皇の即位の日" +msgstr "Emperor's Enthronement Day" + +#. Enthronement ceremony. +#: holidays/countries/japan.py:41 +msgid "即位礼正殿の儀が行われる日" +msgstr "Emperor's Enthronement Day" + +#. New Year's Day. +#: holidays/countries/japan.py:52 +msgid "元日" +msgstr "New Year's Day" + +#. Coming of Age Day. +#: holidays/countries/japan.py:60 +msgid "成人の日" +msgstr "Coming of Age Day" + +#: holidays/countries/japan.py:64 +msgid "建国記念の日" +msgstr "Foundation Day" + +#: holidays/countries/japan.py:68 holidays/countries/japan.py:80 +#: holidays/countries/japan.py:148 +msgid "天皇誕生日" +msgstr "Emperor's Birthday" + +#: holidays/countries/japan.py:76 +msgid "春分の日" +msgstr "Vernal Equinox Day" + +#: holidays/countries/japan.py:82 holidays/countries/japan.py:91 +msgid "みどりの日" +msgstr "Greenery Day" + +#: holidays/countries/japan.py:84 +msgid "昭和の日" +msgstr "Showa Day" + +#. Constitution Memorial Day. +#: holidays/countries/japan.py:87 +msgid "憲法記念日" +msgstr "Constitution Day" + +#. Children's Day. +#: holidays/countries/japan.py:94 +msgid "こどもの日" +msgstr "Children's Day" + +#: holidays/countries/japan.py:98 holidays/countries/japan.py:100 +#: holidays/countries/japan.py:102 holidays/countries/japan.py:104 +msgid "海の日" +msgstr "Marine Day" + +#: holidays/countries/japan.py:108 holidays/countries/japan.py:110 +#: holidays/countries/japan.py:112 +msgid "山の日" +msgstr "Mountain Day" + +#: holidays/countries/japan.py:116 holidays/countries/japan.py:118 +msgid "敬老の日" +msgstr "Respect for the Aged Day" + +#: holidays/countries/japan.py:126 +msgid "秋分の日" +msgstr "Autumnal Equinox" + +#: holidays/countries/japan.py:130 holidays/countries/japan.py:132 +msgid "体育の日" +msgstr "Sports Day" + +#: holidays/countries/japan.py:134 holidays/countries/japan.py:136 +#: holidays/countries/japan.py:138 +msgid "スポーツの日" +msgstr "Sports Day" + +#. Culture Day. +#: holidays/countries/japan.py:141 +msgid "文化の日" +msgstr "Culture Day" + +#. Labour Thanksgiving Day. +#: holidays/countries/japan.py:144 +msgid "勤労感謝の日" +msgstr "Labor Thanksgiving Day" + +#: holidays/countries/japan.py:158 +msgid "振替休日" +msgstr "Substitute Holiday" + +#: holidays/countries/japan.py:166 +msgid "国民の休日" +msgstr "National Holiday" diff --git a/holidays/locale/en_US/LC_MESSAGES/PL.po b/holidays/locale/en_US/LC_MESSAGES/PL.po new file mode 100644 index 000000000..a55edc1a7 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/PL.po @@ -0,0 +1,102 @@ +# Poland holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2022-12-07 18:43-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.2.2\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: holidays/countries/poland.py:30 +msgid "Narodowe Święto Niepodległości - 100-lecie" +msgstr "National Independence Day - 100th anniversary" + +#: holidays/countries/poland.py:39 +msgid "Nowy Rok" +msgstr "New Year's Day" + +#: holidays/countries/poland.py:42 +msgid "Święto Trzech Króli" +msgstr "Epiphany" + +#: holidays/countries/poland.py:45 +msgid "Oczyszczenie Najświętszej Marii Panny" +msgstr "Purification of the Blessed Virgin Mary" + +#: holidays/countries/poland.py:50 +msgid "Niedziela Wielkanocna" +msgstr "Easter Sunday" + +#: holidays/countries/poland.py:52 +msgid "Poniedziałek Wielkanocny" +msgstr "Easter Monday" + +#: holidays/countries/poland.py:55 +msgid "Święto Państwowe" +msgstr "National Day" + +#: holidays/countries/poland.py:58 +msgid "Święto Narodowe Trzeciego Maja" +msgstr "National Day of the Third of May" + +#: holidays/countries/poland.py:63 +msgid "Narodowe Święto Zwycięstwa i Wolności" +msgstr "National Victory and Freedom Day" + +#: holidays/countries/poland.py:68 +msgid "Wniebowstąpienie Pańskie" +msgstr "Ascension Day" + +#: holidays/countries/poland.py:72 +msgid "Zielone Świątki" +msgstr "Pentecost" + +#: holidays/countries/poland.py:75 +msgid "Drugi dzień Zielonych Świątek" +msgstr "Pentecost (Day 2)" + +#: holidays/countries/poland.py:79 +msgid "Dzień Bożego Ciała" +msgstr "Corpus Christi" + +#: holidays/countries/poland.py:82 +msgid "Uroczystość Świętych Apostołów Piotra i Pawła" +msgstr "Saints Peter and Paul Day" + +#: holidays/countries/poland.py:87 +msgid "Narodowe Święto Odrodzenia Polski" +msgstr "National Day of Rebirth of Poland" + +#: holidays/countries/poland.py:92 +msgid "Wniebowzięcie Najświętszej Marii Panny" +msgstr "Assumption of the Virgin Mary" + +#: holidays/countries/poland.py:96 +msgid "Uroczystość Wszystkich Świętych" +msgstr "All Saints' Day" + +#: holidays/countries/poland.py:99 +msgid "Narodowe Święto Niepodległości" +msgstr "National Independence Day" + +#: holidays/countries/poland.py:104 +msgid "Niepokalane Poczęcie Najświętszej Marii Panny" +msgstr "Immaculate Conception of the Blessed Virgin Mary" + +#: holidays/countries/poland.py:108 +msgid "Boże Narodzenie (pierwszy dzień)" +msgstr "Christmas (Day 1)" + +#: holidays/countries/poland.py:109 +msgid "Boże Narodzenie (drugi dzień)" +msgstr "Christmas (Day 2)" diff --git a/holidays/locale/en_US/LC_MESSAGES/RS.po b/holidays/locale/en_US/LC_MESSAGES/RS.po new file mode 100644 index 000000000..afe232729 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/RS.po @@ -0,0 +1,68 @@ +# Serbia holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 15:18-0800\n" +"PO-Revision-Date: 2023-02-15 15:21-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/serbia.py:36 +msgid "Нова година" +msgstr "New Year's Day" + +#: holidays/countries/serbia.py:40 holidays/countries/serbia.py:50 +#: holidays/countries/serbia.py:60 holidays/countries/serbia.py:62 +#: holidays/countries/serbia.py:68 +#, c-format +msgid "%s (Слободан дан)" +msgstr "%s (Observed)" + +#. Orthodox Christmas. +#: holidays/countries/serbia.py:43 +msgid "Божић" +msgstr "Orthodox Christmas Day" + +#. Statehood Day. +#: holidays/countries/serbia.py:46 +msgid "Дан државности Србије" +msgstr "Statehood Day" + +#. International Workers' Day. +#: holidays/countries/serbia.py:55 +msgid "Празник рада" +msgstr "International Workers' Day" + +#. Armistice Day. +#: holidays/countries/serbia.py:65 +msgid "Дан примирја у Првом светском рату" +msgstr "Armistice Day" + +#. Good Friday. +#: holidays/countries/serbia.py:71 +msgid "Велики петак" +msgstr "Good Friday" + +#. Easter Saturday. +#: holidays/countries/serbia.py:73 +msgid "Велика субота" +msgstr "Easter Saturday" + +#. Easter Sunday. +#: holidays/countries/serbia.py:75 +msgid "Васкрс" +msgstr "Easter Sunday" + +#. Easter Monday. +#: holidays/countries/serbia.py:77 +msgid "Други дан Васкрса" +msgstr "Easter Monday" diff --git a/holidays/locale/en_US/LC_MESSAGES/RU.po b/holidays/locale/en_US/LC_MESSAGES/RU.po new file mode 100644 index 000000000..c84c78f64 --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/RU.po @@ -0,0 +1,62 @@ +# Russia holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-15 14:25-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year Holidays. +#: holidays/countries/russia.py:30 +msgid "Новогодние каникулы" +msgstr "New Year Holidays" + +#. Orthodox Christmas Day. +#: holidays/countries/russia.py:36 +msgid "Рождество Христово" +msgstr "Orthodox Christmas Day" + +#. Defender of the Fatherland Day. +#: holidays/countries/russia.py:39 +msgid "День защитника Отечества" +msgstr "Fatherland Defender's Day" + +#. International Women's Day. +#: holidays/countries/russia.py:42 +msgid "Международный женский день" +msgstr "International Women's Day" + +#. Labour Day. +#: holidays/countries/russia.py:45 +msgid "Праздник Весны и Труда" +msgstr "Holiday of Spring and Labor" + +#. Victory Day. +#: holidays/countries/russia.py:48 +msgid "День Победы" +msgstr "Victory Day" + +#. Russia's Day. +#: holidays/countries/russia.py:51 +msgid "День России" +msgstr "Russia's Day" + +#. Unity Day. +#: holidays/countries/russia.py:55 +msgid "День народного единства" +msgstr "Unity Day" + +#. October Revolution Day. +#: holidays/countries/russia.py:58 +msgid "День Октябрьской революции" +msgstr "October Revolution Day" diff --git a/holidays/locale/en_US/LC_MESSAGES/UA.po b/holidays/locale/en_US/LC_MESSAGES/UA.po new file mode 100644 index 000000000..e50043e8e --- /dev/null +++ b/holidays/locale/en_US/LC_MESSAGES/UA.po @@ -0,0 +1,107 @@ +# Ukraine holidays en_US localization. +# Authors: Arkadii Yakovets , (c) 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-13 09:05-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +"n%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.2.2\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: holidays/countries/ukraine.py:53 +#, c-format +msgid "Вихідний за %s" +msgstr "%s (Observed)" + +#: holidays/countries/ukraine.py:64 +msgid "Новий рік" +msgstr "New Year's Day" + +#: holidays/countries/ukraine.py:70 +msgid "Різдво Христове (за юліанським календарем)" +msgstr "Christmas (Julian calendar)" + +#: holidays/countries/ukraine.py:76 +msgid "Міжнародний жіночий день" +msgstr "International Women's Day" + +#: holidays/countries/ukraine.py:82 +msgid "Великдень (Пасха)" +msgstr "Easter Sunday (Pascha)" + +#. Holy trinity +#: holidays/countries/ukraine.py:101 +msgid "Трійця" +msgstr "Holy Trinity Day" + +#: holidays/countries/ukraine.py:106 +msgid "День праці" +msgstr "Labor Day" + +#: holidays/countries/ukraine.py:109 +msgid "День міжнародної солідарності трудящих" +msgstr "International Workers' Solidarity Day" + +#: holidays/countries/ukraine.py:119 +msgid "День перемоги над нацизмом у Другій світовій війні (День перемоги)" +msgstr "Day of Victory over Nazism in World War II (Victory Day)" + +#: holidays/countries/ukraine.py:124 +msgid "День перемоги" +msgstr "Victory Day" + +#: holidays/countries/ukraine.py:131 +msgid "День перемоги над Японією" +msgstr "Day of victory over Japan" + +#: holidays/countries/ukraine.py:136 +msgid "День Конституції України" +msgstr "Day of the Constitution of Ukraine" + +#: holidays/countries/ukraine.py:142 +msgid "День Української Державності" +msgstr "Ukrainian Statehood Day" + +#. Independence Day +#: holidays/countries/ukraine.py:146 +msgid "День незалежності України" +msgstr "Independence Day" + +#: holidays/countries/ukraine.py:155 +msgid "День захисників і захисниць України" +msgstr "Day of defenders of Ukraine" + +#: holidays/countries/ukraine.py:157 +msgid "День захисника України" +msgstr "Defender of Ukraine Day" + +#: holidays/countries/ukraine.py:163 +msgid "Річниця Великої Жовтневої соціалістичної революції" +msgstr "Anniversary of the Great October Socialist Revolution" + +#: holidays/countries/ukraine.py:173 +msgid "Різдво Христове (за григоріанським календарем)" +msgstr "Christmas (Gregorian calendar)" + +#: holidays/countries/ukraine.py:179 +msgid "День пам'яті 9 січня 1905 року" +msgstr "Day of Remembrance January 9, 1905" + +#: holidays/countries/ukraine.py:185 +msgid "День Паризької Комуни" +msgstr "Day of the Paris Commune" + +#. USSR Constitution day +#: holidays/countries/ukraine.py:188 +msgid "День Конституції СРСР" +msgstr "Day of the USSR Constitution" diff --git a/holidays/locale/es/LC_MESSAGES/AR.po b/holidays/locale/es/LC_MESSAGES/AR.po new file mode 100644 index 000000000..70786e5d2 --- /dev/null +++ b/holidays/locale/es/LC_MESSAGES/AR.po @@ -0,0 +1,99 @@ +# Argentina holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 08:55-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/argentina.py:41 +msgid "Año Nuevo" +msgstr "" + +#. Carnival days +#: holidays/countries/argentina.py:45 +msgid "Día de Carnaval" +msgstr "" + +#. Memory's National Day for the Truth and Justice +#: holidays/countries/argentina.py:50 +msgid "Día Nacional de la Memoria por la Verdad y la Justicia" +msgstr "" + +#. Holy Week +#: holidays/countries/argentina.py:60 +msgid "Semana Santa (Jueves Santo)" +msgstr "" + +#: holidays/countries/argentina.py:61 +msgid "Semana Santa (Viernes Santo)" +msgstr "" + +#: holidays/countries/argentina.py:62 +msgid "Día de Pascuas" +msgstr "" + +#: holidays/countries/argentina.py:76 +msgid "Día del Veterano y de los Caidos en la Guerra de Malvinas" +msgstr "" + +#. Labor Day +#: holidays/countries/argentina.py:81 +msgid "Día del Trabajo" +msgstr "" + +#. May Revolution Day +#: holidays/countries/argentina.py:88 +msgid "Día de la Revolución de Mayo" +msgstr "" + +#. Day Pass to the Immortality of General Martín Miguel de Güemes. +#: holidays/countries/argentina.py:95 +msgid "Día Pase a la Inmortalidad del General Martín Miguel de Güemes" +msgstr "" + +#. Day Pass to the Immortality of General D. Manuel Belgrano. +#: holidays/countries/argentina.py:104 +msgid "Día Pase a la Inmortalidad del General D. Manuel Belgrano" +msgstr "" + +#. Independence Day +#: holidays/countries/argentina.py:113 +msgid "Día de la Independencia" +msgstr "" + +#. Day Pass to the Immortality of General D. José de San Martin +#: holidays/countries/argentina.py:120 +msgid "Día Pase a la Inmortalidad del General D. José de San Martin" +msgstr "" + +#: holidays/countries/argentina.py:132 +msgid "Día de la Raza" +msgstr "" + +#: holidays/countries/argentina.py:134 +msgid "Día del Respeto a la Diversidad Cultural" +msgstr "" + +#. National Sovereignty Day +#: holidays/countries/argentina.py:138 +msgid "Día Nacional de la Soberanía" +msgstr "" + +#: holidays/countries/argentina.py:148 +msgid "La Inmaculada Concepción" +msgstr "" + +#. Christmas +#: holidays/countries/argentina.py:151 +msgid "Navidad" +msgstr "" diff --git a/holidays/locale/fr/LC_MESSAGES/CA.po b/holidays/locale/fr/LC_MESSAGES/CA.po new file mode 100644 index 000000000..ed3c808c5 --- /dev/null +++ b/holidays/locale/fr/LC_MESSAGES/CA.po @@ -0,0 +1,146 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2023-02-15 08:30-0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + +#. New Year's Day. +#: holidays/countries/canada.py:63 +msgid "New Year's Day" +msgstr "Jour de l'an" + +#: holidays/countries/canada.py:67 holidays/countries/canada.py:168 +#: holidays/countries/canada.py:192 holidays/countries/canada.py:201 +#: holidays/countries/canada.py:278 holidays/countries/canada.py:285 +#: holidays/countries/canada.py:292 +#, c-format +msgid "%s (Observed)" +msgstr "%s (Observé)" + +#: holidays/countries/canada.py:78 holidays/countries/canada.py:83 +#: holidays/countries/canada.py:87 +msgid "Family Day" +msgstr "Fête de la famille" + +#: holidays/countries/canada.py:91 +msgid "Louis Riel Day" +msgstr "Journée Louis Riel" + +#: holidays/countries/canada.py:95 holidays/countries/canada.py:99 +msgid "Islander Day" +msgstr "Fête des Insulaires" + +#. Heritage Day. +#: holidays/countries/canada.py:105 holidays/countries/canada.py:124 +#: holidays/countries/canada.py:213 +msgid "Heritage Day" +msgstr "Fête du Patrimoine" + +#. St. Patrick's Day. +#: holidays/countries/canada.py:131 +msgid "St. Patrick's Day" +msgstr "Fête de la Saint-Patrick" + +#. Good Friday. +#: holidays/countries/canada.py:135 +msgid "Good Friday" +msgstr "Vendredi saint" + +#. Easter Monday. +#: holidays/countries/canada.py:137 +msgid "Easter Monday" +msgstr "Lundi de Pâques" + +#: holidays/countries/canada.py:148 +msgid "St. George's Day" +msgstr "Fête de la Saint-Georges" + +#: holidays/countries/canada.py:154 +msgid "Victoria Day" +msgstr "Fête de la Reine" + +#: holidays/countries/canada.py:156 +msgid "National Patriots' Day" +msgstr "Journée nationale des patriotes" + +#: holidays/countries/canada.py:160 +msgid "National Aboriginal Day" +msgstr "Journée nationale des Autochtones" + +#: holidays/countries/canada.py:164 +msgid "St. Jean Baptiste Day" +msgstr "Fête nationale du Québec" + +#: holidays/countries/canada.py:174 holidays/countries/canada.py:176 +msgid "Discovery Day" +msgstr "Jour de la Découverte" + +#: holidays/countries/canada.py:183 +msgid "Memorial Day" +msgstr "our de mémorial" + +#: holidays/countries/canada.py:185 +msgid "Canada Day" +msgstr "Fête du Canada" + +#: holidays/countries/canada.py:188 +msgid "Dominion Day" +msgstr "Jour du dominion" + +#: holidays/countries/canada.py:196 +msgid "Nunavut Day" +msgstr "Jour du Nunavut" + +#: holidays/countries/canada.py:207 +msgid "Civic Holiday" +msgstr "Premier lundi d'août" + +#. British Columbia Day. +#: holidays/countries/canada.py:217 +msgid "British Columbia Day" +msgstr "Jour de la Colombie Britannique" + +#: holidays/countries/canada.py:222 +msgid "New Brunswick Day" +msgstr "Jour du Nouveau Brunswick" + +#: holidays/countries/canada.py:227 +msgid "Saskatchewan Day" +msgstr "Jour du Saskatchewan" + +#: holidays/countries/canada.py:233 +msgid "Labour Day" +msgstr "Fête du Travail" + +#: holidays/countries/canada.py:246 +msgid "Funeral of Her Majesty the Queen Elizabeth II" +msgstr "Funéraire de sa majesté la reine Elizabeth II" + +#: holidays/countries/canada.py:252 +msgid "National Day for Truth and Reconciliation" +msgstr "Journée nationale de la vérité et de la réconciliation" + +#: holidays/countries/canada.py:262 holidays/countries/canada.py:264 +msgid "Thanksgiving" +msgstr "Action de grâce" + +#: holidays/countries/canada.py:270 +msgid "Remembrance Day" +msgstr "Jour du Souvenir" + +#. Christmas Day, +#: holidays/countries/canada.py:281 +msgid "Christmas Day" +msgstr "Jour de Noël" + +#. Boxing Day. +#: holidays/countries/canada.py:288 +msgid "Boxing Day" +msgstr "Boxing Day" diff --git a/holidays/locale/hy/LC_MESSAGES/AM.po b/holidays/locale/hy/LC_MESSAGES/AM.po new file mode 100644 index 000000000..82d7d943d --- /dev/null +++ b/holidays/locale/hy/LC_MESSAGES/AM.po @@ -0,0 +1,91 @@ +# Armenia holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 20:06-0800\n" +"PO-Revision-Date: 2023-02-16 08:57-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: hy\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/armenia.py:38 +msgid "Նոր տարվա օր" +msgstr "" + +#. Christmas and Epiphany Day. +#: holidays/countries/armenia.py:43 +msgid "Սուրբ Ծնունդ եւ Հայտնություն" +msgstr "" + +#. Christmas Eve. +#: holidays/countries/armenia.py:50 +msgid "Սուրբ Ծննդյան տոներ" +msgstr "" + +#. The Day of Remembrance of the Dead. +#: holidays/countries/armenia.py:53 +msgid "Մեռելոց հիշատակի օր" +msgstr "" + +#. Army Day. +#: holidays/countries/armenia.py:57 +msgid "Բանակի օր" +msgstr "" + +#. Women's Day. +#: holidays/countries/armenia.py:60 +msgid "Կանանց տոն" +msgstr "" + +#. Motherhood and Beauty Day. +#: holidays/countries/armenia.py:64 +msgid "Մայրության և գեղեցկության տոն" +msgstr "" + +#. Armenian Genocide Remembrance Day, +#: holidays/countries/armenia.py:67 +msgid "Եղեռնի զոհերի հիշատակի օր" +msgstr "" + +#. International Day of Workers' Solidarity. +#: holidays/countries/armenia.py:71 +msgid "Աշխատավորների համերաշխության միջազգային օր" +msgstr "" + +#. Labor Day. +#: holidays/countries/armenia.py:74 +msgid "Աշխատանքի օր" +msgstr "" + +#. Victory and Peace Day. +#: holidays/countries/armenia.py:79 +msgid "Հաղթանակի և Խաղաղության տոն" +msgstr "" + +#. Republic Day. +#: holidays/countries/armenia.py:82 +msgid "Հանրապետության օր" +msgstr "" + +#. Constitution Day. +#: holidays/countries/armenia.py:86 +msgid "Սահմանադրության օր" +msgstr "" + +#. Independence Day. +#: holidays/countries/armenia.py:90 +msgid "Անկախության օր" +msgstr "" + +#. New Year's Eve. +#: holidays/countries/armenia.py:93 +msgid "Նոր տարվա գիշեր" +msgstr "" diff --git a/holidays/locale/ja/LC_MESSAGES/JP.po b/holidays/locale/ja/LC_MESSAGES/JP.po new file mode 100644 index 000000000..2cbc9f305 --- /dev/null +++ b/holidays/locale/ja/LC_MESSAGES/JP.po @@ -0,0 +1,127 @@ +# Japan holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:36-0800\n" +"PO-Revision-Date: 2023-02-16 08:58-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. The Crown Prince marriage ceremony. +#: holidays/countries/japan.py:35 holidays/countries/japan.py:38 +msgid "結婚の儀" +msgstr "" + +#. State Funeral of Emperor Shōwa. +#: holidays/countries/japan.py:36 +msgid "大喪の礼" +msgstr "" + +#. Enthronement ceremony. +#: holidays/countries/japan.py:37 +msgid "即位礼正殿の儀" +msgstr "" + +#. Enthronement day. +#: holidays/countries/japan.py:40 +msgid "天皇の即位の日" +msgstr "" + +#. Enthronement ceremony. +#: holidays/countries/japan.py:41 +msgid "即位礼正殿の儀が行われる日" +msgstr "" + +#. New Year's Day. +#: holidays/countries/japan.py:52 +msgid "元日" +msgstr "" + +#. Coming of Age Day. +#: holidays/countries/japan.py:60 +msgid "成人の日" +msgstr "" + +#: holidays/countries/japan.py:64 +msgid "建国記念の日" +msgstr "" + +#: holidays/countries/japan.py:68 holidays/countries/japan.py:80 +#: holidays/countries/japan.py:148 +msgid "天皇誕生日" +msgstr "" + +#: holidays/countries/japan.py:76 +msgid "春分の日" +msgstr "" + +#: holidays/countries/japan.py:82 holidays/countries/japan.py:91 +msgid "みどりの日" +msgstr "" + +#: holidays/countries/japan.py:84 +msgid "昭和の日" +msgstr "" + +#. Constitution Memorial Day. +#: holidays/countries/japan.py:87 +msgid "憲法記念日" +msgstr "" + +#. Children's Day. +#: holidays/countries/japan.py:94 +msgid "こどもの日" +msgstr "" + +#: holidays/countries/japan.py:98 holidays/countries/japan.py:100 +#: holidays/countries/japan.py:102 holidays/countries/japan.py:104 +msgid "海の日" +msgstr "" + +#: holidays/countries/japan.py:108 holidays/countries/japan.py:110 +#: holidays/countries/japan.py:112 +msgid "山の日" +msgstr "" + +#: holidays/countries/japan.py:116 holidays/countries/japan.py:118 +msgid "敬老の日" +msgstr "" + +#: holidays/countries/japan.py:126 +msgid "秋分の日" +msgstr "" + +#: holidays/countries/japan.py:130 holidays/countries/japan.py:132 +msgid "体育の日" +msgstr "" + +#: holidays/countries/japan.py:134 holidays/countries/japan.py:136 +#: holidays/countries/japan.py:138 +msgid "スポーツの日" +msgstr "" + +#. Culture Day. +#: holidays/countries/japan.py:141 +msgid "文化の日" +msgstr "" + +#. Labour Thanksgiving Day. +#: holidays/countries/japan.py:144 +msgid "勤労感謝の日" +msgstr "" + +#: holidays/countries/japan.py:158 +msgid "振替休日" +msgstr "" + +#: holidays/countries/japan.py:166 +msgid "国民の休日" +msgstr "" diff --git a/holidays/locale/ka/LC_MESSAGES/GE.po b/holidays/locale/ka/LC_MESSAGES/GE.po new file mode 100644 index 000000000..3b8ba6f74 --- /dev/null +++ b/holidays/locale/ka/LC_MESSAGES/GE.po @@ -0,0 +1,101 @@ +# Georgia holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 14:15-0800\n" +"PO-Revision-Date: 2023-02-16 08:59-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: ka\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/georgia.py:36 +msgid "ახალი წელი" +msgstr "" + +#. New Year's Day. +#: holidays/countries/georgia.py:39 +msgid "ბედობა" +msgstr "" + +#. Orthodox Christmas Day. +#: holidays/countries/georgia.py:42 +msgid "ქრისტეშობა" +msgstr "" + +#. Baptism Day of our Lord Jesus Christ. +#: holidays/countries/georgia.py:45 +msgid "ნათლისღება" +msgstr "" + +#. Mother's Day. +#: holidays/countries/georgia.py:48 +msgid "დედის დღე" +msgstr "" + +#. Women's Day. +#: holidays/countries/georgia.py:51 +msgid "ქალთა საერთაშორისო დღე" +msgstr "" + +#. Orthodox Good Friday. +#: holidays/countries/georgia.py:55 +msgid "წითელი პარასკევი" +msgstr "" + +#. Orthodox Holy Saturday. +#: holidays/countries/georgia.py:58 +msgid "დიდი შაბათი" +msgstr "" + +#. Orthodox Easter Sunday. +#: holidays/countries/georgia.py:61 +msgid "აღდგომა" +msgstr "" + +#. Orthodox Easter Monday. +#: holidays/countries/georgia.py:64 +msgid "შავი ორშაბათი" +msgstr "" + +#. National Unity Day. +#: holidays/countries/georgia.py:67 +msgid "ეროვნული ერთიანობის დღე" +msgstr "" + +#. Day of Victory. +#: holidays/countries/georgia.py:70 +msgid "ფაშიზმზე გამარჯვების დღე" +msgstr "" + +#. Saint Andrew the First-Called Day. +#: holidays/countries/georgia.py:73 +msgid "წმინდა ანდრია პირველწოდებულის დღე" +msgstr "" + +#. Independence Day. +#: holidays/countries/georgia.py:78 +msgid "დამოუკიდებლობის დღე" +msgstr "" + +#. Saint Mary's Day. +#: holidays/countries/georgia.py:81 +msgid "მარიამობა" +msgstr "" + +#. Day of Svetitskhoveli Cathedral. +#: holidays/countries/georgia.py:84 +msgid "სვეტიცხოვლობა" +msgstr "" + +#. Saint George's Day. +#: holidays/countries/georgia.py:87 +msgid "გიორგობა" +msgstr "" diff --git a/holidays/locale/pl/LC_MESSAGES/PL.po b/holidays/locale/pl/LC_MESSAGES/PL.po new file mode 100644 index 000000000..6b8181d31 --- /dev/null +++ b/holidays/locale/pl/LC_MESSAGES/PL.po @@ -0,0 +1,100 @@ +# Poland holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 09:00-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/poland.py:30 +msgid "Narodowe Święto Niepodległości - 100-lecie" +msgstr "" + +#: holidays/countries/poland.py:39 +msgid "Nowy Rok" +msgstr "" + +#: holidays/countries/poland.py:42 +msgid "Święto Trzech Króli" +msgstr "" + +#: holidays/countries/poland.py:45 +msgid "Oczyszczenie Najświętszej Marii Panny" +msgstr "" + +#: holidays/countries/poland.py:50 +msgid "Niedziela Wielkanocna" +msgstr "" + +#: holidays/countries/poland.py:52 +msgid "Poniedziałek Wielkanocny" +msgstr "" + +#: holidays/countries/poland.py:55 +msgid "Święto Państwowe" +msgstr "" + +#: holidays/countries/poland.py:58 +msgid "Święto Narodowe Trzeciego Maja" +msgstr "" + +#: holidays/countries/poland.py:63 +msgid "Narodowe Święto Zwycięstwa i Wolności" +msgstr "" + +#: holidays/countries/poland.py:68 +msgid "Wniebowstąpienie Pańskie" +msgstr "" + +#: holidays/countries/poland.py:72 +msgid "Zielone Świątki" +msgstr "" + +#: holidays/countries/poland.py:75 +msgid "Drugi dzień Zielonych Świątek" +msgstr "" + +#: holidays/countries/poland.py:79 +msgid "Dzień Bożego Ciała" +msgstr "" + +#: holidays/countries/poland.py:82 +msgid "Uroczystość Świętych Apostołów Piotra i Pawła" +msgstr "" + +#: holidays/countries/poland.py:87 +msgid "Narodowe Święto Odrodzenia Polski" +msgstr "" + +#: holidays/countries/poland.py:92 +msgid "Wniebowzięcie Najświętszej Marii Panny" +msgstr "" + +#: holidays/countries/poland.py:96 +msgid "Uroczystość Wszystkich Świętych" +msgstr "" + +#: holidays/countries/poland.py:99 +msgid "Narodowe Święto Niepodległości" +msgstr "" + +#: holidays/countries/poland.py:104 +msgid "Niepokalane Poczęcie Najświętszej Marii Panny" +msgstr "" + +#: holidays/countries/poland.py:108 +msgid "Boże Narodzenie (pierwszy dzień)" +msgstr "" + +#: holidays/countries/poland.py:109 +msgid "Boże Narodzenie (drugi dzień)" +msgstr "" diff --git a/holidays/locale/ru/LC_MESSAGES/RU.po b/holidays/locale/ru/LC_MESSAGES/RU.po new file mode 100644 index 000000000..419f3ce05 --- /dev/null +++ b/holidays/locale/ru/LC_MESSAGES/RU.po @@ -0,0 +1,61 @@ +# Russia holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 09:01-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year Holidays. +#: holidays/countries/russia.py:30 +msgid "Новогодние каникулы" +msgstr "" + +#. Orthodox Christmas Day. +#: holidays/countries/russia.py:36 +msgid "Рождество Христово" +msgstr "" + +#. Defender of the Fatherland Day. +#: holidays/countries/russia.py:39 +msgid "День защитника Отечества" +msgstr "" + +#. International Women's Day. +#: holidays/countries/russia.py:42 +msgid "Международный женский день" +msgstr "" + +#. Labour Day. +#: holidays/countries/russia.py:45 +msgid "Праздник Весны и Труда" +msgstr "" + +#. Victory Day. +#: holidays/countries/russia.py:48 +msgid "День Победы" +msgstr "" + +#. Russia's Day. +#: holidays/countries/russia.py:51 +msgid "День России" +msgstr "" + +#. Unity Day. +#: holidays/countries/russia.py:55 +msgid "День народного единства" +msgstr "" + +#. October Revolution Day. +#: holidays/countries/russia.py:58 +msgid "День Октябрьской революции" +msgstr "" diff --git a/holidays/locale/sr/LC_MESSAGES/RS.po b/holidays/locale/sr/LC_MESSAGES/RS.po new file mode 100644 index 000000000..31efdb935 --- /dev/null +++ b/holidays/locale/sr/LC_MESSAGES/RS.po @@ -0,0 +1,68 @@ +# Serbia holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 15:18-0800\n" +"PO-Revision-Date: 2023-02-16 09:01-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#. New Year's Day. +#: holidays/countries/serbia.py:36 +msgid "Нова година" +msgstr "" + +#: holidays/countries/serbia.py:40 holidays/countries/serbia.py:50 +#: holidays/countries/serbia.py:60 holidays/countries/serbia.py:62 +#: holidays/countries/serbia.py:68 +#, c-format +msgid "%s (Слободан дан)" +msgstr "" + +#. Orthodox Christmas. +#: holidays/countries/serbia.py:43 +msgid "Божић" +msgstr "" + +#. Statehood Day. +#: holidays/countries/serbia.py:46 +msgid "Дан државности Србије" +msgstr "" + +#. International Workers' Day. +#: holidays/countries/serbia.py:55 +msgid "Празник рада" +msgstr "" + +#. Armistice Day. +#: holidays/countries/serbia.py:65 +msgid "Дан примирја у Првом светском рату" +msgstr "" + +#. Good Friday. +#: holidays/countries/serbia.py:71 +msgid "Велики петак" +msgstr "" + +#. Easter Saturday. +#: holidays/countries/serbia.py:73 +msgid "Велика субота" +msgstr "" + +#. Easter Sunday. +#: holidays/countries/serbia.py:75 +msgid "Васкрс" +msgstr "" + +#. Easter Monday. +#: holidays/countries/serbia.py:77 +msgid "Други дан Васкрса" +msgstr "" diff --git a/holidays/locale/uk/LC_MESSAGES/PL.po b/holidays/locale/uk/LC_MESSAGES/PL.po new file mode 100644 index 000000000..5c4f105ff --- /dev/null +++ b/holidays/locale/uk/LC_MESSAGES/PL.po @@ -0,0 +1,102 @@ +# Poland holidays Ukrainian translation. +# Authors: ~Jhellico , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-14 20:19+0200\n" +"PO-Revision-Date: 2023-02-14 20:48+0200\n" +"Last-Translator: ~Jhellico \n" +"Language-Team: Python Holidays localization team\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Generated-By: pygettext.py 1.5\n" +"X-Generator: Poedit 3.2.2\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: holidays/countries/poland.py:30 +msgid "Narodowe Święto Niepodległości - 100-lecie" +msgstr "100-а річниця Дня Незалежності" + +#: holidays/countries/poland.py:39 +msgid "Nowy Rok" +msgstr "Новий рік" + +#: holidays/countries/poland.py:42 +msgid "Święto Trzech Króli" +msgstr "Богоявлення" + +#: holidays/countries/poland.py:45 +msgid "Oczyszczenie Najświętszej Marii Panny" +msgstr "Стрітення" + +#: holidays/countries/poland.py:50 +msgid "Niedziela Wielkanocna" +msgstr "Перший день Великодня" + +#: holidays/countries/poland.py:52 +msgid "Poniedziałek Wielkanocny" +msgstr "Другий день Великодня" + +#: holidays/countries/poland.py:55 +msgid "Święto Państwowe" +msgstr "Національне свято" + +#: holidays/countries/poland.py:58 +msgid "Święto Narodowe Trzeciego Maja" +msgstr "Національне свято Третього Травня" + +#: holidays/countries/poland.py:63 +msgid "Narodowe Święto Zwycięstwa i Wolności" +msgstr "Національне свято перемоги та свободи" + +#: holidays/countries/poland.py:68 +msgid "Wniebowstąpienie Pańskie" +msgstr "Вознесіння Господнє" + +#: holidays/countries/poland.py:72 +msgid "Zielone Świątki" +msgstr "День Святої Трійці" + +#: holidays/countries/poland.py:75 +msgid "Drugi dzień Zielonych Świątek" +msgstr "Другий день Святої Трійці" + +#: holidays/countries/poland.py:79 +msgid "Dzień Bożego Ciała" +msgstr "Свято Тіла і Крові Христових" + +#: holidays/countries/poland.py:82 +msgid "Uroczystość Świętych Apostołów Piotra i Pawła" +msgstr "День святих апостолів Петра і Павла" + +#: holidays/countries/poland.py:87 +msgid "Narodowe Święto Odrodzenia Polski" +msgstr "День національного відродження Польщі" + +#: holidays/countries/poland.py:92 +msgid "Wniebowzięcie Najświętszej Marii Panny" +msgstr "Успіння Пресвятої Богородиці" + +#: holidays/countries/poland.py:96 +msgid "Uroczystość Wszystkich Świętych" +msgstr "День усіх святих" + +#: holidays/countries/poland.py:99 +msgid "Narodowe Święto Niepodległości" +msgstr "День Незалежності" + +#: holidays/countries/poland.py:104 +msgid "Niepokalane Poczęcie Najświętszej Marii Panny" +msgstr "Непорочне зачаття Діви Марії" + +#: holidays/countries/poland.py:108 +msgid "Boże Narodzenie (pierwszy dzień)" +msgstr "Перший день Різдва" + +#: holidays/countries/poland.py:109 +msgid "Boże Narodzenie (drugi dzień)" +msgstr "Другий день Різдва" diff --git a/holidays/locale/uk/LC_MESSAGES/UA.po b/holidays/locale/uk/LC_MESSAGES/UA.po new file mode 100644 index 000000000..3fd28097f --- /dev/null +++ b/holidays/locale/uk/LC_MESSAGES/UA.po @@ -0,0 +1,104 @@ +# Ukraine holidays. +# Authors: Arkadii Yakovets , (c) 2023. +# +msgid "" +msgstr "" +"Project-Id-Version: Python Holidays 0.20\n" +"POT-Creation-Date: 2023-02-15 08:13-0800\n" +"PO-Revision-Date: 2023-02-16 09:02-0800\n" +"Last-Translator: Arkadii Yakovets \n" +"Language-Team: Python Holidays localization team\n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Lingua 4.15.0\n" +"X-Generator: Poedit 3.2.2\n" + +#: holidays/countries/ukraine.py:53 +#, c-format +msgid "Вихідний за %s" +msgstr "" + +#: holidays/countries/ukraine.py:64 +msgid "Новий рік" +msgstr "" + +#: holidays/countries/ukraine.py:70 +msgid "Різдво Христове (за юліанським календарем)" +msgstr "" + +#: holidays/countries/ukraine.py:76 +msgid "Міжнародний жіночий день" +msgstr "" + +#: holidays/countries/ukraine.py:82 +msgid "Великдень (Пасха)" +msgstr "" + +#. Holy trinity +#: holidays/countries/ukraine.py:101 +msgid "Трійця" +msgstr "" + +#: holidays/countries/ukraine.py:106 +msgid "День праці" +msgstr "" + +#: holidays/countries/ukraine.py:109 +msgid "День міжнародної солідарності трудящих" +msgstr "" + +#: holidays/countries/ukraine.py:119 +msgid "День перемоги над нацизмом у Другій світовій війні (День перемоги)" +msgstr "" + +#: holidays/countries/ukraine.py:124 +msgid "День перемоги" +msgstr "" + +#: holidays/countries/ukraine.py:131 +msgid "День перемоги над Японією" +msgstr "" + +#: holidays/countries/ukraine.py:136 +msgid "День Конституції України" +msgstr "" + +#: holidays/countries/ukraine.py:142 +msgid "День Української Державності" +msgstr "" + +#. Independence Day +#: holidays/countries/ukraine.py:146 +msgid "День незалежності України" +msgstr "" + +#: holidays/countries/ukraine.py:155 +msgid "День захисників і захисниць України" +msgstr "" + +#: holidays/countries/ukraine.py:157 +msgid "День захисника України" +msgstr "" + +#: holidays/countries/ukraine.py:163 +msgid "Річниця Великої Жовтневої соціалістичної революції" +msgstr "" + +#: holidays/countries/ukraine.py:173 +msgid "Різдво Христове (за григоріанським календарем)" +msgstr "" + +#: holidays/countries/ukraine.py:179 +msgid "День пам'яті 9 січня 1905 року" +msgstr "" + +#: holidays/countries/ukraine.py:185 +msgid "День Паризької Комуни" +msgstr "" + +#. USSR Constitution day +#: holidays/countries/ukraine.py:188 +msgid "День Конституції СРСР" +msgstr "" diff --git a/holidays/utils.py b/holidays/utils.py index f5b4be865..c3f99fd30 100755 --- a/holidays/utils.py +++ b/holidays/utils.py @@ -1,6 +1,6 @@ # python-holidays # --------------- -# A fast, efficient Python library for generating country and subdivision +# 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. # @@ -20,12 +20,12 @@ import inspect import warnings from datetime import date +from datetime import timedelta as td from functools import lru_cache from typing import Dict, Iterable, List, Optional, Union -from dateutil.relativedelta import relativedelta as rd from hijri_converter import convert -from hijri_converter.ummalqura import GREGORIAN_RANGE +from hijri_converter.ummalqura import GREGORIAN_RANGE, HIJRI_RANGE from holidays import countries, financial from holidays.holiday_base import HolidayBase @@ -39,6 +39,7 @@ def country_holidays( observed: bool = True, prov: Optional[str] = None, state: Optional[str] = None, + language: Optional[str] = None, ) -> HolidayBase: """ Returns a new dictionary-like :py:class:`HolidayBase` object for the public @@ -69,6 +70,12 @@ def country_holidays( :param state: *deprecated* use subdiv instead. + :param language: + The language which the returned holiday names will be translated + into. It must be an ISO 639-1 (2-letter) language code. If the + language translation is not supported the original holiday names + will be used. + :return: A :py:class:`HolidayBase` object matching the **country**. @@ -175,21 +182,17 @@ def country_holidays( See documentation for examples. """ try: - country_classes = inspect.getmembers(countries, inspect.isclass) - country_class = next( - obj for name, obj in country_classes if name == country - ) - country_holiday: HolidayBase = country_class( + return getattr(countries, country)( years=years, subdiv=subdiv, expand=expand, observed=observed, prov=prov, state=state, + language=language, ) - except StopIteration: + except AttributeError: raise NotImplementedError(f"Country {country} not available") - return country_holiday def financial_holidays( @@ -198,6 +201,7 @@ def financial_holidays( years: Optional[Union[int, Iterable[int]]] = None, expand: bool = True, observed: bool = True, + language: Optional[str] = None, ) -> HolidayBase: """ Returns a new dictionary-like :py:class:`HolidayBase` object for the public @@ -222,6 +226,12 @@ def financial_holidays( (e.g. a holiday falling on a Sunday being observed the following Monday). False may not work for all countries. + :param language: + The language which the returned holiday names will be translated + into. It must be an ISO 639-1 (2-letter) language code. If the + language translation is not supported the original holiday names + will be used. + :return: A :py:class:`HolidayBase` object matching the **market**. @@ -234,19 +244,15 @@ def financial_holidays( examples. """ try: - financial_classes = inspect.getmembers(financial, inspect.isclass) - financial_class = next( - obj for name, obj in financial_classes if name == market - ) - financial_holiday: HolidayBase = financial_class( + return getattr(financial, market)( years=years, subdiv=subdiv, expand=expand, observed=observed, + language=language, ) - except StopIteration: + except AttributeError: raise NotImplementedError(f"Financial market {market} not available") - return financial_holiday def CountryHoliday( @@ -303,7 +309,7 @@ def list_supported_financial(unique=False) -> Dict[str, List[str]]: } -def _islamic_to_gre(Gyear: int, Hmonth: int, Hday: int) -> List[date]: +def _islamic_to_gre(g_year: int, h_month: int, h_day: int) -> Iterable[date]: """ Find the Gregorian dates of all instances of Islamic (Lunar Hijrī) calendar month and day falling within the Gregorian year. There could be up to two @@ -311,39 +317,41 @@ def _islamic_to_gre(Gyear: int, Hmonth: int, Hday: int) -> List[date]: calendar is about 11 days shorter. Relies on package `hijri_converter - `__. + __. - :param Gyear: + :param g_year: The Gregorian year. - :param Hmonth: + :param h_month: The Lunar Hijrī (Islamic) month. - :param Hday: + :param h_day: The Lunar Hijrī (Islamic) day. :return: - List of Gregorian dates within the Gregorian year specified that - matches the Islamic (Lunar Hijrī) calendar day and month specified. + An Iterable of Gregorian dates within the Gregorian year specified + that matches the Islamic (Lunar Hijrī) calendar day and month + specified. An empty Iterable is returned if the Gregorian year + is outside of the covered period, which as of hijri_converter 2.2.4 + (in January 2023) is Gregorian years 1925 to 2076 inclusive, or + equal to the contents of hijri_converter.ummalqura.GREGORIAN_RANGE + plus/minus 1 year. """ - gre_dates: List[date] = [] # To avoid hijri_converter check range OverflowError. - dt = (Gyear, Hmonth, Hday) - dt_min, dt_max = GREGORIAN_RANGE - if dt < dt_min or dt > dt_max: - return gre_dates - - Hyear = convert.Gregorian(Gyear, 1, 1).to_hijri().datetuple()[0] - gres = [ - convert.Hijri(y, Hmonth, Hday).to_gregorian() - for y in range(Hyear - 1, Hyear + 2) - ] - gre_dates.extend( - (date(*gre.datetuple()) for gre in gres if gre.year == Gyear) + g_year_min, g_year_max = (d[0] for d in GREGORIAN_RANGE) + h_year_min, h_year_max = (d[0] for d in HIJRI_RANGE) + if g_year <= g_year_min or g_year > g_year_max: + return () + + h_year = convert.Gregorian(g_year, 1, 1).to_hijri().year + h_years = ( + y for y in range(h_year, h_year + 3) if h_year_min <= y <= h_year_max ) - - return gre_dates + gre_dates = ( + convert.Hijri(y, h_month, h_day).to_gregorian() for y in h_years + ) + return (gre_date for gre_date in gre_dates if gre_date.year == g_year) class _ChineseLuniSolar: @@ -680,7 +688,7 @@ def lunar_n_y_date(self, year: int) -> date: # leap_month = self._get_leap_month(year) # for m in range(1, 1 + (1 > leap_month)): # span_days += self._lunar_month_days(year, m) - return self.SOLAR_START_DATE + rd(days=span_days) + return self.SOLAR_START_DATE + td(days=span_days) def lunar_to_gre( self, year: int, month: int, day: int, leap: bool = True @@ -706,7 +714,7 @@ def lunar_to_gre( for m in range(1, month + (month > leap_month)): span_days += self._lunar_month_days(year, m) span_days += day - 1 - return self.SOLAR_START_DATE + rd(days=span_days) + return self.SOLAR_START_DATE + td(days=span_days) def vesak_date(self, year: int) -> date: """ @@ -727,7 +735,7 @@ def vesak_date(self, year: int) -> date: for m in range(1, 4 + (4 > leap_month)): span_days += self._lunar_month_days(year, m) span_days += 14 - return self.SOLAR_START_DATE + rd(days=span_days) + return self.SOLAR_START_DATE + td(days=span_days) def vesak_may_date(self, year: int) -> date: """ @@ -743,10 +751,10 @@ def vesak_may_date(self, year: int) -> date: Estimated Gregorian date of Vesak (first full moon in May). """ span_days = self._span_days(year) - vesak_may_date = self.SOLAR_START_DATE + rd(days=span_days + 14) + vesak_may_date = self.SOLAR_START_DATE + td(days=span_days + 14) m = 1 while vesak_may_date.month < 5: - vesak_may_date += rd(days=self._lunar_month_days(year, m)) + vesak_may_date += td(days=self._lunar_month_days(year, m)) m += 1 return vesak_may_date @@ -770,7 +778,7 @@ def s_diwali_date(self, year: int) -> date: for m in range(1, 10 + (10 > leap_month)): span_days += self._lunar_month_days(year, m) span_days -= 2 - return self.SOLAR_START_DATE + rd(days=span_days) + return self.SOLAR_START_DATE + td(days=span_days) def thaipusam_date(self, year: int) -> date: """ @@ -791,4 +799,394 @@ def thaipusam_date(self, year: int) -> date: for m in range(1, 1 + (leap_month <= 6)): span_days += self._lunar_month_days(year, m) span_days -= 15 - return self.SOLAR_START_DATE + rd(days=span_days) + return self.SOLAR_START_DATE + td(days=span_days) + + +class _ThaiLuniSolar: + """ + ** Thai Lunar Calendar Holidays only work from 1941 (B.E. 2484) onwards + until 2057 (B.E. 2600) as we only have Thai year-type data for + cross-checking until then. + + So here are the basics of the Thai Lunar Calendar + 3-year types for calendar intercalation: + - Pakatimat (Normal Year): + consist of 12 months, has 354 days. + - Athikawan (Extra-Day Year): a + add a day to the 7th month of the year, has 355 days + for the synodic month correction. + - Athikamat (Extra-Month Year): + we have the 8th month twice, has 384 days for the + sidereal year correction. + + Each month either has 30 (Even months) or 29 (Odd months) + - The waxing phase has 15 days until Full Moon and waning + phase 14 (Odd Months)/15 (Even Months/ + Month 7 of Athikawan years) days for the New Moon. + - The second "Month 8" for Athikamat years is called + "Month 8.8", with all observed holy days delayed from + the usual calendar by 1 month. + + List of public holidays dependent on the Thai Lunar Calendar: + - Magha Puja/Makha Bucha: + 15th Waxing Day (Full Moon) of Month 3 + (On Month 4 for Athikamat Years). + - Royal Ploughing Ceremony: + Based on this, though Court Astrologer picks the + auspicious dates, which sadly don't fall into a + predictable pattern; see its specific section below. + - Vesak/Visakha Bucha: + 15th Waxing Day (Full Moon) of Month 6 + (On Month 7 for Athikamat Years). + - Asalha Puja/Asarnha Bucha: + 15th Waxing Day (Full Moon) of Month 8 + (On Month 8/8 for Athikamat Years). + - Buddhist Lent Day/Wan Khao Phansa: + 1st Waning Day of Month 8 + (On Month 8/8 for Athikamat Years). + + Other Buddhist date on Thai Lunar Calendar: + - Buddha's Cremation Day/Atthami Bucha + 8th Waning Day of Month 6 + (On Month 7 for Athikamat Years). + - End of Buddhist Lent Day/Ok Phansa: + 15th Waxing Day (Full Moon) of Month 11 + + The following code is based on Ninenik Narkdee's PHP implementation, + and we're thankful for his work. + + Please avoid touching the Athikawan and Athikamat declaration array + at all costs unless you can find sources for them somewhere for 2057++ + + Sources: (Ninenik.com 's wbm) http://tiny.cc/wa_ninenik_thluncal_php + https://www.myhora.com/ปฏิทิน/ปฏิทิน-พ.ศ.2560.aspx + + Usage example: + + >>> from holidays.utils import _ThaiLuniSolar + >>> thls = _ThaiLuniSolar() + >>> print(thls.visakha_bucha_date(2010)) + 2010-05-28 + """ + + # Athikawan (Extra-Day Year) list goes from 1941-2057 C.E. + # Copied off from 1757-2057 (B.E. 2300-2600) Thai Lunar Calendar + ATHIKAWAN_YEARS_GREGORIAN = { + 1945, + 1949, + 1952, + 1957, + 1963, + 1970, + 1973, + 1979, + 1987, + 1990, + 1997, + 2000, + 2006, + 2009, + 2016, + 2020, + 2025, + 2032, + 2035, + 2043, + 2046, + 2052, + } + + # Athikamat (Extra-Month Year) list goes from 1941-2057 C.E.: + # Copied off from 1757-2057 (B.E. 2300-2600) Thai Lunar Calendar + # Approx formula as follows: (common_era-78)-0.45222)%2.7118886 < 1 + ATHIKAMAT_YEARS_GREGORIAN = { + 1942, + 1944, + 1947, + 1950, + 1953, + 1956, + 1958, + 1961, + 1964, + 1966, + 1969, + 1972, + 1975, + 1977, + 1980, + 1983, + 1985, + 1988, + 1991, + 1994, + 1996, + 1999, + 2002, + 2004, + 2007, + 2010, + 2012, + 2015, + 2018, + 2021, + 2023, + 2026, + 2029, + 2031, + 2034, + 2037, + 2040, + 2042, + 2045, + 2048, + 2050, + 2053, + 2056, + } + + # While Buddhist Holy Days have been observed since the 1900s + # Due to the calendar changes in 1941 (B.E. 2484) and that + # our array only goes up to B.E. 2600; We'll thus only populate + # the data for 1941-2057 (B.E. 2484-2600). + # Sources: หนังสือเวียนกรมการปกครอง กระทรวงมหาดไทย มท 0310.1/ว4 5 ก.พ. 2539 + START_DATE = date(1940, 11, 30) + START_YEAR = 1941 + END_YEAR = 2057 + + @lru_cache() + def _get_start_date(self, year: int) -> Optional[date]: + """ + Calculate the start date of that particular Thai Lunar Calendar Year. + This usually falls in November or December of the previous Gregorian + year in question. Should the year be outside of working scope + (1941-2057: B.E 2484-2600), this will returns None instead. + + :param year: + The Gregorian year. + + :return: + The start date of Thai Lunar Calendar for a Gregorian year. + """ + if year < _ThaiLuniSolar.START_YEAR or year > _ThaiLuniSolar.END_YEAR: + return None + + iter_start_date = _ThaiLuniSolar.START_DATE + iter_start_year = _ThaiLuniSolar.START_YEAR + + while iter_start_year < year: + if iter_start_year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN: + delta_days = 384 + elif iter_start_year in _ThaiLuniSolar.ATHIKAWAN_YEARS_GREGORIAN: + delta_days = 355 + else: + delta_days = 354 + iter_start_date += td(days=delta_days) + iter_start_year += 1 + return iter_start_date + + def makha_bucha_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Makha Bucha. + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "Magha Puja". This concides with + the 15th Waxing Day of Month 3 in Thai Lunar Calendar, + or Month 4 in Athikamat years. + + To calculate, we use use the following time delta: + - Athikamat: 15th Waxing Day of Month 4 + or 29[1] + 30[2] + 29[3] + 15[4] -1 = 102 + - Athikawan: 15th Waxing Day of Month 3 + or 29[1] + 30[2] + 15[3] -1 = 73 + - Pakatimat: 15th Waxing Day of Month 3 + or 29[1] + 30[2] + 15[3] -1 = 73 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Makha Bucha. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + return start_date + td( + days=+102 + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN + else +73 + ) + + def visakha_bucha_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Visakha Bucha. + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "Vesak" and "Buddha Day". This concides with + the 15th Waxing Day of Month 6 in Thai Lunar Calendar, + or Month 7 in Athikamat years. + + To calculate, we use use the following time delta: + - Athikamat: 15th Waxing Day of Month 6 + or 177[1-6] + 15[7] -1 = 191 + - Athikawan: 15th Waxing Day of Month 6 + or 147[1-5] + 15[6] -1 = 161 + - Pakatimat: 15th Waxing Day of Month 6 + or 147[1-5] + 15[6] -1 = 161 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Visakha Bucha. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + return start_date + td( + days=+191 + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN + else +161 + ) + + def atthami_bucha_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Atthami Bucha. + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "Buddha's Cremation Day". This concides with + the 8th Waning Day of Month 6 in Thai Lunar Calendar, + or Month 7 in Athikamat years. + + To calculate, we use use the following time delta: + - Athikamat: 8th Waning Day of Month 7 + or 177[1-6] + 23[7] -1 = 199 + - Athikawan: 8th Waning Day of Month 6 + or 147[1-5] + 23[6] -1 = 169 + - Pakatimat: 8th Waning Day of Month 6 + or 147[1-5] + 23[6] -1 = 169 + - Or as in simpler terms: "Visakha Bucha" +8 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Atthami Bucha. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + return start_date + td( + days=+199 + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN + else +169 + ) + + def asarnha_bucha_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Asarnha Bucha. + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "Asalha Puja". This concides with + the 15th Waxing Day of Month 8 in Thai Lunar Calendar, + or Month 8.8 in Athikamat years. + + To calculate, we use use the following time delta: + - Athikamat: 15th Waxing Day of Month 8/8 + or 177[1-6] + 29[7] + 30[8] + 15[8.8] -1 = 250 + - Athikawan: 15th Waxing Day of Month 8 + or 177[1-6] + 30[7] + 15[8] -1 = 221 + - Pakatimat: 15th Waxing Day of Month 8 + or 177[1-6] + 29[7] + 15[8] -1 = 220 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Asarnha Bucha. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN: + delta_days = 250 + elif year in _ThaiLuniSolar.ATHIKAWAN_YEARS_GREGORIAN: + delta_days = 221 + else: + delta_days = 220 + return start_date + td(days=delta_days) + + def khao_phansa_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Khao Phansa. + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "(Start of) Buddhist Lent" and "Start of Vassa". + This concides with the 1st Waning Day of Month 8 + in Thai Lunar Calendar, or Month 8.8 in Athikamat years. + + To calculate, we use use the following time delta: + - Athikamat: 1st Waning Day of Month 8.8 + or 177[1-6] + 29[7] + 30[8] + 16[8.8] -1 = 251 + - Athikawan: 1st Waning Day of Month 8 ] + or 177[1-6] + 30[7] + 16[8] -1 = 222 + - Pakatimat: 1st Waning Day of Month 8 + or 177[1-6] + 29[7] + 16[8] -1 = 221 + - Or as in simpler terms: "Asarnha Bucha" +1 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Khao Phansa. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN: + delta_days = 251 + elif year in _ThaiLuniSolar.ATHIKAWAN_YEARS_GREGORIAN: + delta_days = 222 + else: + delta_days = 221 + return start_date + td(days=delta_days) + + def ok_phansa_date(self, year: int) -> Optional[date]: + """ + Calculate the estimated Gregorian date of Ok Phansa + If the Gregorian year input is invalud, this will outputs None instead. + + Also known as "End of Buddhist Lent" and "End of Vassa". + This concides with the 15th Waxing Day of Month 11 + in Thai Lunar Calendar. + + To calculate, we use use the following time delta: + - Athikamat: 15th Waxing Day of Month 11 + or 295[1-10] + 30[8.8] + 15[11] -1 = 339 + - Athikawan: 15th Waxing Day of Month 11 + or 295[1-10] + 1[7] + 15[11] -1 = 310 + - Pakatimat: 15th Waxing Day of Month 11 + or 295[1-10] + 15[11] -1 = 309 + + :param year: + The Gregorian year. + + :return: + Estimated Gregorian date of Ok Phansa. + """ + start_date = self._get_start_date(year) + if not start_date: + return None + + if year in _ThaiLuniSolar.ATHIKAMAT_YEARS_GREGORIAN: + delta_days = 339 + elif year in _ThaiLuniSolar.ATHIKAWAN_YEARS_GREGORIAN: + delta_days = 310 + else: + delta_days = 309 + return start_date + td(days=delta_days) diff --git a/pyproject.toml b/pyproject.toml index 473b9446b..4b1d4ae2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,21 +13,18 @@ exclude = ''' | buck-out | build | dist + | scripts/l10n/msgfmt.py )/ ''' [tool.coverage.run] branch = true -include = [ - 'tests.py', -] omit = [ - 'setup.py', 'holidays/__init__.py', - 'test/*', - 'tests.py', -# comment the above line if you want to see if all tests did run - ] + 'scripts/*', + 'setup.py', + 'tests/*', +] [tool.coverage.report] # Regexes for lines to exclude from consideration @@ -49,8 +46,9 @@ exclude_lines = [ ] [tool.isort] -known_first_party = ["holidays", "test"] +known_first_party = ["holidays", "tests"] line_length = 79 multi_line_output = 9 no_inline_sort = true profile = "black" +skip = ["docs", "scripts/l10n/msgfmt.py"] diff --git a/requirements_dev.txt b/requirements/dev.txt similarity index 60% rename from requirements_dev.txt rename to requirements/dev.txt index 19b455989..aa28af83a 100644 --- a/requirements_dev.txt +++ b/requirements/dev.txt @@ -1,19 +1,24 @@ -# package runtime requirements +# Package runtime requirements. convertdate>=2.3.0 hijri-converter korean-lunar-calendar -python-dateutil PyMeeus +python-dateutil -# test requirements +# Test requirements. coverage[toml]<7.0.0 flake8 pre-commit pytest pytest-cov +pytest-xdist sphinx tox -# deployment +# Localization. +chameleon +lingua + +# Deployment. pip>=19.2.3 wheel>=0.33.6 diff --git a/docs/requirements.txt b/requirements/docs.txt similarity index 55% rename from docs/requirements.txt rename to requirements/docs.txt index 3d318a951..c23c95922 100644 --- a/docs/requirements.txt +++ b/requirements/docs.txt @@ -1,4 +1,5 @@ -# pip requirements for building docs (they must include install_requires from setup.cfg) +# pip requirements for building docs. +# Must include package `install_requires` entries. convertdate>=2.3.0 hijri-converter korean-lunar-calendar diff --git a/scripts/l10n/generate_mo_files.py b/scripts/l10n/generate_mo_files.py new file mode 100755 index 000000000..8f45aec6a --- /dev/null +++ b/scripts/l10n/generate_mo_files.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +# 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) + +import os +import subprocess +import sys +from pathlib import Path + + +class MOGenerator: + """Creates .mo files for supported country/market entities.""" + + def run(self): + """Runs the .mo files generation process.""" + # Delete old files. + for mo_file in Path(os.path.join("holidays", "locale")).rglob("*.mo"): + os.unlink(str(mo_file)) + + # Create new files. + for po_path in Path(os.path.join("holidays", "locale")).rglob("*.po"): + po_file = str(po_path) + mo_file = po_file.replace(".po", ".mo") + subprocess.run( + ( + sys.executable, + os.path.join("scripts", "l10n", "msgfmt.py"), + "-o", + mo_file, + po_file, + ), + check=True, + ) + + +if __name__ == "__main__": + MOGenerator().run() diff --git a/scripts/l10n/generate_po_files.py b/scripts/l10n/generate_po_files.py new file mode 100755 index 000000000..362c1ef1d --- /dev/null +++ b/scripts/l10n/generate_po_files.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 + +# 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) + +import importlib +import inspect +import os +import subprocess +import sys +from pathlib import Path + + +class POGenerator: + """Generates .po files for supported country/market entities.""" + + def process_countries(self): + """Processes entities in specified directory.""" + country_code_info_mapping = {} + module_name_path_mapping = { + str(path).split(os.sep)[-1].replace(".py", ""): str(path) + for path in Path(os.path.join("holidays", "countries")).glob( + "*.py" + ) + if not str(path).endswith("__init__.py") + } + + sys.path.append(os.getcwd()) # Make holidays visible. + from holidays import __version__ as package_version + from holidays.holiday_base import HolidayBase + + for module_name, module_path in module_name_path_mapping.items(): + module = f"holidays.countries.{module_name}" + country_code_info_mapping.update( + { + name.upper(): (cls.default_language, module_path) + for name, cls in inspect.getmembers( + importlib.import_module(module), inspect.isclass + ) + if issubclass(cls, HolidayBase) + and len(name) == 2 + and cls.__module__ == module + and hasattr(cls, "default_language") + } + ) + + for country_code in sorted(country_code_info_mapping.keys()): + default_language, class_file_path = country_code_info_mapping[ + country_code + ] + pot_file_path = os.path.join( + "holidays", "locale", "pot", f"{country_code}.pot" + ) + # Create .pot files. + subprocess.run( + ( + "pot-create", + class_file_path, + "-k", + "tr", + "-o", + pot_file_path, + "--package-name", + "Python Holidays", + "--package-version", + package_version, + "--width", + "80", + ), + check=True, + ) + + # Update default country .po file. + po_directory = os.path.join( + "holidays", "locale", default_language, "LC_MESSAGES" + ) + os.makedirs(po_directory, exist_ok=True) + po_file_path = os.path.join(po_directory, f"{country_code}.po") + subprocess.run( + ( + "msgmerge", + po_file_path, + pot_file_path, + "-o", + po_file_path, + ), + check=True, + ) + + # Update .po files. + for po_file_path in Path(os.path.join("holidays", "locale")).rglob( + f"{country_code}.po" + ): + subprocess.run( + ( + "msgmerge", + po_file_path, + pot_file_path, + "-o", + po_file_path, + ), + check=True, + ) + + def run(self): + """Runs the .po files generation process.""" + self.process_countries() + + +if __name__ == "__main__": + POGenerator().run() diff --git a/scripts/l10n/msgfmt.py b/scripts/l10n/msgfmt.py new file mode 100755 index 000000000..3f731e941 --- /dev/null +++ b/scripts/l10n/msgfmt.py @@ -0,0 +1,246 @@ +#! /usr/bin/env python3 +# Written by Martin v. Löwis + +"""Generate binary message catalog from textual translation description. + +This program converts a textual Uniforum-style message catalog (.po file) into +a binary GNU catalog (.mo file). This is essentially the same function as the +GNU msgfmt program, however, it is a simpler implementation. Currently it +does not handle plural forms but it does handle message contexts. + +Usage: msgfmt.py [OPTIONS] filename.po + +Options: + -o file + --output-file=file + Specify the output file to write to. If omitted, output will go to a + file named filename.mo (based off the input file name). + + -h + --help + Print this message and exit. + + -V + --version + Display version information and exit. +""" + +import os +import sys +import ast +import getopt +import struct +import array +from email.parser import HeaderParser + +__version__ = "1.2" + +MESSAGES = {} + + +def usage(code, msg=''): + print(__doc__, file=sys.stderr) + if msg: + print(msg, file=sys.stderr) + sys.exit(code) + + +def add(ctxt, id, str, fuzzy): + "Add a non-fuzzy translation to the dictionary." + global MESSAGES + if not fuzzy and str: + if ctxt is None: + MESSAGES[id] = str + else: + MESSAGES[b"%b\x04%b" % (ctxt, id)] = str + + +def generate(): + "Return the generated output." + global MESSAGES + # the keys are sorted in the .mo file + keys = sorted(MESSAGES.keys()) + offsets = [] + ids = strs = b'' + for id in keys: + # For each string, we need size and file offset. Each string is NUL + # terminated; the NUL does not count into the size. + offsets.append((len(ids), len(id), len(strs), len(MESSAGES[id]))) + ids += id + b'\0' + strs += MESSAGES[id] + b'\0' + output = '' + # The header is 7 32-bit unsigned integers. We don't use hash tables, so + # the keys start right after the index tables. + # translated string. + keystart = 7*4+16*len(keys) + # and the values start after the keys + valuestart = keystart + len(ids) + koffsets = [] + voffsets = [] + # The string table first has the list of keys, then the list of values. + # Each entry has first the size of the string, then the file offset. + for o1, l1, o2, l2 in offsets: + koffsets += [l1, o1+keystart] + voffsets += [l2, o2+valuestart] + offsets = koffsets + voffsets + output = struct.pack("Iiiiiii", + 0x950412de, # Magic + 0, # Version + len(keys), # # of entries + 7*4, # start of key index + 7*4+len(keys)*8, # start of value index + 0, 0) # size and offset of hash table + output += array.array("i", offsets).tobytes() + output += ids + output += strs + return output + + +def make(filename, outfile): + ID = 1 + STR = 2 + CTXT = 3 + + # Compute .mo name from .po name and arguments + if filename.endswith('.po'): + infile = filename + else: + infile = filename + '.po' + if outfile is None: + outfile = os.path.splitext(infile)[0] + '.mo' + + try: + with open(infile, 'rb') as f: + lines = f.readlines() + except IOError as msg: + print(msg, file=sys.stderr) + sys.exit(1) + + section = msgctxt = None + fuzzy = 0 + + # Start off assuming Latin-1, so everything decodes without failure, + # until we know the exact encoding + encoding = 'latin-1' + + # Parse the catalog + lno = 0 + for l in lines: + l = l.decode(encoding) + lno += 1 + # If we get a comment line after a msgstr, this is a new entry + if l[0] == '#' and section == STR: + add(msgctxt, msgid, msgstr, fuzzy) + section = msgctxt = None + fuzzy = 0 + # Record a fuzzy mark + if l[:2] == '#,' and 'fuzzy' in l: + fuzzy = 1 + # Skip comments + if l[0] == '#': + continue + # Now we are in a msgid or msgctxt section, output previous section + if l.startswith('msgctxt'): + if section == STR: + add(msgctxt, msgid, msgstr, fuzzy) + section = CTXT + l = l[7:] + msgctxt = b'' + elif l.startswith('msgid') and not l.startswith('msgid_plural'): + if section == STR: + add(msgctxt, msgid, msgstr, fuzzy) + if not msgid: + # See whether there is an encoding declaration + p = HeaderParser() + charset = p.parsestr(msgstr.decode(encoding)).get_content_charset() + if charset: + encoding = charset + section = ID + l = l[5:] + msgid = msgstr = b'' + is_plural = False + # This is a message with plural forms + elif l.startswith('msgid_plural'): + if section != ID: + print('msgid_plural not preceded by msgid on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[12:] + msgid += b'\0' # separator of singular and plural + is_plural = True + # Now we are in a msgstr section + elif l.startswith('msgstr'): + section = STR + if l.startswith('msgstr['): + if not is_plural: + print('plural without msgid_plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l.split(']', 1)[1] + if msgstr: + msgstr += b'\0' # Separator of the various plural forms + else: + if is_plural: + print('indexed msgstr required for plural on %s:%d' % (infile, lno), + file=sys.stderr) + sys.exit(1) + l = l[6:] + # Skip empty lines + l = l.strip() + if not l: + continue + l = ast.literal_eval(l) + if section == CTXT: + msgctxt += l.encode(encoding) + elif section == ID: + msgid += l.encode(encoding) + elif section == STR: + msgstr += l.encode(encoding) + else: + print('Syntax error on %s:%d' % (infile, lno), \ + 'before:', file=sys.stderr) + print(l, file=sys.stderr) + sys.exit(1) + # Add last entry + if section == STR: + add(msgctxt, msgid, msgstr, fuzzy) + + # Compute output + output = generate() + + try: + with open(outfile,"wb") as f: + f.write(output) + except IOError as msg: + print(msg, file=sys.stderr) + + +def main(): + try: + opts, args = getopt.getopt(sys.argv[1:], 'hVo:', + ['help', 'version', 'output-file=']) + except getopt.error as msg: + usage(1, msg) + + outfile = None + # parse options + for opt, arg in opts: + if opt in ('-h', '--help'): + usage(0) + elif opt in ('-V', '--version'): + print("msgfmt.py", __version__) + sys.exit(0) + elif opt in ('-o', '--output-file'): + outfile = arg + # do it + if not args: + print('No input file given', file=sys.stderr) + print("Try `msgfmt --help' for more information.", file=sys.stderr) + return + + for filename in args: + make(filename, outfile) + + +if __name__ == '__main__': + main() diff --git a/setup.cfg b/setup.cfg index 4a0b3f3ee..8432a6f34 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,8 @@ author_email = dr.prodigy.github@gmail.com maintainer = Arkadii Yakovets (arkid15r) maintainer_email = ark@cho.red license = MIT -license_file = LICENSE +license_files = + LICENSE platforms = any classifiers = Development Status :: 4 - Beta @@ -38,21 +39,21 @@ install_requires = korean-lunar-calendar python-dateutil python_requires = >=3.7 - -[options.package_data] -holidays = py.typed +include_package_data = True [bumpversion] -current_version = 0.19 +current_version = 0.20 [flake8] per-file-ignores = + __init__.py:F401,F403 holidays/__init__.py:F401,F403 holidays/countries/__init__.py:F401 holidays/financial/__init__.py:F401 - test/test_holiday_base.py:E203 - test/test_imports.py:F401 + tests/test_utils.py:T201 + tests/test_holiday_base.py:E203 + tests/test_imports.py:F401 [rstcheck] -ignore_language = python ignore_directives = automodule +ignore_language = python diff --git a/setup.py b/setup.py index 68f5fd7a7..4f03c8e33 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,34 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) +import os +import subprocess +import sys +from pathlib import Path from setuptools import setup -setup() + +def generate_mo_files(): + """Looks up for .po files and generates respective .mo files.""" + for po_path in Path(os.path.join("holidays", "locale")).rglob("*.po"): + po_file = str(po_path) + mo_file = po_file.replace(".po", ".mo") + + if os.path.exists(mo_file): + os.unlink(mo_file) + subprocess.run( + ( + sys.executable, + os.path.join("scripts", "l10n", "msgfmt.py"), + "-o", + mo_file, + po_file, + ), + check=True, + ) + + +if __name__ == "__main__": + generate_mo_files() + setup() diff --git a/test/countries/test_albania.py b/test/countries/test_albania.py deleted file mode 100644 index 3d6ffa496..000000000 --- a/test/countries/test_albania.py +++ /dev/null @@ -1,65 +0,0 @@ -# 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-2022 -# ryanss (c) 2014-2017 -# Website: https://github.com/dr-prodigy/python-holidays -# License: MIT (see LICENSE file) - -from holidays.countries.albania import AL, ALB, Albania -from test.common import TestCase - - -class TestAlbania(TestCase): - def setUp(self): - self.holidays = Albania() - - def test_country_aliases(self): - self.assertCountryAliases(Albania, AL, ALB) - - def test_2022(self): - self.assertHolidays( - ("2022-01-01", "New Year's Day"), - ("2022-01-02", "New Year's Day"), - ("2022-01-03", "New Year's Day (Observed)"), - ("2022-01-04", "New Year's Day (Observed)"), - ("2022-03-14", "Summer Day"), - ("2022-03-22", "Nevruz"), - ("2022-04-17", "Catholic Easter"), - ("2022-04-18", "Catholic Easter (Observed)"), - ("2022-04-24", "Orthodox Easter"), - ("2022-04-25", "Orthodox Easter (Observed)"), - ("2022-05-01", "May Day"), - ("2022-05-02", "Eid al-Fitr* (*estimated), May Day (Observed)"), - ("2022-07-09", "Eid al-Adha* (*estimated)"), - ("2022-07-11", "Eid al-Adha* (*estimated) (Observed)"), - ("2022-09-05", "Mother Teresa Day"), - ("2022-11-28", "Independence Day"), - ("2022-11-29", "Liberation Day"), - ("2022-12-08", "National Youth Day"), - ("2022-12-25", "Christmas Day"), - ("2022-12-26", "Christmas Day (Observed)"), - ) - - def test_2023(self): - self.assertHolidays( - ("2023-01-01", "New Year's Day"), - ("2023-01-02", "New Year's Day, New Year's Day (Observed)"), - ("2023-03-14", "Summer Day"), - ("2023-03-22", "Nevruz"), - ("2023-04-09", "Catholic Easter"), - ("2023-04-10", "Catholic Easter (Observed)"), - ("2023-04-16", "Orthodox Easter"), - ("2023-04-17", "Orthodox Easter (Observed)"), - ("2023-04-21", "Eid al-Fitr* (*estimated)"), - ("2023-05-01", "May Day"), - ("2023-06-28", "Eid al-Adha* (*estimated)"), - ("2023-09-05", "Mother Teresa Day"), - ("2023-11-28", "Independence Day"), - ("2023-11-29", "Liberation Day"), - ("2023-12-08", "National Youth Day"), - ("2023-12-25", "Christmas Day"), - ) diff --git a/test/countries/test_bolivia.py b/test/countries/test_bolivia.py deleted file mode 100644 index 248d7b1ae..000000000 --- a/test/countries/test_bolivia.py +++ /dev/null @@ -1,264 +0,0 @@ -# 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) -# Copyright: Kateryna Golovanova , 2022 - -import unittest -from datetime import date - -import holidays - - -class TestBO(unittest.TestCase): - def setUp(self): - self.holidays = holidays.BO(observed=False) - self.holidays_observed = holidays.BO(observed=True) - - def test_new_years(self): - for dt in (date(2010, 12, 31), date(2017, 1, 2)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2022, 1, 1), date(2021, 1, 1)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Año Nuevo") - - for dt in (date(2017, 1, 2), date(2023, 1, 2)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Año Nuevo (Observed)" - ) - - def test_plurinational_state_foundation_day(self): - for dt in (date(2009, 1, 22), date(2017, 1, 23)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2010, 1, 22), date(2022, 1, 22)): - self.assertIn(dt, self.holidays) - self.assertEqual( - self.holidays[dt], - "Nacimiento del Estado Plurinacional de Bolivia", - ) - - def test_la_tablada(self): - self.assertNotIn(date(2010, 4, 15), self.holidays) - - t_holidays = holidays.BO(subdiv="T") - for dt in (date(2010, 4, 16), date(2010, 4, 14)): - self.assertNotIn(dt, t_holidays) - - for dt in (date(2015, 4, 15), date(2016, 4, 15)): - self.assertIn(dt, t_holidays) - self.assertEqual(t_holidays[dt], "La Tablada") - - def test_la_tablada_and_viernes_santo(self): - t_holidays = holidays.BO(subdiv="T") - dt = date(2022, 4, 15) - self.assertIn(dt, t_holidays) - self.assertEqual(t_holidays[dt], "La Tablada, Viernes Santo") - - def test_carnival_in_oruro(self): - self.assertNotIn(date(2020, 2, 21), self.holidays) - - o_holidays = holidays.BO(subdiv="O") - for dt in (date(2020, 2, 22), date(2020, 2, 20)): - self.assertNotIn(dt, o_holidays) - - for dt in (date(2020, 2, 21), date(2021, 2, 12)): - self.assertIn(dt, o_holidays) - self.assertEqual(o_holidays[dt], "Carnaval de Oruro") - - def test_carnival_monday(self): - for dt in (date(2020, 2, 23), date(2021, 2, 14)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2020, 2, 24), date(2023, 2, 20)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Feriado por Carnaval") - - for dt in (date(2020, 2, 25), date(2023, 2, 21)): - self.assertIn(dt, self.holidays) - self.assertEqual( - self.holidays[dt], "Feriado por Carnaval (Observed)" - ) - - def test_good_friday(self): - for dt in (date(2022, 4, 20), date(2021, 4, 1)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2022, 4, 15), date(2023, 4, 7)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Viernes Santo") - - def test_labor_day(self): - for dt in (date(2010, 5, 2), date(2017, 4, 30)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2021, 5, 1), date(2022, 5, 1)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Dia del trabajo") - - for dt in (date(2022, 5, 2), date(2016, 5, 2)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Dia del trabajo (Observed)" - ) - - def test_chuquisaca_day(self): - self.assertNotIn(date(2020, 5, 25), self.holidays) - - h_holidays = holidays.BO(subdiv="H") - for dt in (date(2020, 5, 24), date(2020, 5, 26)): - self.assertNotIn(dt, h_holidays) - - for dt in (date(2020, 5, 25), date(2021, 5, 25)): - self.assertIn(dt, h_holidays) - self.assertEqual( - h_holidays[dt], "Día del departamento de Chuquisaca" - ) - - def test_corpus_christi(self): - for dt in (date(2020, 6, 10), date(2020, 6, 12)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2020, 6, 11), date(2021, 6, 3)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Corpus Christi") - - def test_andean_new_year(self): - for dt in (date(2009, 6, 21), date(2010, 6, 20)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2010, 6, 21), date(2011, 6, 21)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Año Nuevo Andino") - - for dt in (date(2020, 6, 22), date(2015, 6, 22)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Año Nuevo Andino (Observed)" - ) - - def test_la_paz_day(self): - self.assertNotIn(date(2020, 7, 16), self.holidays) - - l_holidays = holidays.BO(subdiv="L") - for dt in (date(2020, 7, 15), date(2020, 7, 17)): - self.assertNotIn(dt, l_holidays) - - for dt in (date(2020, 7, 16), date(2021, 7, 16)): - self.assertIn(dt, l_holidays) - self.assertEqual(l_holidays[dt], "Día del departamento de La Paz") - - def test_agrarian_reform_day(self): - for dt in (date(1936, 8, 2), date(2020, 8, 1), date(2021, 8, 3)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(1937, 8, 2), date(2020, 8, 2), date(2021, 8, 2)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Día de la Revolución Agraria") - - def test_independence_day(self): - for dt in (date(1824, 8, 6), date(1825, 8, 5), date(2020, 8, 7)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(1825, 8, 6), date(2020, 8, 6)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Dia de la Patria") - - for dt in (date(2023, 8, 7), date(2017, 8, 7)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Dia de la Patria (Observed)" - ) - - def test_cochabamba_day(self): - self.assertNotIn(date(2020, 9, 14), self.holidays) - - c_holidays = holidays.BO(subdiv="C") - for dt in (date(2021, 9, 13), date(2021, 9, 15)): - self.assertNotIn(dt, c_holidays) - - for dt in (date(2020, 9, 14), date(2021, 9, 14)): - self.assertIn(dt, c_holidays) - self.assertEqual( - c_holidays[dt], "Día del departamento de Cochabamba" - ) - - def test_santa_cruz_day(self): - self.assertNotIn(date(2020, 9, 24), self.holidays) - - s_holidays = holidays.BO(subdiv="S") - for dt in (date(2021, 9, 23), date(2021, 9, 25)): - self.assertNotIn(dt, s_holidays) - - for dt in (date(2020, 9, 24), date(2021, 9, 24)): - self.assertIn(dt, s_holidays) - self.assertEqual( - s_holidays[dt], "Día del departamento de Santa Cruz" - ) - - def test_pando_day(self): - self.assertNotIn(date(2020, 10, 11), self.holidays) - - n_holidays = holidays.BO(subdiv="N") - for dt in (date(2021, 10, 10), date(2021, 9, 12)): - self.assertNotIn(dt, n_holidays) - - for dt in (date(2020, 10, 11), date(2021, 10, 11)): - self.assertIn(dt, n_holidays) - self.assertEqual(n_holidays[dt], "Dia del departamento de Pando") - - def test_all_souls_day(self): - for dt in (date(2021, 11, 1), date(2021, 11, 3)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2020, 11, 2), date(2021, 11, 2)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Todos Santos") - - for dt in (date(2025, 11, 3), date(2014, 11, 3)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Todos Santos (Observed)" - ) - - def test_potosi_day(self): - self.assertNotIn(date(2020, 11, 10), self.holidays) - - p_holidays = holidays.BO(subdiv="P") - for dt in (date(2021, 11, 9), date(2021, 11, 11)): - self.assertNotIn(dt, p_holidays) - - for dt in (date(2020, 11, 10), date(2021, 11, 10)): - self.assertIn(dt, p_holidays) - self.assertEqual(p_holidays[dt], "Dia del departamento de Potosí") - - def test_beni_day(self): - self.assertNotIn(date(2020, 11, 18), self.holidays) - - b_holidays = holidays.BO(subdiv="B") - for dt in (date(2021, 11, 17), date(2021, 11, 19)): - self.assertNotIn(dt, b_holidays) - - for dt in (date(2020, 11, 18), date(2021, 11, 18)): - self.assertIn(dt, b_holidays) - self.assertEqual(b_holidays[dt], "Dia del departamento de Beni") - - def test_christmas_day(self): - for dt in (date(2010, 12, 24), date(2017, 12, 26)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2017, 12, 25), date(2022, 12, 25)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Navidad") - - for dt in (date(2022, 12, 26), date(2016, 12, 26)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual(self.holidays_observed[dt], "Navidad (Observed)") diff --git a/test/countries/test_bosnia_and_herzegovina.py b/test/countries/test_bosnia_and_herzegovina.py deleted file mode 100644 index a68bfa0da..000000000 --- a/test/countries/test_bosnia_and_herzegovina.py +++ /dev/null @@ -1,295 +0,0 @@ -# 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) -# Copyright: Kateryna Golovanova , 2022 - -import unittest -from datetime import date - -import holidays - - -class TestBA(unittest.TestCase): - def setUp(self): - self.holidays = holidays.BA(observed=False) - self.holidays_observed = holidays.BA(observed=True) - - def test_new_years(self): - - for dt in (date(2010, 12, 31), date(2017, 1, 3)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2020, 1, 1), date(2019, 1, 1)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Nova Godina") - - for dt in (date(2020, 1, 2), date(2021, 1, 2)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual(self.holidays[dt], "Drugi dan Nove Godine") - - for dt in (date(2017, 1, 3), date(2023, 1, 3)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual( - self.holidays_observed[dt], "Treći dan Nove Godine" - ) - - def test_orthodox_christmas_eve(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 1, 5), date(2021, 1, 5)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 1, 6), date(2021, 1, 6)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Pravoslavno Badnje veče") - - def test_orthodox_christmas(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 1, 5), date(2021, 1, 8)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 1, 7), date(2021, 1, 7)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Božić (Божић)") - - def test_republic_day(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 1, 10), date(2021, 1, 8)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 1, 9), date(2021, 1, 9)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Dan Republike") - - def test_orthodox_new_year(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 1, 13), date(2021, 1, 15)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 1, 14), date(2021, 1, 14)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Pravoslavna Nova Godina") - - def test_independence_day(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2022, 3, 2), date(2021, 2, 28)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2022, 3, 1), date(2021, 3, 1)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Dan nezavisnosti") - - def test_catholic_good_friday(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2022, 4, 16), date(2021, 4, 14)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2022, 4, 15), date(2021, 4, 2)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Veliki Petak (Katolički)") - - def test_catholic_easter(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2022, 4, 16), date(2021, 4, 3)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2022, 4, 17), date(2021, 4, 4)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Uskrs (Katolički)") - - for dt in (date(2022, 4, 18), date(2021, 4, 5)): - self.assertIn(dt, fbih_holidays) - self.assertEqual( - fbih_holidays[dt], "Uskrsni ponedjeljak (Katolički)" - ) - - def test_orthodox_good_friday(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 4, 21), date(2021, 4, 29)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 4, 22), date(2021, 4, 30)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Veliki Petak (Pravoslavni)") - - def test_orthodox_easter(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 4, 23), date(2020, 4, 18)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 4, 24), date(2020, 4, 19)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Vaskrs (Pravoslavni)") - - for dt in (date(2022, 4, 25), date(2020, 4, 20)): - self.assertIn(dt, rs_holidays) - self.assertEqual( - rs_holidays[dt], "Uskrsni ponedjeljak (Pravoslavni)" - ) - - def test_labor_day(self): - for dt in (date(2022, 5, 4), date(2021, 5, 4)): - self.assertNotIn(dt, self.holidays) - - for dt in (date(2020, 5, 1), date(2021, 5, 1)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Dan rada") - - for dt in (date(2022, 5, 2), date(2021, 5, 2)): - self.assertIn(dt, self.holidays) - self.assertEqual(self.holidays[dt], "Drugi dan Dana rada") - - for dt in (date(2022, 5, 3), date(2016, 5, 3)): - self.assertIn(dt, self.holidays_observed) - self.assertEqual(self.holidays_observed[dt], "Treći dan Dana rada") - - def test_corpus_cristi(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2022, 6, 15), date(2021, 6, 2)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2022, 6, 16), date(2021, 6, 3)): - self.assertIn(dt, fbih_holidays) - self.assertEqual( - fbih_holidays[dt], "Tijelovo (Tijelo i Krv Kristova)" - ) - - def test_victory_day(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 5, 8), date(2020, 5, 10)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 5, 9), date(2020, 5, 9)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Dan pobjede") - - def test_eid_al_fitr(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 5, 12), date(2020, 5, 23)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 5, 13), date(2020, 5, 24)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Ramazanski Bajram") - - for dt in (date(2021, 5, 14), date(2020, 5, 25)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Drugi Dan Ramazanski Bajram") - - def test_eid_ul_adha(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 7, 8), date(2021, 7, 19)): - self.assertNotIn(dt, fbih_holidays) - - for dt in ( - date(2022, 7, 9), - date(2021, 7, 20), - date(2022, 7, 10), - date(2022, 7, 11), - date(2022, 7, 12), - ): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Kurban Bajram") - - def test_st_vitus_day(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 6, 27), date(2020, 6, 29)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 6, 28), date(2020, 6, 28)): - self.assertIn(dt, rs_holidays) - self.assertEqual(rs_holidays[dt], "Vidovdan") - - def test_islamic_new_year(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2022, 7, 28), date(2021, 8, 8)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2022, 7, 30), date(2021, 8, 9)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Muslimanska Nova Godina") - - def test_all_saints_day(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 11, 3), date(2020, 10, 31)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 11, 1), date(2020, 11, 1)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Svi Sveti") - - def test_all_souls_day(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 11, 3), date(2020, 10, 31)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 11, 2), date(2020, 11, 2)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Dušni dan") - - def test_dayton_agreement_day(self): - rs_holidays = holidays.BA(subdiv="RS") - - for dt in (date(2022, 11, 20), date(2020, 11, 22)): - self.assertNotIn(dt, rs_holidays) - - for dt in (date(2022, 11, 21), date(2020, 11, 21)): - self.assertIn(dt, rs_holidays) - self.assertEqual( - rs_holidays[dt], - "Dan uspostave Opšteg okvirnog sporazuma za mir u " - "Bosni i Hercegovini", - ) - - def test_statehood_day(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 11, 24), date(2020, 10, 26)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 11, 25), date(2020, 11, 25)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Dan državnosti") - - def test_catholic_christmas(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 12, 23), date(2020, 12, 23)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 12, 25), date(2020, 12, 25)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Božić (Katolički)") - - def test_st_stephens_day(self): - fbih_holidays = holidays.BA(subdiv="FBiH") - - for dt in (date(2021, 12, 27), date(2020, 12, 27)): - self.assertNotIn(dt, fbih_holidays) - - for dt in (date(2021, 12, 26), date(2020, 12, 26)): - self.assertIn(dt, fbih_holidays) - self.assertEqual(fbih_holidays[dt], "Stipandan (Stjepandan)") diff --git a/test/countries/test_botswana.py b/test/countries/test_botswana.py deleted file mode 100644 index 515c221e8..000000000 --- a/test/countries/test_botswana.py +++ /dev/null @@ -1,64 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestBotswana(unittest.TestCase): - def setUp(self): - self.holidays = holidays.BW() - - def test_new_years(self): - self.assertIn(date(1966, 1, 1), self.holidays) - self.assertIn(date(2018, 1, 1), self.holidays) - self.assertIn(date(2999, 1, 1), self.holidays) - self.assertIn(date(2017, 1, 2), self.holidays) # sunday - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) - self.assertIn(date(2017, 4, 17), self.holidays) - self.assertIn(date(1994, 4, 1), self.holidays) - - def test_presidents_day(self): - self.assertIn(date(2000, 7, 17), self.holidays) - self.assertIn(date(2000, 7, 18), self.holidays) - self.assertIn(date(2020, 7, 20), self.holidays) - self.assertIn(date(2020, 7, 21), self.holidays) - self.assertIn(date(2021, 7, 19), self.holidays) - self.assertIn(date(2021, 7, 20), self.holidays) - self.assertIn(date(2022, 7, 18), self.holidays) - self.assertIn(date(2022, 7, 19), self.holidays) - - def test_static(self): - self.assertIn(date(2004, 7, 1), self.holidays) - self.assertIn(date(2022, 12, 26), self.holidays) # Christmas - - def test_not_holiday(self): - self.assertNotIn(date(2016, 12, 28), self.holidays) - self.assertNotIn(date(2015, 3, 2), self.holidays) - self.assertNotIn(date(1964, 4, 16), self.holidays) - - def test_special_holidays(self): - self.assertIn(date(2019, 7, 2), self.holidays) - - def test_saturday_and_monday(self): - self.assertIn(date(2020, 12, 26), self.holidays) - - def test_not_observed(self): - self.holidays = holidays.BW(observed=False) - self.assertNotIn(date(2018, 7, 2), self.holidays) - self.assertNotIn(date(2018, 10, 2), self.holidays) - self.assertNotIn(date(2021, 12, 27), self.holidays) - self.assertNotIn(date(2022, 5, 2), self.holidays) - self.assertNotIn(date(2022, 12, 27), self.holidays) diff --git a/test/countries/test_burundi.py b/test/countries/test_burundi.py deleted file mode 100644 index 4ac86c38d..000000000 --- a/test/countries/test_burundi.py +++ /dev/null @@ -1,92 +0,0 @@ -# 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) - -import importlib.util -import unittest -from datetime import date - -import holidays - - -class TestBurundi(unittest.TestCase): - def setUp(self): - self.holidays = holidays.BI() - - def test_new_year_day(self): - for year in range(1979, 2050): - self.assertIn("New Year's Day", self.holidays[date(year, 1, 1)]) - - def test_unity_day(self): - self.assertIn("Unity Day", self.holidays[date(2017, 2, 5)]) - self.assertIn("Unity Day (Observed)", self.holidays[date(2017, 2, 6)]) - - def test_labour_day(self): - self.assertIn("Labour Day", self.holidays[date(2017, 5, 1)]) - self.assertIn("Labour Day (Observed)", self.holidays[date(2022, 5, 2)]) - - def test_rwagasore_day(self): - self.assertIn( - "Prince Louis Rwagasore Day", self.holidays[date(2017, 10, 13)] - ) - self.assertIn( - "Prince Louis Rwagasore Day (Observed)", - self.holidays[date(2024, 10, 14)], - ) - - def test_ntaryamira_day(self): - self.assertIn( - "President Ntaryamira Day", self.holidays[date(2017, 4, 6)] - ) - - def test_ndadaye_day(self): - self.assertIn( - "President Ndadaye's Day", self.holidays[date(2017, 10, 21)] - ) - self.assertIn( - "President Ndadaye's Day (Observed)", - self.holidays[date(2018, 10, 22)], - ) - - def test_independence_day(self): - for year in range(1962, 2050): - self.assertIn(date(year, 7, 1), self.holidays) - - for year in range(1930, 1962): - if year != 1958: - # in 1958 it's Eid Al Adha (as estimated by convertdate) - self.assertNotIn(date(year, 7, 1), self.holidays) - - self.assertIn( - "Independence Day (Observed)", self.holidays[date(2018, 7, 2)] - ) - - def test_ascension_day(self): - self.assertIn("Ascension Day", self.holidays[date(2020, 5, 21)]) - - def test_assumption_Day(self): - self.assertIn("Assumption Day", self.holidays[date(2020, 8, 15)]) - - def test_all_saints_Day(self): - self.assertIn("All Saints' Day", self.holidays[date(2020, 11, 1)]) - self.assertIn( - "All Saints' Day (Observed)", self.holidays[date(2020, 11, 2)] - ) - - def test_christmas_Day(self): - self.assertIn("Christmas Day", self.holidays[date(2020, 12, 25)]) - - def test_eid_al_adha(self): - if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.Burundi(years=[2019, 1999]) - - # eid Al Adha - self.assertIn(date(2020, 7, 31), self.holidays) - self.assertIn(date(2020, 7, 31), self.holidays) diff --git a/test/countries/test_cuba.py b/test/countries/test_cuba.py deleted file mode 100644 index dc6eaa945..000000000 --- a/test/countries/test_cuba.py +++ /dev/null @@ -1,306 +0,0 @@ -# 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) - -import unittest -from datetime import date - -from dateutil.relativedelta import relativedelta as rd - -import holidays -from holidays.constants import APR, DEC, JAN, JUL, MAR, MAY, OCT - - -class TestCuba(unittest.TestCase): - def setUp(self): - self.holidays = holidays.CU(observed=True) - - def _check_all_dates(self, year, expected_holidays): - start_date = date(year, 1, 1) - end_date = date(year, 12, 31) - delta = rd(days=+1) - - while start_date <= end_date: - if start_date in expected_holidays: - self.assertIn(start_date, self.holidays) - else: - self.assertNotIn(start_date, self.holidays) - start_date += delta - - def test_1968(self): - year = 1968 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - } - self._check_all_dates(year, expected) - - def test_1969(self): - year = 1969 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - } - self._check_all_dates(year, expected) - - def test_1970(self): - year = 1970 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - } - self._check_all_dates(year, expected) - - def test_1996(self): - year = 1996 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - } - self._check_all_dates(year, expected) - - def test_1997(self): - year = 1997 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - } - self._check_all_dates(year, expected) - - def test_1998(self): - year = 1998 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - } - self._check_all_dates(year, expected) - - def test_2006(self): - year = 2006 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - } - self._check_all_dates(year, expected) - - def test_2007(self): - year = 2007 - expected = { - date(year, JAN, 1), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2008(self): - year = 2008 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2011(self): - year = 2011 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, MAY, 1), - date(year, MAY, 2), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2012(self): - year = 2012 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, JAN, 2), - date(year, APR, 6), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2013(self): - year = 2013 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, MAR, 29), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2018(self): - # https://www.officeholidays.com/countries/cuba/2018 - year = 2018 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, MAR, 30), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2019(self): - # https://www.officeholidays.com/countries/cuba/2019 - year = 2019 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, APR, 19), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2020(self): - # https://www.officeholidays.com/countries/cuba/2020 - year = 2020 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, APR, 10), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2021(self): - # https://www.officeholidays.com/countries/cuba/2021 - year = 2021 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, APR, 2), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, OCT, 11), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2022(self): - # https://www.officeholidays.com/countries/cuba/2022 - year = 2022 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, APR, 15), - date(year, MAY, 1), - date(year, MAY, 2), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) - - def test_2023(self): - # https://www.officeholidays.com/countries/cuba/2023 - year = 2023 - expected = { - date(year, JAN, 1), - date(year, JAN, 2), - date(year, APR, 7), - date(year, MAY, 1), - date(year, JUL, 25), - date(year, JUL, 26), - date(year, JUL, 27), - date(year, OCT, 10), - date(year, DEC, 25), - date(year, DEC, 31), - } - self._check_all_dates(year, expected) diff --git a/test/countries/test_cyprus.py b/test/countries/test_cyprus.py deleted file mode 100644 index 5d12dce3a..000000000 --- a/test/countries/test_cyprus.py +++ /dev/null @@ -1,132 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestCyprus(unittest.TestCase): - def setUp(self): - self.cy_holidays = holidays.CY() - - def test_fixed_holidays(self): - years = range(2000, 2025) - for y in years: - fdays = ( - (date(y, 1, 1), "Πρωτοχρονιά [New Year's Day]"), - (date(y, 1, 6), "Θεοφάνεια [Epiphany]"), - ( - date(y, 3, 25), - "Εικοστή Πέμπτη Μαρτίου [Greek Independence Day]", - ), - (date(y, 4, 1), "1η Απριλίου [Cyprus National Day]"), - (date(y, 5, 1), "Εργατική Πρωτομαγιά [Labour day]"), - ( - date(y, 8, 15), - "Κοίμηση της Θεοτόκου [Assumption of Mary]", - ), - (date(y, 10, 28), "Ημέρα του Όχι [Ochi Day]"), - (date(y, 12, 25), "Χριστούγεννα [Christmas]"), - ( - date(y, 12, 26), - "Δεύτερη μέρα Χριστουγέννων [Day after Christmas]", - ), - ) - - for (d, dstr) in fdays: - self.assertIn(d, self.cy_holidays) - self.assertIn(dstr, self.cy_holidays[d]) - - def test_cy_clean_monday(self): - checkdates = ( - date(2018, 2, 19), - date(2019, 3, 11), - date(2020, 3, 2), - date(2021, 3, 15), - date(2022, 3, 7), - date(2023, 2, 27), - date(2024, 3, 18), - ) - - for d in checkdates: - self.assertIn(d, self.cy_holidays) - self.assertIn("Καθαρά Δευτέρα [Clean Monday]", self.cy_holidays[d]) - - def test_cy_good_friday(self): - checkdates = ( - date(2018, 4, 6), - date(2019, 4, 26), - date(2020, 4, 17), - date(2021, 4, 30), - date(2022, 4, 22), - date(2023, 4, 14), - date(2024, 5, 3), - ) - - for d in checkdates: - self.assertIn(d, self.cy_holidays) - self.assertIn( - "Μεγάλη Παρασκευή [Good Friday]", self.cy_holidays[d] - ) - - def test_cy_easter_sunday(self): - checkdates = ( - date(2018, 4, 8), - date(2019, 4, 28), - date(2020, 4, 19), - date(2021, 5, 2), - date(2022, 4, 24), - date(2023, 4, 16), - date(2024, 5, 5), - ) - - for d in checkdates: - self.assertIn(d, self.cy_holidays) - self.assertIn( - "Κυριακή του Πάσχα [Easter Sunday]", self.cy_holidays[d] - ) - - def test_cy_easter_monday(self): - checkdates = ( - date(2018, 4, 9), - date(2019, 4, 29), - date(2020, 4, 20), - date(2021, 5, 3), - date(2022, 4, 25), - date(2023, 4, 17), - date(2024, 5, 6), - ) - - for d in checkdates: - self.assertIn(d, self.cy_holidays) - self.assertIn( - "Δευτέρα του Πάσχα [Easter Monday]", self.cy_holidays[d] - ) - - def test_cy_monday_of_the_holy_spirit(self): - checkdates = ( - date(2018, 5, 28), - date(2019, 6, 17), - date(2020, 6, 8), - date(2021, 6, 21), - date(2022, 6, 13), - date(2023, 6, 5), - date(2024, 6, 24), - ) - - for d in checkdates: - self.assertIn(d, self.cy_holidays) - self.assertIn( - "Δευτέρα του Αγίου Πνεύματος " + "[Monday of the Holy Spirit]", - self.cy_holidays[d], - ) diff --git a/test/countries/test_denmark.py b/test/countries/test_denmark.py deleted file mode 100644 index d59501afd..000000000 --- a/test/countries/test_denmark.py +++ /dev/null @@ -1,31 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestDK(unittest.TestCase): - def setUp(self): - self.holidays = holidays.DK() - - def test_2016(self): - # http://www.officeholidays.com/countries/denmark/2016.php - self.assertIn(date(2016, 1, 1), self.holidays) - self.assertIn(date(2016, 3, 24), self.holidays) - self.assertIn(date(2016, 3, 25), self.holidays) - self.assertIn(date(2016, 3, 28), self.holidays) - self.assertIn(date(2016, 4, 22), self.holidays) - self.assertIn(date(2016, 5, 5), self.holidays) - self.assertIn(date(2016, 5, 16), self.holidays) - self.assertIn(date(2016, 12, 25), self.holidays) diff --git a/test/countries/test_eswatini.py b/test/countries/test_eswatini.py deleted file mode 100644 index 9ad6d4b6b..000000000 --- a/test/countries/test_eswatini.py +++ /dev/null @@ -1,71 +0,0 @@ -# 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) - -import unittest -import warnings -from datetime import date - -import holidays - - -class TestEswatini(unittest.TestCase): - def setUp(self): - self.holidays = holidays.SZ() - - def test_out_of_range(self): - self.assertNotIn(date(1920, 1, 1), self.holidays) - self.assertNotIn(date(1938, 1, 1), self.holidays) - - def test_new_years(self): - self.assertIn(date(1996, 1, 1), self.holidays) - self.assertIn(date(2000, 1, 1), self.holidays) - self.assertIn(date(2001, 1, 1), self.holidays) - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) - self.assertIn(date(2017, 4, 17), self.holidays) - self.assertIn(date(2017, 5, 25), self.holidays) - self.assertNotIn(date(2017, 5, 26), self.holidays) - - def test_special_holidays(self): - self.assertIn(date(1999, 12, 31), self.holidays) # y2k - self.assertIn(date(2000, 1, 3), self.holidays) # y2k - - def test_national_flag_day(self): - self.assertNotIn(date(1968, 4, 25), self.holidays) - self.assertIn(date(2006, 4, 25), self.holidays) - - def test_kings_birthday(self): - self.assertNotIn(date(1982, 7, 22), self.holidays) - self.assertIn(date(1983, 7, 22), self.holidays) - self.assertIn(date(1987, 4, 19), self.holidays) - self.assertNotIn(date(1986, 4, 19), self.holidays) - self.assertNotIn(date(1985, 4, 19), self.holidays) - - def test_holidays(self): - self.assertIn(date(2020, 5, 1), self.holidays) - self.assertIn(date(2020, 9, 6), self.holidays) - self.assertIn(date(2020, 12, 25), self.holidays) - self.assertIn(date(2020, 12, 26), self.holidays) - - def test_observed(self): - self.assertIn(date(2021, 4, 26), self.holidays) - self.assertIn(date(2021, 12, 27), self.holidays) - self.assertIn(date(2023, 1, 2), self.holidays) - - def test_swaziland_deprecation_warning(self): - warnings.simplefilter("default") - with self.assertWarns(Warning): - holidays.Swaziland() - - warnings.simplefilter("error") - with self.assertRaises(Warning): - holidays.Swaziland() diff --git a/test/countries/test_jamaica.py b/test/countries/test_jamaica.py deleted file mode 100644 index 8069a4221..000000000 --- a/test/countries/test_jamaica.py +++ /dev/null @@ -1,87 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestJamaica(unittest.TestCase): - def setUp(self): - self.holidays = holidays.Jamaica() - - def test_new_years_day(self): - self.assertIn(date(2021, 1, 1), self.holidays) - self.assertIn(date(2023, 1, 2), self.holidays) - self.assertIn(date(2024, 1, 1), self.holidays) - - def test_valentines_day(self): - for year in range(1948, 2050): - self.assertIn(date(year, 2, 14), self.holidays) - - def test_mothers_day(self): - self.assertIn(date(2021, 5, 9), self.holidays) - self.assertIn(date(2023, 5, 14), self.holidays) - self.assertIn(date(2024, 5, 12), self.holidays) - - def test_labour_day(self): - self.assertIn(date(2021, 5, 24), self.holidays) - self.assertIn(date(2023, 5, 23), self.holidays) - self.assertIn(date(2024, 5, 23), self.holidays) - - def test_fathers_day(self): - self.assertIn(date(2021, 6, 20), self.holidays) - self.assertIn(date(2023, 6, 18), self.holidays) - self.assertIn(date(2024, 6, 16), self.holidays) - - def test_emancipation_day(self): - self.assertIn(date(2021, 8, 2), self.holidays) - self.assertIn(date(2023, 8, 1), self.holidays) - self.assertIn(date(2024, 8, 1), self.holidays) - - def test_independence_day(self): - self.assertIn(date(2021, 8, 6), self.holidays) - self.assertIn(date(2023, 8, 7), self.holidays) - self.assertIn(date(2024, 8, 6), self.holidays) - - def test_national_heroes_day(self): - self.assertIn(date(2021, 10, 18), self.holidays) - self.assertIn(date(2023, 10, 16), self.holidays) - self.assertIn(date(2024, 10, 21), self.holidays) - - def test_christmas_day(self): - for year in range(1948, 2050): - self.assertIn(date(year, 12, 25), self.holidays) - - def test_boxing_day(self): - for year in range(1948, 2050): - self.assertIn(date(year, 12, 26), self.holidays) - - def test_ash_wednesday(self): - self.assertIn(date(2021, 2, 17), self.holidays) - self.assertIn(date(2022, 3, 2), self.holidays) - self.assertIn(date(2024, 2, 14), self.holidays) - - def test_good_friday(self): - self.assertIn(date(2021, 4, 2), self.holidays) - self.assertIn(date(2022, 4, 15), self.holidays) - self.assertIn(date(2024, 3, 29), self.holidays) - - def test_easter(self): - self.assertIn(date(2021, 4, 4), self.holidays) - self.assertIn(date(2022, 4, 17), self.holidays) - self.assertIn(date(2024, 3, 31), self.holidays) - - def test_easter_monday(self): - self.assertIn(date(2021, 4, 5), self.holidays) - self.assertIn(date(2022, 4, 18), self.holidays) - self.assertIn(date(2024, 4, 1), self.holidays) diff --git a/test/countries/test_kenya.py b/test/countries/test_kenya.py deleted file mode 100644 index 858492473..000000000 --- a/test/countries/test_kenya.py +++ /dev/null @@ -1,50 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestKenya(unittest.TestCase): - def setUp(self): - self.holidays = holidays.Kenya() - - def test_2019(self): - # New Year's Day - self.assertIn(date(2019, 1, 1), self.holidays) - # Good Friday - self.assertIn(date(2019, 4, 19), self.holidays) - # Easter Monday - self.assertIn(date(2019, 4, 22), self.holidays) - # Labour Day - self.assertIn(date(2019, 5, 1), self.holidays) - # Madaraka Day - self.assertIn(date(2019, 6, 1), self.holidays) - # Huduma Day - self.assertIn(date(2019, 10, 10), self.holidays) - # Mashujaa Day - self.assertIn(date(2019, 10, 20), self.holidays) - # Jamhuri (Independence) Day - self.assertIn(date(2019, 12, 12), self.holidays) - # Christmas Day - self.assertIn(date(2019, 12, 25), self.holidays) - # Utamaduni Day - self.assertIn(date(2018, 12, 26), self.holidays) - - def test_not_observed(self): - self.holidays = holidays.Kenya(observed=False) - self.assertNotIn(date(2017, 1, 2), self.holidays) - self.assertNotIn(date(2019, 10, 21), self.holidays) - self.assertNotIn(date(2021, 10, 11), self.holidays) - self.assertNotIn(date(2021, 12, 13), self.holidays) - self.assertNotIn(date(2022, 5, 2), self.holidays) diff --git a/test/countries/test_malawi.py b/test/countries/test_malawi.py deleted file mode 100644 index a12c4364a..000000000 --- a/test/countries/test_malawi.py +++ /dev/null @@ -1,47 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestMalawi(unittest.TestCase): - def setUp(self): - self.holidays = holidays.MW() - - def test_new_years(self): - self.assertIn("2015-01-01", self.holidays) - self.assertIn("2017-01-01", self.holidays) - self.assertIn("2999-01-01", self.holidays) - self.assertIn("2017-01-02", self.holidays) # sunday - self.assertNotIn("2017-01-02", holidays.MW(observed=False)) # sunday - - def test_good_friday(self): - self.assertIn("2022-04-15", self.holidays) - self.assertIn("2018-03-30", self.holidays) - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) - self.assertIn(date(2020, 4, 10), self.holidays) - self.assertIn(date(2015, 4, 6), self.holidays) - - def test_static(self): - self.assertIn("2004-03-03", self.holidays) - - def test_not_holiday(self): - self.assertNotIn("2016-12-28", self.holidays) - self.assertNotIn("2015-03-02", self.holidays) - - def test_pre_1999(self): - self.holidays = holidays.MW(years=[1990]) - self.assertEqual(0, len(self.holidays)) diff --git a/test/countries/test_mozambique.py b/test/countries/test_mozambique.py deleted file mode 100644 index 9882abda9..000000000 --- a/test/countries/test_mozambique.py +++ /dev/null @@ -1,54 +0,0 @@ -# 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) - -import unittest - -import holidays - - -class TestMozambique(unittest.TestCase): - def setUp(self): - self.holidays = holidays.MZ() - - def test_new_years(self): - self.assertIn("1975-01-01", self.holidays) - self.assertIn("2017-01-01", self.holidays) - self.assertIn("2999-01-01", self.holidays) - self.assertIn("2017-01-02", self.holidays) # sunday - - def test_carnival(self): - self.assertIn("1994-02-15", self.holidays) - self.assertIn("2002-02-12", self.holidays) - self.assertIn("2010-02-16", self.holidays) - self.assertIn("2017-02-28", self.holidays) - self.assertIn("2018-02-13", self.holidays) - self.assertIn("2019-03-05", self.holidays) - self.assertIn("2020-02-25", self.holidays) - self.assertIn("2021-02-16", self.holidays) - self.assertIn("2022-03-01", self.holidays) - - def test_easter(self): - self.assertIn("2017-04-14", self.holidays) - self.assertIn("2020-04-10", self.holidays) - self.assertIn("1994-04-01", self.holidays) - - def test_not_holiday(self): - self.assertNotIn("2018-02-04", self.holidays) - self.assertNotIn("2015-04-13", self.holidays) - self.assertNotIn("2018-03-23", self.holidays) - - def test_pre1974(self): - # Holidays not defined since 1975 - self.assertEqual(len(holidays.Mozambique(years=[1974])), 0) - - def test_observed(self): - not_observed = holidays.MZ(observed=False) - self.assertNotIn("2017-01-02", not_observed) diff --git a/test/countries/test_namibia.py b/test/countries/test_namibia.py deleted file mode 100644 index 3ae292a25..000000000 --- a/test/countries/test_namibia.py +++ /dev/null @@ -1,63 +0,0 @@ -# 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) -import unittest -from datetime import date - -import holidays - - -class TestNamibia(unittest.TestCase): - def setUp(self): - self.holidays = holidays.NA() - - def test_out_of_range_year(self): - self.assertNotIn(date(1970, 1, 1), self.holidays) - - def test_new_years(self): - self.assertIn(date(1991, 1, 1), self.holidays) - self.assertIn(date(1999, 1, 1), self.holidays) - self.assertIn(date(2000, 1, 1), self.holidays) - self.assertIn(date(2017, 1, 2), self.holidays) # observed holiday - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) - self.assertIn(date(2017, 4, 17), self.holidays) - self.assertIn(date(2017, 5, 25), self.holidays) - self.assertIn(date(1994, 4, 1), self.holidays) - - def test_special_holidays(self): - self.assertIn(date(1999, 12, 31), self.holidays) # Y2K - self.assertIn(date(2000, 1, 3), self.holidays) # Y2K - - def test_namibian_women_int_rights(self): - self.assertIn(date(2004, 9, 10), self.holidays) - self.assertIn( - date(2005, 9, 10), self.holidays - ) # test namib women and int. human rights day - - def test_holidays(self): - self.assertIn(date(2020, 5, 1), self.holidays) - self.assertIn(date(2020, 5, 4), self.holidays) - self.assertIn(date(2020, 5, 25), self.holidays) - self.assertIn(date(2020, 8, 26), self.holidays) - - def test_observed(self): - self.assertIn(date(2021, 3, 22), self.holidays) - self.assertIn(date(2021, 12, 27), self.holidays) - self.assertIn(date(2022, 12, 26), self.holidays) - - def test_not_observed(self): - self.holidays = holidays.NA(observed=False) - self.assertNotIn(date(2017, 1, 2), self.holidays) - self.assertNotIn(date(2017, 9, 11), self.holidays) - self.assertNotIn(date(2018, 8, 27), self.holidays) - self.assertNotIn(date(2021, 3, 22), self.holidays) - self.assertNotIn(date(2021, 12, 27), self.holidays) diff --git a/test/countries/test_poland.py b/test/countries/test_poland.py deleted file mode 100644 index d63d297a1..000000000 --- a/test/countries/test_poland.py +++ /dev/null @@ -1,68 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestPL(unittest.TestCase): - def setUp(self): - self.holidays = holidays.PL() - - def test_1910(self): - self.assertNotIn(date(1910, 5, 1), self.holidays) - self.assertNotIn(date(1910, 5, 3), self.holidays) - self.assertNotIn(date(1910, 11, 11), self.holidays) - - def test_2017(self): - # http://www.officeholidays.com/countries/poland/2017.php - self.assertIn(date(2017, 1, 1), self.holidays) - self.assertIn(date(2017, 1, 6), self.holidays) - self.assertIn(date(2017, 4, 16), self.holidays) - self.assertIn(date(2017, 4, 17), self.holidays) - self.assertIn(date(2017, 5, 1), self.holidays) - self.assertIn(date(2017, 5, 3), self.holidays) - self.assertIn(date(2017, 6, 4), self.holidays) - self.assertIn(date(2017, 6, 15), self.holidays) - self.assertIn(date(2017, 8, 15), self.holidays) - self.assertIn(date(2017, 11, 1), self.holidays) - self.assertIn(date(2017, 11, 11), self.holidays) - self.assertIn(date(2017, 12, 25), self.holidays) - self.assertIn(date(2017, 12, 26), self.holidays) - - self.assertNotIn(date(2017, 11, 12), self.holidays) - - def test_special_holidays(self): - self.assertIn(date(2018, 11, 12), self.holidays) - - def test_swieto_trzech_kroli(self): - self.holidays = holidays.Poland(years=[2011]) - self.assertEqual( - self.holidays[date(2011, 1, 6)], "Święto Trzech Króli" - ) - self.holidays = holidays.Poland(years=[2010]) - self.assertNotIn(date(2010, 1, 6), self.holidays) - - def test_swieto_panstwowe(self): - self.holidays = holidays.Poland(years=[1950]) - self.assertEqual(self.holidays[date(1950, 5, 1)], "Święto Państwowe") - self.holidays = holidays.Poland(years=[1949]) - self.assertNotIn(date(1949, 5, 1), self.holidays) - - def test_swieto_narodowe_trzeciego_maja(self): - self.holidays = holidays.Poland(years=[1919]) - self.assertEqual( - self.holidays[date(1919, 5, 3)], "Święto Narodowe Trzeciego Maja" - ) - self.holidays = holidays.Poland(years=[1918]) - self.assertNotIn(date(1918, 5, 3), self.holidays) diff --git a/test/countries/test_spain.py b/test/countries/test_spain.py deleted file mode 100644 index b86d4c5cf..000000000 --- a/test/countries/test_spain.py +++ /dev/null @@ -1,274 +0,0 @@ -# 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) - -import unittest -from copy import deepcopy -from datetime import date -from itertools import product - -import holidays -from holidays.utils import _islamic_to_gre - - -class TestSpain(unittest.TestCase): - def setUp(self): - self.holidays = holidays.ES(observed=False) - self.holidays_observed = holidays.ES() - self.prov_holidays = { - prov: holidays.ES(observed=False, subdiv=prov) - for prov in holidays.ES.subdivisions - } - - def test_fixed_holidays(self): - fixed_days_whole_country = ( - (1, 1), - (1, 6), - (5, 1), - (8, 15), - (10, 12), - (11, 1), - (12, 6), - (12, 8), - (12, 25), - ) - for y, (m, d) in product(range(1950, 2050), fixed_days_whole_country): - if y == 2022: - continue - self.assertIn(date(y, m, d), self.holidays) - - def test_fixed_holidays_observed(self): - fixed_days_whole_country = ( - (1, 1), - (1, 6), - (5, 1), - (8, 15), - (10, 12), - (11, 2), - (12, 7), - (12, 8), - (12, 25), - ) - for (m, d) in fixed_days_whole_country: - self.assertIn(date(2020, m, d), self.holidays_observed) - - def test_variable_days_in_2016(self): - for prov, prov_holidays in self.prov_holidays.items(): - self.assertEqual( - date(2016, 3, 24) in prov_holidays, prov not in {"CT", "VC"} - ) - self.assertIn(date(2016, 3, 25), prov_holidays) - self.assertEqual( - date(2016, 3, 28) in prov_holidays, - prov in {"CM", "CT", "IB", "NC", "PV", "VC"}, - ) - - def test_fix_days_in_2022(self): - fix_days_whole_country_2022 = ( - (1, 1), - (1, 6), - (4, 15), - (8, 15), - (10, 12), - (11, 1), - (12, 6), - (12, 8), - ) - for (m, d) in fix_days_whole_country_2022: - self.assertIn(date(2022, m, d), self.holidays_observed) - - def test_province_specific_days(self): - province_days = { - (2, 28): {"AN"}, - (3, 1): {"IB"}, - (4, 23): {"AR", "CL"}, - (5, 30): {"CN"}, - (5, 31): {"CM"}, - (5, 2): {"MD"}, - (6, 9): {"MC", "RI"}, - (7, 25): {"GA"}, - (7, 28): {"CB"}, - (8, 5): {"CE"}, - (9, 2): {"CE"}, - (9, 8): {"AS", "EX", "ML"}, - (9, 11): {"CT"}, - (9, 15): {"CB"}, - (9, 17): {"ML"}, - (9, 27): {"NC"}, - (10, 9): {"VC"}, - } - for prov, prov_holidays in self.prov_holidays.items(): - for year in range(2010, 2021): - self.assertEqual( - date(year, 12, 26) in prov_holidays, prov in {"CT", "IB"} - ) - if year < 2015: - self.assertEqual( - date(year, 3, 19) in prov_holidays, - prov - in { - "AR", - "CL", - "CM", - "EX", - "GA", - "MC", - "MD", - "ML", - "NC", - "PV", - "VC", - }, - ) - elif year == 2015: - self.assertEqual( - date(year, 3, 19) in prov_holidays, - prov in {"CM", "MC", "MD", "ML", "NC", "PV", "VC"}, - ) - elif year == 2016: - self.assertEqual( - date(year, 3, 19) in prov_holidays, - prov in {"MC", "ML", "PV", "VC"}, - ) - elif year == 2017: - self.assertEqual( - date(year, 3, 19) in prov_holidays, prov in {"PV"} - ) - elif 2018 <= year <= 2019: - self.assertEqual( - date(year, 3, 19) in prov_holidays, - prov in {"GA", "MC", "NC", "PV", "VC"}, - ) - elif year == 2020: - self.assertEqual( - date(year, 3, 19) in prov_holidays, - prov in {"CM", "GA", "MC", "NC", "PV", "VC"}, - ) - self.assertEqual( - date(year, 6, 24) in prov_holidays, - prov in {"CT", "GA", "VC"}, - ) - - year_province_days = deepcopy(province_days) - if prov in {"ML"}: - eid_al_fitr_current_year = _islamic_to_gre(year, 10, 1)[0] - eid_al_adha_current_year = _islamic_to_gre(year, 12, 10)[0] - year_province_days.update( - { - ( - eid_al_fitr_current_year.month, - eid_al_fitr_current_year.day, - ): {"ML"}, - ( - eid_al_adha_current_year.month, - eid_al_adha_current_year.day, - ): {"ML"}, - } - ) - - if year == 2022: - year_province_days.update( - {(7, 25): {"GA", "MD", "NC", "PV"}} - ) - - for fest_day, fest_prov in year_province_days.items(): - self.assertEqual( - date(year, *fest_day) in prov_holidays, - prov in fest_prov, - "Failed date `%s`, province `%s`: %s" - % (date(year, *fest_day), prov, fest_prov), - ) - - def test_variable_days_in_2022(self): - province_days = { - (2, 28): {"AN"}, - (3, 1): {"IB"}, - (3, 19): {"VC"}, - (4, 14): [ - "AN", - "AR", - "AS", - "CB", - "CE", - "CL", - "CM", - "CN", - "EX", - "GA", - "IB", - "MC", - "MD", - "ML", - "NC", - "PV", - "RI", - "VC", - ], - (4, 18): {"CT", "IB", "NC", "PV", "RI", "VC"}, - (4, 23): {"AR", "CL"}, - (5, 2): {"AN", "AS", "CL", "EX", "MC", "MD", "AR"}, - (5, 3): {"ML"}, - (5, 17): {"GA"}, - (5, 30): {"CN"}, - (5, 31): {"CM"}, - (6, 6): {"CT"}, - (6, 9): {"MC", "RI"}, - (6, 16): {"CM"}, - (6, 24): {"CT", "GA", "VC"}, - (7, 9): {"CE"}, - (7, 11): {"ML"}, - (7, 25): {"GA", "NC", "MD", "PV"}, - (7, 28): {"CB"}, - (8, 5): {"CE"}, - (9, 2): {"CE"}, - (9, 6): {"PV"}, - (9, 8): {"AS", "EX", "ML"}, - (9, 15): {"CB"}, - (9, 17): {"ML"}, - (12, 26): [ - "AN", - "AR", - "AS", - "CB", - "CL", - "CM", - "CN", - "CT", - "EX", - "IB", - "MC", - "MD", - "ML", - "NC", - "RI", - ], - } - - observed_prov_holidays = { - prov: holidays.ES(observed=True, subdiv=prov) - for prov in holidays.ES.subdivisions - } - - for fest_date, fest_provs in province_days.items(): - for prov, prov_holidays in observed_prov_holidays.items(): - self.assertEqual( - date(2022, *fest_date) in prov_holidays, - prov in fest_provs, - "Failed date `%s`, province `%s`: %s" - % (date(2022, *fest_date), prov, ", ".join(fest_provs)), - ) - - def test_change_of_province_specific_days(self): - prov_holidays = self.prov_holidays["PV"] - self.assertNotIn(date(2010, 10, 25), prov_holidays) - self.assertIn(date(2011, 10, 25), prov_holidays) - self.assertIn(date(2012, 10, 25), prov_holidays) - self.assertIn(date(2013, 10, 25), prov_holidays) - self.assertNotIn(date(2014, 10, 25), prov_holidays) diff --git a/test/countries/test_thailand.py b/test/countries/test_thailand.py deleted file mode 100644 index 51559c3a4..000000000 --- a/test/countries/test_thailand.py +++ /dev/null @@ -1,81 +0,0 @@ -# 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.thailand import TH, THA, Thailand -from test.common import TestCase - - -class TestThailand(TestCase): - def setUp(self): - self.holidays = Thailand() - - def test_country_aliases(self): - self.assertCountryAliases(Thailand, TH, THA) - - def test_2022(self): - self.assertHolidays( - ("2022-01-01", "New Year's Day"), - ("2022-01-03", "New Year's Day (in lieu)"), - ("2022-02-16", "Makha Bucha"), - ("2022-04-06", "Chakri Memorial Day"), - ("2022-04-13", "Songkran Festival"), - ("2022-04-14", "Songkran Festival"), - ("2022-04-15", "Songkran Festival"), - ("2022-05-01", "Labour Day"), - ("2022-05-02", "Labour Day (in lieu)"), - ("2022-05-04", "Coronation Day"), - ("2022-05-15", "Buddha's Birthday"), - ("2022-05-16", "Buddha's Birthday (in lieu)"), - ("2022-06-03", "Queen Suthida's Birthday"), - ("2022-07-13", "Asalha Puja"), - ("2022-07-14", "Beginning of Vassa"), - ("2022-07-28", "King's Birthday"), - ("2022-08-12", "The Queen Mother's Birthday"), - ("2022-10-13", "King Bhumibol Adulyadej Memorial Day"), - ("2022-10-23", "King Chulalongkorn Day"), - ("2022-10-24", "King Chulalongkorn Day (in lieu)"), - ("2022-12-05", "King Bhumibol Adulyadej's Birthday"), - ("2022-12-10", "Constitution Day"), - ("2022-12-12", "Constitution Day (in lieu)"), - ("2022-12-31", "New Year's Eve"), - ) - - def test_new_years_day(self): - self.assertHoliday( - Thailand(observed=True), - "2010-01-01", - "2011-01-03", - "2012-01-02", - ) - - self.assertNoHoliday( - Thailand(observed=False), - "2010-01-03", - "2011-01-03", - "2012-01-02", - ) - - def test_new_years_eve(self): - self.assertHoliday( - Thailand(), - "2012-12-31", - "2013-01-01", - "2028-12-31", - "2029-01-01", - ) - - def test_pre_2006(self): - self.assertFalse(Thailand(years=2005).get_named("Asalha Puja")) - self.assertFalse(Thailand(years=2005).get_named("Beginning of Vassa")) - - def test_coronation_day(self): - self.assertHoliday("2016-05-05", "2020-05-04") - self.assertNoHoliday("2017-05-04", "2017-05-05") diff --git a/test/countries/test_ukraine.py b/test/countries/test_ukraine.py deleted file mode 100644 index 48fa472fa..000000000 --- a/test/countries/test_ukraine.py +++ /dev/null @@ -1,263 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestUkraine(unittest.TestCase): - def setUp(self): - self.holidays = holidays.UA(observed=False) - self.holidays_full = holidays.UA(observed=True) - - def test_before_1918(self): - self.assertNotIn(date(1917, 12, 31), self.holidays) - - def test_1950(self): - self.assertEqual( - self.holidays[date(1950, 5, 1)], - "День міжнародної солідарності трудящих", - ) - - def test_2018(self): - # https://www.buhoblik.org.ua/kadry-zarplata/vremya/3678-3678-normi-trivalosti-robochogo-chasu.html - self.assertIn(date(2018, 1, 1), self.holidays) - self.assertIn(date(2018, 1, 7), self.holidays) - self.assertIn(date(2018, 3, 8), self.holidays) - self.assertIn(date(2018, 4, 8), self.holidays) - self.assertIn(date(2018, 5, 1), self.holidays) - self.assertIn(date(2018, 5, 9), self.holidays) - self.assertIn(date(2018, 5, 27), self.holidays) - self.assertIn(date(2018, 6, 28), self.holidays) - self.assertIn(date(2018, 8, 24), self.holidays) - self.assertIn(date(2018, 10, 14), self.holidays) - self.assertIn(date(2018, 12, 25), self.holidays) - self.assertIn(date(2018, 1, 8), self.holidays_full) - self.assertIn(date(2018, 4, 9), self.holidays_full) - self.assertIn(date(2018, 5, 28), self.holidays_full) - self.assertIn(date(2018, 10, 15), self.holidays_full) - - def test_2019(self): - # https://www.buhoblik.org.ua/kadry-zarplata/vremya/3946-3946-normi-trivalosti-robochogo-chasu.html - self.assertIn(date(2019, 1, 1), self.holidays) - self.assertIn(date(2019, 1, 7), self.holidays) - self.assertIn(date(2019, 3, 8), self.holidays) - self.assertIn(date(2019, 4, 28), self.holidays) - self.assertIn(date(2019, 5, 1), self.holidays) - self.assertIn(date(2019, 5, 9), self.holidays) - self.assertIn(date(2019, 6, 16), self.holidays) - self.assertIn(date(2019, 6, 28), self.holidays) - self.assertIn(date(2019, 8, 24), self.holidays) - self.assertIn(date(2019, 10, 14), self.holidays) - self.assertIn(date(2019, 12, 25), self.holidays) - self.assertIn(date(2019, 4, 29), self.holidays_full) - self.assertIn(date(2019, 6, 17), self.holidays_full) - self.assertIn(date(2019, 8, 26), self.holidays_full) - - def test_2020(self): - # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4058-4058-normi-trivalosti-robochogo-chasu.html - self.assertIn(date(2020, 1, 1), self.holidays) - self.assertIn(date(2020, 1, 7), self.holidays) - self.assertIn(date(2020, 3, 8), self.holidays) - self.assertIn(date(2020, 4, 19), self.holidays) - self.assertIn(date(2020, 5, 1), self.holidays) - self.assertIn(date(2020, 5, 9), self.holidays) - self.assertIn(date(2020, 6, 7), self.holidays) - self.assertIn(date(2020, 6, 28), self.holidays) - self.assertIn(date(2020, 8, 24), self.holidays) - self.assertIn(date(2020, 10, 14), self.holidays) - self.assertIn(date(2020, 12, 25), self.holidays) - self.assertIn(date(2020, 3, 9), self.holidays_full) - self.assertIn(date(2020, 4, 20), self.holidays_full) - self.assertIn(date(2020, 5, 11), self.holidays_full) - self.assertIn(date(2020, 6, 8), self.holidays_full) - self.assertIn(date(2020, 6, 29), self.holidays_full) - - def test_2021(self): - # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4221-4221-norma-trivalosti-robochogo-chasu.html - self.assertIn(date(2021, 1, 1), self.holidays) - self.assertIn(date(2021, 1, 7), self.holidays) - self.assertIn(date(2021, 3, 8), self.holidays) - self.assertIn(date(2021, 5, 1), self.holidays) - self.assertIn(date(2021, 5, 2), self.holidays) - self.assertIn(date(2021, 5, 9), self.holidays) - self.assertIn(date(2021, 6, 20), self.holidays) - self.assertIn(date(2021, 6, 28), self.holidays) - self.assertIn(date(2021, 8, 24), self.holidays) - self.assertIn(date(2021, 10, 14), self.holidays) - self.assertIn(date(2021, 12, 25), self.holidays) - self.assertIn(date(2021, 5, 3), self.holidays_full) - self.assertIn(date(2021, 5, 4), self.holidays_full) - self.assertIn(date(2021, 5, 10), self.holidays_full) - self.assertIn(date(2021, 6, 21), self.holidays_full) - self.assertIn(date(2021, 12, 27), self.holidays_full) - - def test_2022(self): - # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4246-norma-trivalosti-robochogo-chasu-2022.html - self.assertIn(date(2022, 1, 1), self.holidays) - self.assertIn(date(2022, 1, 7), self.holidays) - self.assertIn(date(2022, 3, 8), self.holidays) - self.assertIn(date(2022, 4, 24), self.holidays) - self.assertIn(date(2022, 5, 1), self.holidays) - self.assertIn(date(2022, 5, 9), self.holidays) - self.assertIn(date(2022, 6, 12), self.holidays) - self.assertIn(date(2022, 6, 28), self.holidays) - self.assertIn(date(2022, 7, 28), self.holidays) - self.assertIn(date(2022, 8, 24), self.holidays) - self.assertIn(date(2022, 10, 14), self.holidays) - self.assertIn(date(2022, 12, 25), self.holidays) - - def test_old_holidays(self): - self.assertIn(date(2018, 5, 1), self.holidays) - self.assertIn(date(2016, 5, 2), self.holidays) - self.assertIn(date(1991, 7, 16), self.holidays) - self.assertIn(date(1950, 1, 22), self.holidays) - self.assertIn(date(1999, 11, 7), self.holidays) - self.assertIn(date(1999, 11, 8), self.holidays) - self.assertIn(date(1945, 5, 9), self.holidays) - self.assertIn(date(1945, 9, 3), self.holidays) - self.assertIn(date(1981, 10, 7), self.holidays) - self.assertIn(date(1937, 12, 5), self.holidays) - self.assertIn(date(1918, 3, 18), self.holidays) - - def test_observed(self): - for dt in [ - # New Year's Day - date(2000, 1, 3), - date(2005, 1, 3), - date(2006, 1, 2), - date(2011, 1, 3), - date(2012, 1, 2), - date(2017, 1, 2), - date(2022, 1, 3), - # Christmas Day (Julian calendar) - date(1996, 1, 8), - date(2001, 1, 8), - date(2006, 1, 9), - date(2007, 1, 8), - date(2012, 1, 9), - date(2017, 1, 9), - date(2018, 1, 8), - # Women's Day - date(1997, 3, 10), - date(2003, 3, 10), - date(2008, 3, 10), - date(2009, 3, 9), - date(2014, 3, 10), - date(2015, 3, 9), - date(2020, 3, 9), - # Easter - date(1995, 4, 24), - date(1996, 4, 15), - date(1997, 4, 28), - date(2000, 5, 3), - date(2001, 4, 16), - date(2002, 5, 6), - date(2003, 4, 28), - date(2004, 4, 12), - date(2005, 5, 3), - date(2006, 4, 24), - date(2007, 4, 9), - date(2008, 4, 28), - date(2009, 4, 20), - date(2010, 4, 5), - date(2011, 4, 25), - date(2012, 4, 16), - date(2013, 5, 6), - date(2014, 4, 21), - date(2015, 4, 13), - date(2016, 5, 3), - date(2017, 4, 17), - date(2018, 4, 9), - date(2019, 4, 29), - date(2020, 4, 20), - date(2021, 5, 4), - date(2022, 4, 25), - date(2062, 5, 2), # rare case - # Holy trinity - date(1995, 6, 12), - date(1996, 6, 3), - date(1997, 6, 16), - date(1999, 5, 31), - date(2000, 6, 19), - date(2001, 6, 4), - date(2002, 6, 24), - date(2003, 6, 16), - date(2004, 5, 31), - date(2005, 6, 20), - date(2006, 6, 12), - date(2007, 5, 28), - date(2008, 6, 16), - date(2009, 6, 8), - date(2010, 5, 24), - date(2011, 6, 13), - date(2012, 6, 4), - date(2013, 6, 24), - date(2014, 6, 9), - date(2015, 6, 1), - date(2016, 6, 20), - date(2017, 6, 5), - date(2018, 5, 28), - date(2019, 6, 17), - date(2020, 6, 8), - date(2021, 6, 21), - date(2022, 6, 13), - # Labour Day - date(1999, 5, 3), - date(1999, 5, 4), - date(2004, 5, 3), - date(2004, 5, 4), - date(2009, 5, 4), - date(2010, 5, 3), - date(2010, 5, 4), - date(2011, 5, 3), - date(2015, 5, 4), - date(2021, 5, 3), - date(2022, 5, 2), - # Victory Day - date(1999, 5, 10), - date(2004, 5, 10), - date(2009, 5, 11), - date(2010, 5, 10), - date(2015, 5, 11), - date(2020, 5, 11), - date(2021, 5, 10), - # Constitution Day - date(1997, 6, 30), - date(2003, 6, 30), - date(2008, 6, 30), - date(2009, 6, 29), - date(2014, 6, 30), - date(2015, 6, 29), - date(2020, 6, 29), - # Independence Day - date(1996, 8, 26), - date(1997, 8, 25), - date(2002, 8, 26), - date(2003, 8, 25), - date(2008, 8, 25), - date(2013, 8, 26), - date(2014, 8, 25), - date(2019, 8, 26), - # Day of the defender of Ukraine - date(2017, 10, 16), - date(2018, 10, 15), - # October Revolution - date(1997, 11, 10), - date(1999, 11, 9), - # Christmas Day (Gregorian calendar) - date(2021, 12, 27), - date(2022, 12, 26), - ]: - self.assertIn(dt, self.holidays_full) - self.assertEqual(self.holidays_full.get(dt)[:11], "Вихідний за") diff --git a/test/countries/test_zambia.py b/test/countries/test_zambia.py deleted file mode 100644 index ee74b7d66..000000000 --- a/test/countries/test_zambia.py +++ /dev/null @@ -1,81 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestZambia(unittest.TestCase): - def setUp(self): - self.holidays = holidays.ZM() - - def test_new_years(self): - self.assertIn("2015-01-01", self.holidays) - self.assertIn("2017-01-01", self.holidays) - self.assertIn("2999-01-01", self.holidays) - self.assertIn("2017-01-02", self.holidays) # sunday - - def test_good_friday(self): - self.assertIn("2022-04-15", self.holidays) - self.assertIn("2018-03-30", self.holidays) - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) - self.assertIn(date(2020, 4, 10), self.holidays) - self.assertIn(date(2015, 4, 6), self.holidays) - - def test_heroes_day(self): - self.assertIn(date(1997, 7, 7), self.holidays) - self.assertIn(date(2006, 7, 3), self.holidays) - self.assertIn(date(2047, 7, 1), self.holidays) - - def test_unity_day(self): - self.assertIn(date(1992, 7, 7), self.holidays) - self.assertIn(date(2003, 7, 8), self.holidays) - self.assertIn(date(2095, 7, 5), self.holidays) - - def test_farmers_day(self): - self.assertIn(date(1990, 8, 6), self.holidays) - self.assertIn(date(2021, 8, 2), self.holidays) - self.assertIn(date(2063, 8, 6), self.holidays) - - def test_static(self): - # African Freedom Day (on Sunday) - self.assertIn("1969-05-26", self.holidays) - # Youth Day - self.assertIn("2004-03-12", self.holidays) - # Kenneth Kaunda Day - self.assertIn("2032-04-28", self.holidays) - - def test_not_holiday(self): - self.assertNotIn("1958-05-26", self.holidays) - self.assertNotIn("2016-12-28", self.holidays) - self.assertNotIn("2015-03-02", self.holidays) - self.assertNotIn("2017-04-28", self.holidays) - - def test_observed(self): - self.holidays = holidays.ZM(observed=False) - # African Freedom Day (on Sunday) - self.assertNotIn("1969-05-26", self.holidays) - - def test_special_holidays(self): - self.assertIn(date(2016, 8, 11), self.holidays) - self.assertIn(date(2016, 9, 13), self.holidays) - self.assertIn(date(2018, 3, 9), self.holidays) - self.assertIn(date(2018, 7, 26), self.holidays) - self.assertIn(date(2021, 7, 2), self.holidays) - self.assertIn(date(2021, 7, 7), self.holidays) - self.assertIn(date(2021, 8, 12), self.holidays) - self.assertIn(date(2021, 8, 13), self.holidays) - self.assertIn(date(2021, 8, 24), self.holidays) - self.assertIn(date(2022, 3, 18), self.holidays) diff --git a/test/countries/test_zimbabwe.py b/test/countries/test_zimbabwe.py deleted file mode 100644 index 8ebac701e..000000000 --- a/test/countries/test_zimbabwe.py +++ /dev/null @@ -1,63 +0,0 @@ -# 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) - -import unittest -from datetime import date - -import holidays - - -class TestZimbabwe(unittest.TestCase): - def setUp(self): - self.holidays = holidays.ZW() - - def test_new_years(self): - self.assertIn(date(2010, 1, 1), self.holidays) - self.assertIn(date(2020, 1, 1), self.holidays) - self.assertNotIn(date(1986, 1, 2), self.holidays) # sunday - - def test_observed(self): - self.assertIn(date(2017, 1, 2), self.holidays) # sunday - - def test_easter(self): - self.assertIn(date(2017, 4, 14), self.holidays) # Good friday - self.assertIn(date(2017, 4, 15), self.holidays) # Easter Saturday - self.assertIn(date(2017, 4, 17), self.holidays) # Easter Monday - - def test_heroes_day(self): - self.assertIn(date(1988, 8, 8), self.holidays) - self.assertIn(date(1988, 8, 9), self.holidays) - self.assertIn(date(1996, 8, 12), self.holidays) - self.assertIn(date(1996, 8, 13), self.holidays) - self.assertIn(date(2000, 8, 14), self.holidays) - self.assertIn(date(2000, 8, 15), self.holidays) - self.assertIn(date(2020, 8, 10), self.holidays) - self.assertIn(date(2020, 8, 11), self.holidays) - self.assertIn(date(2021, 8, 9), self.holidays) - self.assertIn(date(2021, 8, 10), self.holidays) - self.assertIn(date(2022, 8, 8), self.holidays) - self.assertIn(date(2022, 8, 9), self.holidays) - - def test_not_holiday(self): - self.assertNotIn(date(2016, 1, 12), self.holidays) - self.assertNotIn(date(1999, 2, 3), self.holidays) - - def test_youth_day(self): - self.assertIn(date(2019, 2, 21), self.holidays) - self.assertNotIn(date(2015, 2, 21), self.holidays) - - def test_not_observed(self): - self.holidays = holidays.ZW(observed=False) - self.assertNotIn(date(2017, 1, 2), self.holidays) - self.assertNotIn(date(2019, 12, 23), self.holidays) - self.assertNotIn(date(2021, 2, 22), self.holidays) - self.assertNotIn(date(2022, 5, 2), self.holidays) - self.assertNotIn(date(2022, 12, 27), self.holidays) diff --git a/test/__init__.py b/tests/__init__.py similarity index 100% rename from test/__init__.py rename to tests/__init__.py diff --git a/test/common.py b/tests/common.py similarity index 84% rename from test/common.py rename to tests/common.py index d72825c32..eb6608d6c 100644 --- a/test/common.py +++ b/tests/common.py @@ -9,6 +9,7 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) +import os import unittest from typing import Generator @@ -21,6 +22,34 @@ class TestCase(unittest.TestCase): """Base class for python-holiday test cases.""" + @classmethod + def setUpClass(cls, test_class=None): + super().setUpClass() + + if test_class is None: + return None + + cls.test_class = test_class + + if ( + not hasattr(test_class, "default_language") + or test_class.default_language is None + # Can be either 2 (e.g., en, fr, uk) or 5 (e.g., en_US, en_GB). + or len(test_class.default_language) not in {2, 5} + ): + raise ValueError( + f"`{test_class.__name__}.default_language` value is invalid." + ) + + def setUp(self): + super().setUp() + + self.set_language(self.test_class.default_language) + self.holidays = self.test_class() + + def set_language(self, language): + os.environ["LANGUAGE"] = language + def _parse_arguments(self, args, expand_items=True): item_args = args instance = None @@ -117,15 +146,16 @@ def assertHolidayDates(self, *args): set(dates).difference(holidays.keys()), ) - def assertHolidayName(self, *args): + def assertHolidayName(self, name, *args): """Assert a holiday with a specific name exists.""" - holidays, names = self._parse_arguments(args) - for name in names: - self.assertTrue(holidays.get_named(name)) + holidays, _ = self._parse_arguments(args) + self.assertEqual( + len(holidays.years), len(holidays.get_named(name)), name + ) def assertHolidays(self, *args): - """Asserts holidays exactly match expected holidays.""" + """Assert holidays exactly match expected holidays.""" holidays, expected_holidays = self._parse_arguments( args, expand_items=False @@ -151,7 +181,7 @@ def assertHolidaysName(self, name, *args): holidays, dates = self._parse_arguments(args) for dt in dates: - self.assertEqual(name, holidays.get(dt), dt) + self.assertIn(name, holidays.get_list(dt)) def assertNoHoliday(self, *args): """Assert each date is not a holiday.""" @@ -160,12 +190,11 @@ def assertNoHoliday(self, *args): for dt in dates: self.assertNotIn(dt, holidays, dt) - def assertNoHolidayName(self, *args): + def assertNoHolidayName(self, name, *args): """Assert a holiday with a specific name doesn't exist.""" - holidays, names = self._parse_arguments(args) - for name in names: - self.assertFalse(holidays.get_named(name)) + holidays, _ = self._parse_arguments(args) + self.assertFalse(holidays.get_named(name), name) def assertNoHolidays(self, holidays): """Assert holidays dict is empty.""" diff --git a/test/countries/__init__.py b/tests/countries/__init__.py similarity index 100% rename from test/countries/__init__.py rename to tests/countries/__init__.py diff --git a/tests/countries/test_albania.py b/tests/countries/test_albania.py new file mode 100644 index 000000000..fdac6e1dc --- /dev/null +++ b/tests/countries/test_albania.py @@ -0,0 +1,226 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +from holidays.countries.albania import AL, ALB, Albania +from tests.common import TestCase + + +class TestAlbania(TestCase): + def setUp(self): + self.holidays = Albania() + + def test_country_aliases(self): + self.assertCountryAliases(Albania, AL, ALB) + + def test_special_holidays(self): + self.assertHoliday("2022-03-21") + + def test_holidays(self): + for year in range(1990, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-01-02", + f"{year}-05-01", + f"{year}-11-28", + f"{year}-11-29", + f"{year}-12-25", + ) + + self.assertNoHolidayName( + "Summer Day", Albania(years=range(1990, 2004)) + ) + self.assertHoliday(f"{year}-03-14" for year in range(2004, 2050)) + + self.assertNoHolidayName("Nevruz", Albania(years=range(1990, 1996))) + self.assertHoliday(f"{year}-03-22" for year in range(1996, 2050)) + + self.assertNoHolidayName( + "National Youth Day", Albania(years=range(1990, 2009)) + ) + self.assertHoliday(f"{year}-12-08" for year in range(2009, 2050)) + + def test_easter(self): + self.assertHoliday( + # Catholic Easter + "2018-04-01", + "2019-04-21", + "2020-04-12", + "2021-04-04", + "2022-04-17", + # Orthodox Easter + "2018-04-08", + "2019-04-28", + "2020-04-19", + "2021-05-02", + "2022-04-24", + ) + + def test_islamic_holidays(self): + self.assertHoliday( + # Eid al-Fitr + "2015-07-17", + "2016-07-06", + "2017-06-25", + "2018-06-15", + "2019-06-04", + "2020-05-24", + "2021-05-13", + "2022-05-02", + "2023-04-21", + "2024-04-10", + # Eid al-Adha + "2015-09-23", + "2016-09-11", + "2017-09-01", + "2018-08-21", + "2019-08-11", + "2020-07-31", + "2021-07-20", + "2022-07-09", + "2023-06-28", + "2024-06-16", + ) + + def test_mother_teresa_day(self): + name = "Mother Teresa Beatification Day" + self.assertHolidaysName( + name, (f"{year}-10-19" for year in range(2004, 2018)) + ) + self.assertNoHolidayName(name, Albania(years=range(1990, 2004))) + self.assertNoHolidayName(name, Albania(years=range(2018, 2050))) + + name = "Mother Teresa Canonisation Day" + self.assertNoHolidayName(name, Albania(years=range(1990, 2018))) + self.assertHolidaysName( + name, (f"{year}-09-05" for year in range(2018, 2050)) + ) + + def test_observed(self): + dt = ( + # New Year's Day + "2012-01-03", + "2016-01-04", + "2017-01-03", + "2021-01-04", + "2022-01-03", + "2022-01-04", + "2023-01-03", + # Summer Day + "2010-03-15", + "2015-03-16", + "2020-03-16", + "2021-03-15", + # Nevruz + "2014-03-24", + "2015-03-23", + "2020-03-23", + # May Day + "2010-05-03", + "2011-05-02", + "2016-05-02", + "2021-05-03", + # Mother Teresa ... Day + "2013-10-21", + "2014-10-20", + "2020-09-07", + "2021-09-06", + # Independence Day + "2010-11-30", + "2015-11-30", + "2020-11-30", + "2021-11-30", + # Liberation Day + "2014-12-01", + "2015-12-01", + "2020-12-01", + # National Youth Day + "2012-12-10", + "2013-12-09", + "2018-12-10", + "2019-12-09", + "2024-12-09", + # Christmas Day + "2010-12-27", + "2011-12-26", + "2016-12-26", + "2021-12-27", + "2022-12-26", + # Eid al-Fitr + "2012-08-20", + "2017-06-26", + "2020-05-25", + # Eid al-Adha + "2014-10-06", + "2016-09-12", + "2019-08-12", + "2022-07-11", + "2024-06-17", + # special cases + # Catholic Easter + "2008-03-25", + # Orthodox Easter + "1989-05-02", + "2000-05-02", + "2021-05-04", + "2027-05-04", + "2032-05-04", + "2062-05-02", + "2073-05-02", + "2084-05-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Albania(observed=False), dt) + + def test_2022(self): + self.assertHolidays( + ("2022-01-01", "New Year's Day"), + ("2022-01-02", "New Year's Day"), + ("2022-01-03", "New Year's Day (Observed)"), + ("2022-01-04", "New Year's Day (Observed)"), + ("2022-03-14", "Summer Day"), + ("2022-03-21", "Public Holiday"), + ("2022-03-22", "Nevruz"), + ("2022-04-17", "Catholic Easter"), + ("2022-04-18", "Catholic Easter (Observed)"), + ("2022-04-24", "Orthodox Easter"), + ("2022-04-25", "Orthodox Easter (Observed)"), + ("2022-05-01", "May Day"), + ("2022-05-02", "Eid al-Fitr* (*estimated); May Day (Observed)"), + ("2022-07-09", "Eid al-Adha* (*estimated)"), + ("2022-07-11", "Eid al-Adha* (*estimated) (Observed)"), + ("2022-09-05", "Mother Teresa Canonisation Day"), + ("2022-11-28", "Independence Day"), + ("2022-11-29", "Liberation Day"), + ("2022-12-08", "National Youth Day"), + ("2022-12-25", "Christmas Day"), + ("2022-12-26", "Christmas Day (Observed)"), + ) + + def test_2023(self): + self.assertHolidays( + ("2023-01-01", "New Year's Day"), + ("2023-01-02", "New Year's Day"), + ("2023-01-03", "New Year's Day (Observed)"), + ("2023-03-14", "Summer Day"), + ("2023-03-22", "Nevruz"), + ("2023-04-09", "Catholic Easter"), + ("2023-04-10", "Catholic Easter (Observed)"), + ("2023-04-16", "Orthodox Easter"), + ("2023-04-17", "Orthodox Easter (Observed)"), + ("2023-04-21", "Eid al-Fitr* (*estimated)"), + ("2023-05-01", "May Day"), + ("2023-06-28", "Eid al-Adha* (*estimated)"), + ("2023-09-05", "Mother Teresa Canonisation Day"), + ("2023-11-28", "Independence Day"), + ("2023-11-29", "Liberation Day"), + ("2023-12-08", "National Youth Day"), + ("2023-12-25", "Christmas Day"), + ) diff --git a/tests/countries/test_american_samoa.py b/tests/countries/test_american_samoa.py new file mode 100644 index 000000000..255b8ea16 --- /dev/null +++ b/tests/countries/test_american_samoa.py @@ -0,0 +1,37 @@ +# 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) + +import unittest +from datetime import date + +import holidays +from holidays.constants import DEC + + +class TestAS(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysAS() + + def test_AS_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + self.assertIn( + "Christmas Eve (Observed)", + self.holidays.get_list(date(2017, DEC, 22)), + ) + + def test_aliases(self): + """For coverage purposes""" + for h in [holidays.AS(), holidays.ASM(), holidays.AmericanSamoa()]: + self.assertIsInstance(h, holidays.HolidaysAS) diff --git a/test/countries/test_andorra.py b/tests/countries/test_andorra.py similarity index 99% rename from test/countries/test_andorra.py rename to tests/countries/test_andorra.py index 8277dcaed..9ac31e9cf 100644 --- a/test/countries/test_andorra.py +++ b/tests/countries/test_andorra.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.andorra import AD, AND, Andorra -from test.common import TestCase +from tests.common import TestCase class TestAndorra(TestCase): diff --git a/test/countries/test_angola.py b/tests/countries/test_angola.py similarity index 59% rename from test/countries/test_angola.py rename to tests/countries/test_angola.py index 1356278eb..ce0a41baf 100644 --- a/test/countries/test_angola.py +++ b/tests/countries/test_angola.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.angola import AGO, AO, Angola -from test.common import TestCase +from tests.common import TestCase class TestAngola(TestCase): @@ -20,6 +20,9 @@ def setUp(self): def test_country_aliases(self): self.assertCountryAliases(Angola, AO, AGO) + def test_no_holidays(self): + self.assertNoHolidays(Angola(years=1974)) + def test_carnival(self): self.assertHoliday( "1994-02-15", @@ -35,9 +38,14 @@ def test_carnival(self): def test_easter(self): self.assertHoliday( + # Good Friday "1994-04-01", "2017-04-14", + "2018-03-30", + "2019-04-19", "2020-04-10", + "2021-04-02", + "2022-04-15", ) def test_long_weekend(self): @@ -49,14 +57,19 @@ def test_long_weekend(self): def test_national_hero_day(self): self.assertHoliday(f"{year}-09-17" for year in range(1980, 2030)) - self.assertNoHoliday(f"{year}-09-17" for year in range(1975, 1980)) + self.assertNoHolidayName( + "Dia do Herói Nacional", + Angola(years=range(1975, 1980)), + ) def test_national_liberation_day(self): self.assertHoliday(f"{year}-03-23" for year in range(2019, 2030)) - - # Not a holiday before 2019. self.assertNoHoliday(f"{year}-03-23" for year in range(1990, 2019)) + self.assertNoHolidayName( + "Dia da Libertação da África Austral", + Angola(years=range(1975, 2019)), + ) def test_new_years_day(self): self.assertHoliday( @@ -73,9 +86,6 @@ def test_not_holidays(self): "2018-03-23", ) - def test_pre_1975(self): - self.assertNoHolidays(Angola(years=1974)) - def test_2022(self): self.assertHolidays( ("2022-01-01", "Ano novo"), @@ -95,5 +105,58 @@ def test_2022(self): ) def test_observed(self): - for _, name in Angola(observed=False, years=2020).items(): - self.assertNotIn("Observed", name) + dt = ( + # Ano novo + "2006-01-02", + "2012-01-02", + "2017-01-02", + "2018-12-31", + # Dia do Início da Luta Armada + "2007-02-05", + "2020-02-03", + "2021-02-05", + "2025-02-03", + # Dia Internacional da Mulher + "2009-03-09", + "2015-03-09", + "2018-03-09", + "2022-03-07", + # Dia da Libertação da África Austral + "2021-03-22", + "2023-03-24", + # Dia da Paz e Reconciliação + "2010-04-05", + "2019-04-05", + "2023-04-03", + "2024-04-05", + # Dia Mundial do Trabalho + "2005-05-02", + "2011-05-02", + "2016-05-02", + "2018-04-30", + "2025-05-02", + # Dia do Herói Nacional + "2006-09-18", + "2017-09-18", + "2019-09-16", + "2020-09-18", + "2024-09-16", + # Dia dos Finados + "2008-11-03", + "2014-11-03", + "2021-11-01", + "2023-11-03", + # Dia da Independência + "2007-11-12", + "2012-11-12", + "2021-11-12", + "2025-11-10", + # Dia de Natal e da Família + "2005-12-26", + "2011-12-26", + "2016-12-26", + "2018-12-24", + "2025-12-26", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Angola(observed=False), dt) diff --git a/test/countries/test_argentina.py b/tests/countries/test_argentina.py similarity index 73% rename from test/countries/test_argentina.py rename to tests/countries/test_argentina.py index 1bcff74a3..edefb02f2 100644 --- a/test/countries/test_argentina.py +++ b/tests/countries/test_argentina.py @@ -10,17 +10,17 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.constants import MAY, JUN, JUL, AUG, OCT from holidays.countries.argentina import AR, ARG, Argentina -from test.common import TestCase +from tests.common import TestCase class TestArgentina(TestCase): - def setUp(self): - self.holidays = Argentina() + @classmethod + def setUpClass(cls): + super().setUpClass(Argentina) def test_country_aliases(self): self.assertCountryAliases(Argentina, AR, ARG) @@ -41,8 +41,8 @@ def test_new_years_day(self): dt = date(year, 1, 1) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_carnival_day(self): @@ -98,8 +98,8 @@ def test_labor_day(self): dt = date(year, MAY, 1) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_may_revolution_day(self): @@ -114,8 +114,8 @@ def test_may_revolution_day(self): dt = date(year, MAY, 25) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_guemes_day(self): @@ -123,8 +123,8 @@ def test_guemes_day(self): dt = date(year, JUN, 17) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_belgrano_day(self): @@ -132,8 +132,8 @@ def test_belgrano_day(self): dt = date(year, JUN, 20) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_independence_day(self): @@ -153,8 +153,8 @@ def test_independence_day(self): dt = date(year, JUL, 9) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_san_martin_day(self): @@ -169,8 +169,8 @@ def test_san_martin_day(self): dt = date(year, AUG, 17) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_cultural_day(self): @@ -185,8 +185,8 @@ def test_cultural_day(self): dt = date(year, OCT, 12) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_national_sovereignty_day(self): @@ -197,8 +197,8 @@ def test_national_sovereignty_day(self): else: self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_immaculate_conception_day(self): @@ -213,8 +213,8 @@ def test_immaculate_conception_day(self): dt = date(year, 12, 8) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_christmas(self): @@ -222,90 +222,108 @@ def test_christmas(self): dt = date(year, 12, 25) self.assertHoliday(dt) self.assertNoHoliday( - dt + rd(days=-1), - dt + rd(days=+1), + dt + td(days=-1), + dt + td(days=+1), ) def test_2022(self): self.assertHolidays( ( "2022-01-01", - "Año Nuevo [New Year's Day]", + "Año Nuevo", ), ( "2022-02-28", - "Día de Carnaval [Carnival's Day]", + "Día de Carnaval", ), ( "2022-03-01", - "Día de Carnaval [Carnival's Day]", + "Día de Carnaval", ), ( "2022-03-24", - "Día Nacional de la Memoria por la Verdad y la Justicia " - "[Memory's National Day for the Truth and Justice]", + "Día Nacional de la Memoria por la Verdad y la Justicia", ), ( "2022-04-02", - "Día del Veterano y de los Caidos en la Guerra de Malvinas " - "[Veterans Day and the Fallen in the Malvinas War]", + "Día del Veterano y de los Caidos en la Guerra de Malvinas", ), ( "2022-04-14", - "Semana Santa (Jueves Santo) [Holy day (Holy Thursday)]", + "Semana Santa (Jueves Santo)", ), ( "2022-04-15", - "Semana Santa (Viernes Santo) [Holy day (Holy Friday)]", + "Semana Santa (Viernes Santo)", ), ( "2022-04-17", - "Día de Pascuas [Easter Day]", + "Día de Pascuas", ), ( "2022-05-01", - "Día del Trabajo [Labour Day]", + "Día del Trabajo", ), ( "2022-05-25", - "Día de la Revolucion de Mayo [May Revolution Day]", + "Día de la Revolución de Mayo", ), ( "2022-06-17", "Día Pase a la Inmortalidad del General Martín Miguel de " - "Güemes [Day Pass to the Immortality of General Martín Miguel " - "de Güemes]", + "Güemes", ), ( "2022-06-20", - "Día Pase a la Inmortalidad del General D. Manuel Belgrano " - "[Day Pass to the Immortality of General D. Manuel Belgrano]", + "Día Pase a la Inmortalidad del General D. Manuel Belgrano", ), ( "2022-07-09", - "Día de la Independencia [Independence Day]", + "Día de la Independencia", ), ( "2022-08-17", - "Día Pase a la Inmortalidad del General D. José de San Martin " - "[Day Pass to the Immortality of General D. José de San " - "Martin]", + "Día Pase a la Inmortalidad del General D. José de San Martin", ), ( "2022-10-12", - "Día del Respeto a la Diversidad Cultural " - "[Respect for Cultural Diversity Day]", + "Día del Respeto a la Diversidad Cultural", ), ( "2022-11-20", - "Día Nacional de la Soberanía [National Sovereignty Day]", + "Día Nacional de la Soberanía", ), ( "2022-12-08", - "La Inmaculada Concepción [Immaculate Conception]", + "La Inmaculada Concepción", ), ( "2022-12-25", - "Navidad [Christmas]", + "Navidad", ), ) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + ar = Argentina(language=language) + self.assertEqual(ar["2022-01-01"], "Año Nuevo") + self.assertEqual(ar["2022-12-25"], "Navidad") + + run_tests((Argentina.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Argentina.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + ar = Argentina(language=en_us) + self.assertEqual(ar["2018-01-01"], "New Year's Day") + self.assertEqual(ar["2022-12-25"], "Christmas") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + ar = Argentina(language=language) + self.assertEqual(ar["2018-01-01"], "New Year's Day") + self.assertEqual(ar["2022-12-25"], "Christmas") diff --git a/test/countries/test_armenia.py b/tests/countries/test_armenia.py similarity index 72% rename from test/countries/test_armenia.py rename to tests/countries/test_armenia.py index 0bd1ad8d4..2f6180524 100644 --- a/test/countries/test_armenia.py +++ b/tests/countries/test_armenia.py @@ -9,13 +9,14 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -from holidays.countries.armenia import AM, ARM, Armenia -from test.common import TestCase +from holidays.countries.armenia import Armenia, AM, ARM +from tests.common import TestCase class TestArmenia(TestCase): - def setUp(self): - self.holidays = Armenia() + @classmethod + def setUpClass(cls): + super().setUpClass(Armenia) def test_country_aliases(self): self.assertCountryAliases(Armenia, AM, ARM) @@ -71,7 +72,7 @@ def test_genocide_remembrance_day(self): def test_labour_day(self): self.assertHoliday(f"{year}-05-01" for year in range(2001, 2100)) self.assertNoHoliday(f"{year}-05-01" for year in range(1991, 2001)) - may1_old_name = "International Day of Workers' Solidarity" + may1_old_name = "Աշխատավորների համերաշխության միջազգային օր" self.assertIn(may1_old_name, self.holidays["2001-05-01"]) self.assertNotIn(may1_old_name, self.holidays["2002-05-01"]) @@ -89,3 +90,28 @@ def test_constitution_day(self): def test_independence_day(self): self.assertHoliday(f"{year}-09-21" for year in range(1992, 2100)) self.assertNoHoliday(f"{year}-09-21" for year in range(1991, 1992)) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + am = Armenia(language=language) + self.assertEqual(am["2022-01-01"], "Նոր տարվա օր") + self.assertEqual(am["2022-12-31"], "Նոր տարվա գիշեր") + + run_tests((Armenia.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Armenia.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + am = Armenia(language=en_us) + self.assertEqual(am["2022-01-01"], "New Year's Day") + self.assertEqual(am["2022-12-31"], "New Year's Eve") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + am = Armenia(language=language) + self.assertEqual(am["2022-01-01"], "New Year's Day") + self.assertEqual(am["2022-12-31"], "New Year's Eve") diff --git a/test/countries/test_aruba.py b/tests/countries/test_aruba.py similarity index 100% rename from test/countries/test_aruba.py rename to tests/countries/test_aruba.py diff --git a/test/countries/test_australia.py b/tests/countries/test_australia.py similarity index 95% rename from test/countries/test_australia.py rename to tests/countries/test_australia.py index 8a4df7950..39f557a99 100644 --- a/test/countries/test_australia.py +++ b/tests/countries/test_australia.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -125,7 +124,7 @@ def test_easter_monday(self): ]: self.assertIn(dt, self.holidays) self.assertEqual(self.holidays[dt], "Easter Monday") - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_bank_holiday(self): for dt in [ @@ -313,22 +312,28 @@ def test_melbourne_cup(self): self.assertEqual(self.state_hols["VIC"][dt], "Melbourne Cup") def test_royal_queensland_show(self): - for year, day in enumerate([15, 14, 14, 29, 10, 16], 2018): - if year != 2021: - dt = date(year, 8, day) - else: - dt = date(year, 10, day) - self.assertIn(dt, self.state_hols["QLD"], dt) - self.assertEqual( - self.state_hols["QLD"][dt], "The Royal Queensland Show" - ) + holiday_name = "The Royal Queensland Show" + qld_holidays = self.state_hols["QLD"] + for year, day in enumerate((15, 14, 14, 29, 10, 16), 2018): + dt = date(year, 10 if year == 2021 else 8, day) + self.assertIn(dt, qld_holidays, dt) + self.assertEqual(qld_holidays[dt], holiday_name) + + self.assertEqual( + 1, + len( + holidays.Australia(subdiv="QLD", years=2020).get_named( + holiday_name + ) + ), + ) def test_christmas_day(self): self.holidays.observed = False for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) self.assertNotIn(date(2010, 12, 24), self.holidays) self.assertNotEqual( self.holidays[date(2011, 12, 26)], "Christmas Day (Observed)" @@ -372,7 +377,7 @@ def test_boxing_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2009, 12, 28), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.holidays.observed = True diff --git a/test/countries/test_austria.py b/tests/countries/test_austria.py similarity index 77% rename from test/countries/test_austria.py rename to tests/countries/test_austria.py index 8c8c48d02..2ffdfde50 100644 --- a/test/countries/test_austria.py +++ b/tests/countries/test_austria.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -25,16 +24,16 @@ def test_new_years(self): for year in range(1900, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_christmas(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+2), self.holidays) + self.assertIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+2), self.holidays) def test_easter_monday(self): for dt in [ @@ -49,20 +48,20 @@ def test_easter_monday(self): date(2020, 4, 13), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_national_day(self): for year in range(1919, 1934): dt = date(year, 11, 12) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) for year in range(1967, 2100): dt = date(year, 10, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_all_holidays_present(self): at_2015 = holidays.AT(years=[2015]) diff --git a/test/countries/test_azerbaijan.py b/tests/countries/test_azerbaijan.py similarity index 99% rename from test/countries/test_azerbaijan.py rename to tests/countries/test_azerbaijan.py index 32b6fd712..6ada64b19 100644 --- a/test/countries/test_azerbaijan.py +++ b/tests/countries/test_azerbaijan.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.azerbaijan import AZ, AZE, Azerbaijan -from test.common import TestCase +from tests.common import TestCase class TestAzerbaijan(TestCase): diff --git a/test/countries/test_bahrain.py b/tests/countries/test_bahrain.py similarity index 94% rename from test/countries/test_bahrain.py rename to tests/countries/test_bahrain.py index 346d2681a..1458803d2 100644 --- a/test/countries/test_bahrain.py +++ b/tests/countries/test_bahrain.py @@ -12,7 +12,7 @@ import importlib.util from holidays.countries.bahrain import BH, BAH, Bahrain -from test.common import TestCase +from tests.common import TestCase class TestBahrain(TestCase): @@ -60,7 +60,7 @@ def test_2023(self): def test_hijri_based(self): if not importlib.util.find_spec("hijri_converter"): - return + return None # Eid Al-Fitr. self.assertHoliday( @@ -78,5 +78,7 @@ def test_hijri_based(self): # Islamic New Year. self.assertHoliday( + "2008-01-10", + "2008-12-29", "2020-08-20", ) diff --git a/test/countries/test_bangladesh.py b/tests/countries/test_bangladesh.py similarity index 100% rename from test/countries/test_bangladesh.py rename to tests/countries/test_bangladesh.py diff --git a/test/countries/test_belarus.py b/tests/countries/test_belarus.py similarity index 63% rename from test/countries/test_belarus.py rename to tests/countries/test_belarus.py index d83e92a8d..ccaabb5ba 100644 --- a/test/countries/test_belarus.py +++ b/tests/countries/test_belarus.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from holidays.countries.belarus import BY, BLR, Belarus -from test.common import TestCase +from tests.common import TestCase class TestBelarus(TestCase): - def setUp(self): - self.holidays = Belarus() + @classmethod + def setUpClass(cls): + super().setUpClass(Belarus) def test_country_aliases(self): self.assertCountryAliases(Belarus, BY, BLR) @@ -72,3 +73,30 @@ def test_radunitsa(self): def test_pre_1998(self): self.assertNoHoliday("1997-07-03") + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + by = Belarus(language=language) + self.assertEqual(by["2022-01-01"], "Новы год") + self.assertEqual( + by["2022-12-25"], "Нараджэнне Хрыстова (каталіцкае Раство)" + ) + + run_tests((Belarus.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Belarus.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + by = Belarus(language=en_us) + self.assertEqual(by["2018-01-01"], "New Year's Day") + self.assertEqual(by["2022-12-25"], "Catholic Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + by = Belarus(language=language) + self.assertEqual(by["2018-01-01"], "New Year's Day") + self.assertEqual(by["2022-12-25"], "Catholic Christmas Day") diff --git a/test/countries/test_belgium.py b/tests/countries/test_belgium.py similarity index 100% rename from test/countries/test_belgium.py rename to tests/countries/test_belgium.py diff --git a/tests/countries/test_bolivia.py b/tests/countries/test_bolivia.py new file mode 100644 index 000000000..d5ce1ab85 --- /dev/null +++ b/tests/countries/test_bolivia.py @@ -0,0 +1,276 @@ +# 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) +# Copyright: Kateryna Golovanova , 2022 + +from holidays.countries.bolivia import Bolivia, BO, BOL +from tests.common import TestCase + + +class TestBO(TestCase): + def setUp(self): + self.holidays = Bolivia() + self.holidays_no_observed = Bolivia(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Bolivia, BO, BOL) + + def test_new_years(self): + self.assertNoHoliday("1824-01-01") + self.assertHolidaysName( + "Año Nuevo", (f"{year}-01-01" for year in range(2000, 2050)) + ) + dt = ( + "2006-01-02", + "2012-01-02", + "2017-01-02", + "2023-01-02", + "2034-01-02", + ) + self.assertHolidaysName("Año Nuevo (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_plurinational_state_foundation_day(self): + name = "Nacimiento del Estado Plurinacional de Bolivia" + self.assertHoliday(f"{year}-01-22" for year in range(2010, 2050)) + self.assertNoHoliday(f"{year}-01-22" for year in range(2000, 2010)) + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2010))) + + def test_la_tablada(self): + name = "La Tablada" + t_holidays = Bolivia(subdiv="T") + + for year in range(2000, 2050): + self.assertNoHolidayName(name, Bolivia(years=year)) + if year not in {2022, 2033, 2044}: + self.assertNoHoliday(f"{year}-04-15") + self.assertHolidaysName(name, t_holidays, f"{year}-04-15") + else: + self.assertHolidaysName( + "La Tablada", t_holidays, f"{year}-04-15" + ) + self.assertHolidaysName( + "Viernes Santo", t_holidays, f"{year}-04-15" + ) + + def test_carnival_in_oruro(self): + name = "Carnaval de Oruro" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + + for dt in ( + "2015-02-13", + "2016-02-05", + "2017-02-24", + "2018-02-09", + "2019-03-01", + "2020-02-21", + "2021-02-12", + "2022-02-25", + "2023-02-17", + "2024-02-09", + ): + self.assertNoHoliday(dt) + self.assertHolidaysName(name, Bolivia(subdiv="O"), dt) + + def test_carnival(self): + self.assertHolidaysName( + "Feriado por Carnaval", + "2010-02-15", + "2010-02-16", + "2015-02-16", + "2015-02-17", + "2019-03-04", + "2019-03-05", + "2020-02-24", + "2020-02-25", + "2021-02-15", + "2021-02-16", + "2022-02-28", + "2022-03-01", + "2023-02-20", + "2023-02-21", + "2024-02-12", + "2024-02-13", + ) + + def test_good_friday(self): + self.assertHolidaysName( + "Viernes Santo", + "2015-04-03", + "2016-03-25", + "2017-04-14", + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + "2023-04-07", + "2024-03-29", + ) + + def test_labor_day(self): + self.assertHolidaysName( + "Día del trabajo", (f"{year}-05-01" for year in range(2000, 2050)) + ) + name = "Día del trabajo (Observed)" + dt = ( + "2005-05-02", + "2011-05-02", + "2016-05-02", + "2022-05-02", + "2033-05-02", + ) + self.assertHolidaysName(name, dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_chuquisaca_day(self): + name = "Día del departamento de Chuquisaca" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-05-25" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="H"), + (f"{year}-05-25" for year in range(2000, 2050)), + ) + + def test_corpus_christi(self): + dt = ( + "2015-06-04", + "2016-05-26", + "2017-06-15", + "2018-05-31", + "2019-06-20", + "2020-06-11", + "2021-06-03", + "2022-06-16", + "2023-06-08", + "2024-05-30", + ) + self.assertHolidaysName("Corpus Christi", dt) + + def test_andean_new_year(self): + self.assertHoliday(f"{year}-06-21" for year in range(2010, 2050)) + self.assertNoHoliday(f"{year}-06-21" for year in range(2000, 2010)) + self.assertNoHolidayName( + "Año Nuevo Andino", + Bolivia(years=range(2000, 2010)), + ) + dt = ( + "2015-06-22", + "2020-06-22", + "2026-06-22", + "2037-06-22", + "2043-06-22", + ) + self.assertHolidaysName("Año Nuevo Andino (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_la_paz_day(self): + name = "Día del departamento de La Paz" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-07-16" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="L"), + (f"{year}-07-16" for year in range(2000, 2050)), + ) + + def test_independence_day(self): + self.assertNoHoliday("1824-08-06") + self.assertHolidaysName( + "Día de la Patria", (f"{year}-08-06" for year in range(2000, 2050)) + ) + dt = ( + "2000-08-07", + "2006-08-07", + "2017-08-07", + "2023-08-07", + "2028-08-07", + ) + self.assertHolidaysName("Día de la Patria (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_cochabamba_day(self): + name = "Día del departamento de Cochabamba" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-09-14" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="C"), + (f"{year}-09-14" for year in range(2000, 2050)), + ) + + def test_santa_cruz_day(self): + name = "Día del departamento de Santa Cruz" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-09-24" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="S"), + (f"{year}-09-24" for year in range(2000, 2050)), + ) + + def test_pando_day(self): + name = "Día del departamento de Pando" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-09-24" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="N"), + (f"{year}-09-24" for year in range(2000, 2050)), + ) + + def test_all_souls_day(self): + self.assertHolidaysName( + "Todos Santos", (f"{year}-11-02" for year in range(2000, 2050)) + ) + dt = ( + "2008-11-03", + "2014-11-03", + "2025-11-03", + "2031-11-03", + "2036-11-03", + ) + self.assertHolidaysName("Todos Santos (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_potosi_day(self): + name = "Día del departamento de Potosí" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-11-10" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="P"), + (f"{year}-11-10" for year in range(2000, 2050)), + ) + + def test_beni_day(self): + name = "Día del departamento de Beni" + self.assertNoHolidayName(name, Bolivia(years=range(2000, 2050))) + self.assertNoHoliday(f"{year}-11-18" for year in range(2000, 2050)) + self.assertHolidaysName( + name, + Bolivia(subdiv="B"), + (f"{year}-11-18" for year in range(2000, 2050)), + ) + + def test_christmas_day(self): + self.assertHolidaysName( + "Navidad", (f"{year}-12-25" for year in range(2000, 2050)) + ) + dt = ( + "2005-12-26", + "2011-12-26", + "2016-12-26", + "2022-12-26", + "2033-12-26", + ) + self.assertHolidaysName("Navidad (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) diff --git a/tests/countries/test_bosnia_and_herzegovina.py b/tests/countries/test_bosnia_and_herzegovina.py new file mode 100644 index 000000000..c6dd87342 --- /dev/null +++ b/tests/countries/test_bosnia_and_herzegovina.py @@ -0,0 +1,290 @@ +# 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) +# Copyright: Kateryna Golovanova , 2022 + +from holidays.countries.bosnia_and_herzegovina import BosniaAndHerzegovina, BA +from holidays.countries.bosnia_and_herzegovina import BIH +from tests.common import TestCase + + +class TestBA(TestCase): + def setUp(self): + self.holidays = BosniaAndHerzegovina(observed=False) + self.rs_holidays = BosniaAndHerzegovina(subdiv="RS") + self.fbih_holidays = BosniaAndHerzegovina(subdiv="FBiH") + self.bd_holidays = BosniaAndHerzegovina(subdiv="BD") + + def test_country_aliases(self): + self.assertCountryAliases(BosniaAndHerzegovina, BA, BIH) + + def test_new_years(self): + self.assertHolidaysName( + "Nova Godina", (f"{year}-01-01" for year in range(2000, 2030)) + ) + self.assertHolidaysName( + "Drugi dan Nove Godine", + (f"{year}-01-02" for year in range(2000, 2030)), + ) + + name = "Treći dan Nove Godine" + dt = ( + "2006-01-03", + "2012-01-03", + "2017-01-03", + "2023-01-03", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.bd_holidays, dt) + self.assertNoHoliday(dt) + self.assertNoHoliday( + BosniaAndHerzegovina(subdiv="FBiH", observed=False), dt + ) + self.assertNoHoliday( + BosniaAndHerzegovina(subdiv="BD", observed=False), dt + ) + + def test_orthodox_christmas_eve(self): + name = "Pravoslavno Badnje veče" + dt = (f"{year}-01-06" for year in range(2000, 2030)) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + def test_orthodox_christmas(self): + self.assertHolidaysName( + "Božić (Божић)", (f"{year}-01-07" for year in range(2000, 2030)) + ) + + def test_orthodox_new_year(self): + self.assertHolidaysName( + "Pravoslavna Nova Godina", + self.rs_holidays, + (f"{year}-01-14" for year in range(2000, 2030)), + ) + + def test_independence_day(self): + self.assertHolidaysName( + "Dan nezavisnosti", + self.fbih_holidays, + (f"{year}-03-01" for year in range(2000, 2030)), + ) + + def test_establishment_bd_day(self): + self.assertHolidaysName( + "Dan uspostavljanja Brčko distrikta", + self.bd_holidays, + (f"{year}-03-08" for year in range(2000, 2030)), + ) + + def test_catholic_easter(self): + name = "Veliki Petak (Katolički)" + dt = ( + "2012-04-06", + "2015-04-03", + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + "2023-04-07", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + name = "Uskrs (Katolički)" + dt = ( + "2012-04-08", + "2015-04-05", + "2018-04-01", + "2019-04-21", + "2020-04-12", + "2021-04-04", + "2022-04-17", + "2023-04-09", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + name = "Uskrsni ponedjeljak (Katolički)" + dt = ( + "2012-04-09", + "2015-04-06", + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + "2023-04-10", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + self.assertHolidaysName(name, self.bd_holidays, dt) + self.assertHolidaysName(name, dt) + + def test_orthodox_easter(self): + name = "Veliki Petak (Pravoslavni)" + dt = ( + "2012-04-13", + "2015-04-10", + "2018-04-06", + "2019-04-26", + "2020-04-17", + "2021-04-30", + "2022-04-22", + "2023-04-14", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + self.assertHolidaysName(name, self.bd_holidays, dt) + self.assertHolidaysName(name, dt) + + name = "Vaskrs (Pravoslavni)" + dt = ( + "2012-04-15", + "2015-04-12", + "2018-04-08", + "2019-04-28", + "2020-04-19", + "2022-04-24", + "2023-04-16", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + name = "Uskrsni ponedjeljak (Pravoslavni)" + dt = ( + "2012-04-16", + "2015-04-13", + "2018-04-09", + "2019-04-29", + "2020-04-20", + "2021-05-03", + "2022-04-25", + "2023-04-17", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + def test_labor_day(self): + self.assertHolidaysName( + "Dan rada", + (f"{year}-05-01" for year in range(2000, 2030)), + ) + name = "Drugi dan Dana rada" + self.assertHolidaysName( + name, + (f"{year}-05-02" for year in range(2000, 2022)), + ) + self.assertIn(name, self.holidays.get("2022-05-02")) + self.assertHolidaysName( + name, + (f"{year}-05-02" for year in range(2023, 2030)), + ) + + name = "Treći dan Dana rada" + dt = ( + "2011-05-03", + "2016-05-03", + "2022-05-03", + ) + self.assertHolidaysName(name, BosniaAndHerzegovina(observed=True), dt) + self.assertNoHoliday(dt) + + def test_victory_day(self): + name = "Dan pobjede nad fašizmom" + dt = (f"{year}-05-09" for year in range(2000, 2030)) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + def test_eid_al_fitr(self): + dt = ( + "2010-09-10", + "2015-07-17", + "2018-06-15", + "2019-06-04", + "2020-05-24", + "2021-05-13", + "2023-04-21", + ) + self.assertHolidaysName("Ramazanski Bajram", dt) + + name = "Drugi Dan Ramazanski Bajram" + dt = ( + "2010-09-11", + "2015-07-18", + "2018-06-16", + "2019-06-05", + "2020-05-25", + "2021-05-14", + "2023-04-22", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + def test_eid_ul_adha(self): + dt = ( + "2006-01-10", + "2006-12-31", + "2010-11-16", + "2015-09-23", + "2018-08-21", + "2019-08-11", + "2020-07-31", + "2021-07-20", + "2022-07-09", + "2023-06-28", + ) + self.assertHolidaysName("Kurban Bajram", dt) + + name = "Drugi Dan Kurban Bajram" + dt = ( + "2010-11-17", + "2015-09-24", + "2018-08-22", + "2019-08-12", + "2020-08-01", + "2021-07-21", + "2022-07-10", + "2023-06-29", + ) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + self.assertIn(name, self.fbih_holidays.get("2007-01-01")) + self.assertIn(name, self.rs_holidays.get("2007-01-01")) + + def test_dayton_agreement_day(self): + self.assertHolidaysName( + "Dan uspostave Opšteg okvirnog sporazuma za mir u " + "Bosni i Hercegovini", + self.rs_holidays, + (f"{year}-11-21" for year in range(2000, 2030)), + ) + + def test_statehood_day(self): + self.assertHolidaysName( + "Dan državnosti", + self.fbih_holidays, + (f"{year}-11-25" for year in range(2004, 2030)), + ) + + def test_catholic_christmas(self): + for year in range(2010, 2025): + self.assertEqual( + self.holidays.get(f"{year}-12-25"), "Božić (Katolički)" + ) + name = "Badnji dan (Katolički)" + dt = (f"{year}-12-24" for year in range(2000, 2030)) + self.assertHolidaysName(name, self.fbih_holidays, dt) + self.assertHolidaysName(name, self.rs_holidays, dt) + + self.assertHolidaysName( + "Božić (Katolički)", + (f"{year}-12-25" for year in range(2000, 2030)), + ) diff --git a/tests/countries/test_botswana.py b/tests/countries/test_botswana.py new file mode 100644 index 000000000..6ac57757e --- /dev/null +++ b/tests/countries/test_botswana.py @@ -0,0 +1,182 @@ +# 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.botswana import Botswana, BW, BWA +from tests.common import TestCase + + +class TestBotswana(TestCase): + def setUp(self): + self.holidays = Botswana() + self.holidays_no_observed = Botswana(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Botswana, BW, BWA) + + def test_no_holidays(self): + self.assertNoHolidays(Botswana(years=1965)) + + def test_special_holidays(self): + self.assertHoliday("2019-07-02") + + def test_new_years(self): + for year in range(1966, 2050): + self.assertHoliday(f"{year}-01-01", f"{year}-01-02") + + dt = ( + "2011-01-03", + "2012-01-03", + "2017-01-03", + "2022-01-03", + "2023-01-03", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_easter(self): + dt = ( + "2020-04-10", + "2020-04-11", + "2020-04-13", + "2020-05-21", + "2022-04-15", + "2022-04-16", + "2022-04-18", + "2022-05-26", + ) + self.assertHoliday(dt) + self.assertHoliday(self.holidays_no_observed, dt) + + def test_labour_day(self): + self.assertHoliday(f"{year}-05-01" for year in range(1966, 2050)) + dt = ( + "2011-05-02", + "2016-05-02", + "2022-05-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + dt = ( + "2021-05-03", + "2027-05-03", + "2032-05-03", + ) + self.assertHolidaysName("Labour Day Holiday", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_presidents_day(self): + self.assertHoliday( + "2019-07-15", + "2019-07-16", + "2020-07-20", + "2020-07-21", + "2021-07-19", + "2021-07-20", + "2022-07-18", + "2022-07-19", + ) + + def test_botswana_day(self): + for year in range(1966, 2050): + self.assertHoliday(f"{year}-09-30", f"{year}-10-01") + + dt = ( + "2012-10-02", + "2017-10-02", + "2018-10-02", + "2023-10-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_christmas_day(self): + for year in range(1966, 2050): + self.assertHoliday(f"{year}-12-25", f"{year}-12-26") + + dt = ( + "2010-12-27", + "2011-12-27", + "2016-12-27", + "2021-12-27", + "2022-12-27", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + dt = ( + "2020-12-28", + "2026-12-28", + "2037-12-28", + ) + self.assertHolidaysName("Boxing Day Holiday", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_2021(self): + self.assertHolidayDates( + "2021-01-01", + "2021-01-02", + "2021-04-02", + "2021-04-03", + "2021-04-05", + "2021-05-01", + "2021-05-03", + "2021-05-13", + "2021-07-01", + "2021-07-19", + "2021-07-20", + "2021-09-30", + "2021-10-01", + "2021-12-25", + "2021-12-26", + "2021-12-27", + ) + + def test_2022(self): + self.assertHolidayDates( + "2022-01-01", + "2022-01-02", + "2022-01-03", + "2022-04-15", + "2022-04-16", + "2022-04-18", + "2022-05-01", + "2022-05-02", + "2022-05-26", + "2022-07-01", + "2022-07-18", + "2022-07-19", + "2022-09-30", + "2022-10-01", + "2022-12-25", + "2022-12-26", + "2022-12-27", + ) + + def test_2023(self): + self.assertHolidayDates( + "2023-01-01", + "2023-01-02", + "2023-01-03", + "2023-04-07", + "2023-04-08", + "2023-04-10", + "2023-05-01", + "2023-05-18", + "2023-07-01", + "2023-07-17", + "2023-07-18", + "2023-09-30", + "2023-10-01", + "2023-10-02", + "2023-12-25", + "2023-12-26", + ) diff --git a/test/countries/test_brazil.py b/tests/countries/test_brazil.py similarity index 98% rename from test/countries/test_brazil.py rename to tests/countries/test_brazil.py index 6e37d6751..29cb2fcb7 100644 --- a/test/countries/test_brazil.py +++ b/tests/countries/test_brazil.py @@ -128,7 +128,7 @@ def test_DF_holidays(self): df_holidays = holidays.BR(subdiv="DF") self.assertIn("2018-04-21", df_holidays) self.assertEqual( - df_holidays[date(2018, 4, 21)], "Fundação de Brasília, Tiradentes" + df_holidays[date(2018, 4, 21)], "Fundação de Brasília; Tiradentes" ) self.assertIn("2018-11-30", df_holidays) self.assertEqual(df_holidays[date(2018, 11, 30)], "Dia do Evangélico") @@ -173,7 +173,7 @@ def test_MG_holidays(self): mg_holidays = holidays.BR(subdiv="MG") self.assertIn("2018-04-21", mg_holidays) self.assertEqual( - mg_holidays[date(2018, 4, 21)], "Data Magna de MG, Tiradentes" + mg_holidays[date(2018, 4, 21)], "Data Magna de MG; Tiradentes" ) def test_PA_holidays(self): @@ -292,7 +292,7 @@ def test_TO_holidays(self): to_holidays = holidays.BR(subdiv="TO") self.assertIn("2018-01-01", to_holidays) self.assertEqual( - to_holidays[date(2018, 1, 1)], "Ano novo, Instalação de Tocantins" + to_holidays[date(2018, 1, 1)], "Ano novo; Instalação de Tocantins" ) self.assertIn("2018-09-08", to_holidays) self.assertEqual( diff --git a/test/countries/test_bulgaria.py b/tests/countries/test_bulgaria.py similarity index 65% rename from test/countries/test_bulgaria.py rename to tests/countries/test_bulgaria.py index c9ce8fc48..18be27a62 100644 --- a/test/countries/test_bulgaria.py +++ b/tests/countries/test_bulgaria.py @@ -9,20 +9,24 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -import unittest + from datetime import date +from datetime import timedelta as td -from dateutil.relativedelta import relativedelta as rd +from holidays.countries.bulgaria import Bulgaria, BG, BLG +from tests.common import TestCase -import holidays +class TestBulgaria(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Bulgaria) -class TestBulgaria(unittest.TestCase): - def setUp(self): - self.holidays = holidays.Bulgaria() + def test_country_aliases(self): + self.assertCountryAliases(Bulgaria, BG, BLG) def test_before_1990(self): - self.assertEqual(len(holidays.Bulgaria(years=[1989])), 0) + self.assertEqual(len(Bulgaria(years=[1989])), 0) def test_new_years_day(self): for year in range(1990, 2020): @@ -89,9 +93,9 @@ def test_easter(self): (2022, 4, 24), ]: easter = date(year, month, day) - easter_friday = easter + rd(days=-2) - easter_saturday = easter + rd(days=-1) - easter_monday = easter + rd(days=+1) + easter_friday = easter + td(days=-2) + easter_saturday = easter + td(days=-1) + easter_monday = easter + td(days=+1) for holiday in [ easter_friday, easter_saturday, @@ -99,3 +103,28 @@ def test_easter(self): easter_monday, ]: self.assertIn(holiday, self.holidays) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + bg = Bulgaria(language=language) + self.assertEqual(bg["2022-01-01"], "Нова година") + self.assertEqual(bg["2022-12-25"], "Рождество Христово") + + run_tests((Bulgaria.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Bulgaria.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + bg = Bulgaria(language=en_us) + self.assertEqual(bg["2018-01-01"], "New Year's Day") + self.assertEqual(bg["2022-12-25"], "Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + bg = Bulgaria(language=language) + self.assertEqual(bg["2018-01-01"], "New Year's Day") + self.assertEqual(bg["2022-12-25"], "Christmas Day") diff --git a/tests/countries/test_burundi.py b/tests/countries/test_burundi.py new file mode 100644 index 000000000..b72815d00 --- /dev/null +++ b/tests/countries/test_burundi.py @@ -0,0 +1,203 @@ +# 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.burundi import Burundi, BI, BDI +from tests.common import TestCase + + +class TestBurundi(TestCase): + def setUp(self): + self.holidays = Burundi() + + def test_country_aliases(self): + self.assertCountryAliases(Burundi, BI, BDI) + + def test_no_holidays(self): + self.assertNoHolidays(Burundi(years=1961)) + + def test_new_year_day(self): + self.assertHolidaysName( + "New Year's Day", (f"{year}-01-01" for year in range(1962, 2050)) + ) + + def test_unity_day(self): + name = "Unity Day" + self.assertNoHolidayName(name, Burundi(years=range(1962, 1992))) + self.assertHolidaysName( + name, (f"{year}-02-05" for year in range(1992, 2050)) + ) + + def test_ntaryamira_day(self): + name = "President Ntaryamira Day" + self.assertNoHolidayName(name, Burundi(years=range(1962, 1995))) + self.assertHolidaysName( + name, (f"{year}-04-06" for year in range(1995, 2050)) + ) + + def test_labour_day(self): + self.assertHolidaysName( + "Labour Day", (f"{year}-05-01" for year in range(1962, 2050)) + ) + + def test_ascension_day(self): + self.assertHolidaysName( + "Ascension Day", + "2010-05-13", + "2011-06-02", + "2012-05-17", + "2013-05-09", + "2014-05-29", + "2015-05-14", + "2016-05-05", + "2017-05-25", + "2018-05-10", + "2019-05-30", + "2020-05-21", + "2021-05-13", + "2022-05-26", + "2023-05-18", + ) + + def test_nkurunziza_day(self): + name = "President Nkurunziza Day" + self.assertNoHolidayName(name, Burundi(years=range(1962, 2022))) + self.assertHolidaysName( + name, (f"{year}-06-08" for year in range(2022, 2050)) + ) + + def test_independence_day(self): + self.assertHolidaysName( + "Independence Day", (f"{year}-07-01" for year in range(1962, 2050)) + ) + + def test_assumption_Day(self): + self.assertHolidaysName( + "Assumption Day", (f"{year}-08-15" for year in range(1962, 2050)) + ) + + def test_rwagasore_day(self): + self.assertHolidaysName( + "Prince Louis Rwagasore Day", + (f"{year}-10-13" for year in range(1962, 2050)), + ) + + def test_ndadaye_day(self): + name = "President Ndadaye's Day" + self.assertNoHolidayName(name, Burundi(years=range(1962, 1994))) + self.assertHolidaysName( + name, (f"{year}-10-21" for year in range(1994, 2050)) + ) + + def test_all_saints_Day(self): + self.assertHolidaysName( + "All Saints' Day", (f"{year}-11-01" for year in range(1962, 2050)) + ) + + def test_christmas_Day(self): + self.assertHolidaysName( + "Christmas Day", (f"{year}-12-25" for year in range(1962, 2050)) + ) + + def test_eid_ul_fitr(self): + self.assertHolidaysName( + "Eid ul Fitr", + "2010-09-10", + "2011-08-30", + "2012-08-19", + "2013-08-08", + "2014-07-28", + "2015-07-17", + "2016-07-06", + "2017-06-25", + "2018-06-15", + "2019-06-04", + "2020-05-24", + "2021-05-13", + "2022-05-02", + "2023-04-21", + ) + + def test_eid_al_adha(self): + self.assertHolidaysName( + "Eid al Adha", + "2010-11-16", + "2011-11-06", + "2012-10-26", + "2013-10-15", + "2014-10-04", + "2015-09-23", + "2016-09-11", + "2017-09-01", + "2018-08-21", + "2019-08-11", + "2020-07-31", + "2021-07-20", + "2022-07-09", + "2023-06-28", + ) + + def test_observed(self): + observed_holidays = ( + # New Year's Day + "2012-01-02", + "2017-01-02", + "2023-01-02", + # Unity Day + "2012-02-06", + "2017-02-06", + "2023-02-06", + # President Ntaryamira Day + "2008-04-07", + "2014-04-07", + "2025-04-07", + # Labour Day + "2011-05-02", + "2016-05-02", + "2033-05-02", + # President Nkurunziza Day + "2025-06-09", + "2031-06-09", + "2036-06-09", + # Independence Day + "2012-07-02", + "2018-07-02", + "2029-07-02", + # Assumption Day + "2010-08-16", + "2021-08-16", + "2027-08-16", + # Prince Louis Rwagasore Day + "2013-10-14", + "2019-10-14", + "2024-10-14", + # President Ndadaye's Day + "2012-10-22", + "2018-10-22", + "2029-10-22", + # All Saints' Day + "2015-11-02", + "2020-11-02", + "2026-11-02", + # Christmas Day + "2016-12-26", + "2022-12-26", + "2033-12-26", + # Eid ul Fitr + "2012-08-20", + "2017-06-26", + "2020-05-25", + # Eid al Adha + "2016-09-12", + "2019-08-12", + "2024-06-17", + ) + self.assertHoliday(observed_holidays) + self.assertNoHoliday(Burundi(observed=False), observed_holidays) diff --git a/test/countries/test_canada.py b/tests/countries/test_canada.py similarity index 69% rename from test/countries/test_canada.py rename to tests/countries/test_canada.py index 793856479..162ba0b51 100644 --- a/test/countries/test_canada.py +++ b/tests/countries/test_canada.py @@ -9,17 +9,24 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -import unittest from datetime import date +from datetime import timedelta as td -from dateutil.relativedelta import relativedelta as rd +from holidays.countries.canada import Canada, CA, CAN +from tests.common import TestCase -import holidays - -class TestCA(unittest.TestCase): +class TestCanada(TestCase): def setUp(self): - self.holidays = holidays.CA(observed=False) + super().setUp() + self.holidays = Canada(observed=False) + + @classmethod + def setUpClass(cls): + super().setUpClass(Canada) + + def test_country_aliases(self): + self.assertCountryAliases(Canada, CA, CAN) def test_new_years(self): self.assertNotIn(date(1866, 12, 31), self.holidays) @@ -34,11 +41,11 @@ def test_new_years(self): for year in range(1900, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_islander_day(self): - pei_holidays = holidays.CA(subdiv="PE") + pei_holidays = Canada(subdiv="PE") for dt in [ date(2009, 2, 9), date(2010, 2, 15), @@ -55,12 +62,12 @@ def test_islander_day(self): elif dt.year == 2009: self.assertNotIn(dt, self.holidays) self.assertIn(dt, pei_holidays) - self.assertNotIn(dt + rd(days=-1), pei_holidays) - self.assertNotIn(dt + rd(days=+1), pei_holidays) + self.assertNotIn(dt + td(days=-1), pei_holidays) + self.assertNotIn(dt + td(days=+1), pei_holidays) def test_yukon_heritage_day(self): # https://www.timeanddate.com/holidays/canada/heritage-day-yukon - yt_holidays = holidays.CA(subdiv="YT") + yt_holidays = Canada(subdiv="YT") for dt in [ date(2017, 2, 24), date(2018, 2, 23), @@ -70,16 +77,16 @@ def test_yukon_heritage_day(self): date(2022, 2, 25), ]: self.assertIn(dt, yt_holidays) - self.assertNotIn(dt + rd(days=-1), yt_holidays) - self.assertNotIn(dt + rd(days=+1), yt_holidays) + self.assertNotIn(dt + td(days=-1), yt_holidays) + self.assertNotIn(dt + td(days=+1), yt_holidays) def test_family_day(self): - ab_holidays = holidays.CA(subdiv="AB") - bc_holidays = holidays.CA(subdiv="BC") - mb_holidays = holidays.CA(subdiv="MB") - sk_holidays = holidays.CA(subdiv="SK") - nb_holidays = holidays.CA(subdiv="NB") - ns_holidays = holidays.CA(subdiv="NS") + ab_holidays = Canada(subdiv="AB") + bc_holidays = Canada(subdiv="BC") + mb_holidays = Canada(subdiv="MB") + sk_holidays = Canada(subdiv="SK") + nb_holidays = Canada(subdiv="NB") + ns_holidays = Canada(subdiv="NS") for dt in [ date(1990, 2, 19), date(1999, 2, 15), @@ -126,7 +133,7 @@ def test_family_day(self): self.assertEqual(ns_holidays[date(2015, 2, 16)], "Heritage Day") def test_st_patricks_day(self): - nl_holidays = holidays.CA(subdiv="NL", observed=False) + nl_holidays = Canada(subdiv="NL", observed=False) for dt in [ date(1900, 3, 19), date(1999, 3, 15), @@ -140,8 +147,8 @@ def test_st_patricks_day(self): ]: self.assertNotIn(dt, self.holidays) self.assertIn(dt, nl_holidays) - self.assertNotIn(dt + rd(days=-1), nl_holidays) - self.assertNotIn(dt + rd(days=+1), nl_holidays) + self.assertNotIn(dt + td(days=-1), nl_holidays) + self.assertNotIn(dt + td(days=+1), nl_holidays) def test_good_friday(self): for dt in [ @@ -156,8 +163,8 @@ def test_good_friday(self): date(2020, 4, 10), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_easter_monday(self): for dt in [ @@ -172,11 +179,11 @@ def test_easter_monday(self): date(2020, 4, 13), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_st_georges_day(self): - nl_holidays = holidays.CA(subdiv="NL") + nl_holidays = Canada(subdiv="NL") for dt in [ date(1990, 4, 23), date(1999, 4, 26), @@ -186,8 +193,8 @@ def test_st_georges_day(self): ]: self.assertNotIn(dt, self.holidays) self.assertIn(dt, nl_holidays) - self.assertNotIn(dt + rd(days=-1), nl_holidays) - self.assertNotIn(dt + rd(days=+1), nl_holidays) + self.assertNotIn(dt + td(days=-1), nl_holidays) + self.assertNotIn(dt + td(days=+1), nl_holidays) def test_victoria_day(self): for dt in [ @@ -199,35 +206,35 @@ def test_victoria_day(self): date(2020, 5, 18), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_national_aboriginal_day(self): - nt_holidays = holidays.CA(subdiv="NT") + nt_holidays = Canada(subdiv="NT") self.assertNotIn(date(1995, 6, 21), nt_holidays) for year in range(1996, 2100): dt = date(year, 6, 21) self.assertNotIn(dt, self.holidays) self.assertIn(dt, nt_holidays) - self.assertNotIn(dt + rd(days=-1), nt_holidays) - self.assertNotIn(dt + rd(days=+1), nt_holidays) + self.assertNotIn(dt + td(days=-1), nt_holidays) + self.assertNotIn(dt + td(days=+1), nt_holidays) def test_st_jean_baptiste_day(self): - qc_holidays = holidays.CA(subdiv="QC", observed=False) + qc_holidays = Canada(subdiv="QC", observed=False) self.assertNotIn(date(1924, 6, 24), qc_holidays) for year in range(1925, 2100): dt = date(year, 6, 24) self.assertNotIn(dt, self.holidays) self.assertIn(dt, qc_holidays) - self.assertNotIn(dt + rd(days=-1), qc_holidays) - self.assertNotIn(dt + rd(days=+1), qc_holidays) + self.assertNotIn(dt + td(days=-1), qc_holidays) + self.assertNotIn(dt + td(days=+1), qc_holidays) self.assertNotIn(date(2001, 6, 25), qc_holidays) qc_holidays.observed = True self.assertIn(date(2001, 6, 25), qc_holidays) def test_discovery_day(self): - nl_holidays = holidays.CA(subdiv="NL") - yt_holidays = holidays.CA(subdiv="YT") + nl_holidays = Canada(subdiv="NL") + yt_holidays = Canada(subdiv="YT") for dt in [ date(1997, 6, 23), date(1999, 6, 21), @@ -255,8 +262,8 @@ def test_canada_day(self): for year in range(1900, 2100): dt = date(year, 7, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2006, 7, 3), self.holidays) self.assertNotIn(date(2007, 7, 2), self.holidays) self.holidays.observed = True @@ -264,7 +271,7 @@ def test_canada_day(self): self.assertIn(date(2007, 7, 2), self.holidays) def test_nunavut_day(self): - nu_holidays = holidays.CA(subdiv="NU", observed=False) + nu_holidays = Canada(subdiv="NU", observed=False) self.assertNotIn(date(1999, 7, 9), nu_holidays) self.assertNotIn(date(2000, 7, 9), nu_holidays) self.assertIn(date(2000, 4, 1), nu_holidays) @@ -272,14 +279,14 @@ def test_nunavut_day(self): dt = date(year, 7, 9) self.assertNotIn(dt, self.holidays) self.assertIn(dt, nu_holidays) - self.assertNotIn(dt + rd(days=-1), nu_holidays) - self.assertNotIn(dt + rd(days=+1), nu_holidays) + self.assertNotIn(dt + td(days=-1), nu_holidays) + self.assertNotIn(dt + td(days=+1), nu_holidays) self.assertNotIn(date(2017, 7, 10), nu_holidays) nu_holidays.observed = True self.assertIn(date(2017, 7, 10), nu_holidays) def test_civic_holiday(self): - bc_holidays = holidays.CA(subdiv="BC") + bc_holidays = Canada(subdiv="BC") for dt in [date(1900, 8, 6), date(1955, 8, 1), date(1973, 8, 6)]: self.assertIn(dt, self.holidays) self.assertNotIn(dt, bc_holidays) @@ -305,27 +312,46 @@ def test_labour_day(self): date(2015, 9, 7), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_national_day_for_truth_and_reconciliation(self): + bc_holidays = Canada(subdiv="BC") + mb_holidays = Canada(subdiv="MB") + ns_holidays = Canada(subdiv="NS") + for dt in [ date(1991, 9, 30), date(2020, 9, 30), ]: self.assertNotIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - mb_holidays = holidays.CA(subdiv="MB") + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt, mb_holidays) + self.assertNotIn(dt, ns_holidays) for dt in [ date(2021, 9, 30), + date(2022, 9, 30), + ]: + self.assertIn(dt, mb_holidays) + self.assertIn(dt, ns_holidays) + self.assertNotIn(dt + td(days=-1), mb_holidays) + self.assertNotIn(dt + td(days=-1), ns_holidays) + self.assertNotIn(dt, self.holidays) + for dt in [ + date(2023, 9, 30), + date(2024, 9, 30), date(2030, 9, 30), ]: self.assertIn(dt, mb_holidays) - self.assertNotIn(dt + rd(days=-1), mb_holidays) + self.assertIn(dt, ns_holidays) + self.assertIn(dt, bc_holidays) + self.assertNotIn(dt + td(days=-1), mb_holidays) + self.assertNotIn(dt + td(days=-1), ns_holidays) + self.assertNotIn(dt + td(days=-1), bc_holidays) self.assertNotIn(dt, self.holidays) def test_thanksgiving(self): - ns_holidays = holidays.CA(subdiv="NB") + ns_holidays = Canada(subdiv="NB") for dt in [ date(1931, 10, 12), date(1990, 10, 8), @@ -335,13 +361,13 @@ def test_thanksgiving(self): date(2020, 10, 12), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(dt, ns_holidays) def test_remembrance_day(self): - ab_holidays = holidays.CA(subdiv="AB", observed=False) - nl_holidays = holidays.CA(subdiv="NL", observed=False) + ab_holidays = Canada(subdiv="AB", observed=False) + nl_holidays = Canada(subdiv="NL", observed=False) self.assertNotIn(date(1930, 11, 11), ab_holidays) self.assertNotIn(date(1930, 11, 11), nl_holidays) for year in range(1931, 2100): @@ -349,8 +375,8 @@ def test_remembrance_day(self): self.assertNotIn(dt, self.holidays) self.assertIn(dt, ab_holidays) self.assertIn(dt, nl_holidays) - self.assertNotIn(dt + rd(days=-1), nl_holidays) - self.assertNotIn(dt + rd(days=+1), nl_holidays) + self.assertNotIn(dt + td(days=-1), nl_holidays) + self.assertNotIn(dt + td(days=+1), nl_holidays) self.assertNotIn(date(2007, 11, 12), ab_holidays) self.assertNotIn(date(2007, 11, 12), nl_holidays) ab_holidays.observed = True @@ -363,7 +389,7 @@ def test_christmas_day(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.assertNotEqual( self.holidays[date(2011, 12, 26)], "Christmas Day (Observed)" @@ -378,7 +404,7 @@ def test_boxing_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2009, 12, 28), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.holidays.observed = True @@ -386,8 +412,8 @@ def test_boxing_day(self): self.assertIn(date(2010, 12, 27), self.holidays) def test_queens_funeral(self): - for subdiv in holidays.CA.subdivisions: - holidays_canada = holidays.CA(subdiv=subdiv) + for subdiv in Canada.subdivisions: + holidays_canada = Canada(subdiv=subdiv) for year in range(1900, 2100): if year == 2022 and subdiv in { "BC", @@ -400,3 +426,28 @@ def test_queens_funeral(self): self.assertIn(date(year, 9, 19), holidays_canada) else: self.assertNotIn(date(year, 9, 19), holidays_canada) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + ca = Canada(language=language) + self.assertEqual(ca["2022-01-01"], "New Year's Day") + self.assertEqual(ca["2022-12-25"], "Christmas Day") + + run_tests((Canada.default_language, None, "invalid")) + + self.set_language("fr") + run_tests((Canada.default_language,)) + + def test_l10n_fr(self): + fr = "fr" + + ca = Canada(language=fr) + self.assertEqual(ca["2018-01-01"], "Jour de l'an") + self.assertEqual(ca["2022-12-25"], "Jour de Noël") + + self.set_language(fr) + for language in (None, fr, "invalid"): + ca = Canada(language=language) + self.assertEqual(ca["2018-01-01"], "Jour de l'an") + self.assertEqual(ca["2022-12-25"], "Jour de Noël") diff --git a/test/countries/test_chile.py b/tests/countries/test_chile.py similarity index 79% rename from test/countries/test_chile.py rename to tests/countries/test_chile.py index 9641ae683..a8ba1244b 100644 --- a/test/countries/test_chile.py +++ b/tests/countries/test_chile.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.chile import Chile, CL, CHL -from test.common import TestCase +from tests.common import TestCase class TestChile(TestCase): @@ -67,17 +67,15 @@ def test_ascension(self): "1950-05-18", "1967-05-04", ) - for year in range(1915, 1968): - self.assertHolidayName( - Chile(years=year), - "Ascensión del Señor [Ascension of Jesus]", - ) + self.assertHolidayName( + "Ascensión del Señor [Ascension of Jesus]", + Chile(years=range(1915, 1968)), + ) - for year in range(1968, 2050): - self.assertNoHolidayName( - Chile(years=year), - "Ascensión del Señor [Ascension of Jesus]", - ) + self.assertNoHolidayName( + "Ascensión del Señor [Ascension of Jesus]", + Chile(years=range(1968, 2050)), + ) def test_corpus_christi(self): self.assertHoliday( @@ -90,21 +88,18 @@ def test_corpus_christi(self): "2000-06-19", "2006-06-12", ) - for year in range(1915, 1968): - self.assertHolidayName( - Chile(years=year), - "Corpus Christi [Corpus Christi]", - ) - for year in range(1968, 1987): - self.assertNoHolidayName( - Chile(years=year), - "Corpus Christi [Corpus Christi]", - ) - for year in range(1987, 2006): - self.assertHolidayName( - Chile(years=year), - "Corpus Christi [Corpus Christi]", - ) + self.assertHolidayName( + "Corpus Christi [Corpus Christi]", + Chile(years=range(1915, 1968)), + ) + self.assertNoHolidayName( + "Corpus Christi [Corpus Christi]", + Chile(years=range(1968, 1987)), + ) + self.assertHolidayName( + "Corpus Christi [Corpus Christi]", + Chile(years=range(1987, 2006)), + ) def test_labour_day(self): self.assertHoliday(f"{year}-05-01" for year in range(1932, 2050)) @@ -151,11 +146,10 @@ def test_indigenous_peoples_day(self): "2078-06-20", "2079-06-20", ) - for year in range(1915, 2021): - self.assertNoHolidayName( - Chile(years=year), - "Día Nacional de los Pueblos Indígenas", - ) + self.assertNoHolidayName( + "Día Nacional de los Pueblos Indígenas", + Chile(years=range(1915, 2021)), + ) def test_saint_peter_and_paul(self): self.assertHoliday(f"{year}-06-29" for year in range(1915, 1967)) @@ -188,11 +182,9 @@ def test_saint_peter_and_paul(self): "2024-06-29", ) - for year in range(1968, 1986): - self.assertNoHolidayName( - Chile(years=year), - "San Pedro y San Pablo", - ) + self.assertNoHolidayName( + "San Pedro y San Pablo", Chile(years=range(1968, 1986)) + ) def test_virgin_of_carmen(self): # Day of Virgin of Carmen started after 2006 @@ -208,16 +200,14 @@ def test_national_liberation(self): "1980-09-11", "1999-09-11", ) - for year in range(1915, 1981): - self.assertNoHolidayName( - Chile(years=year), - "Día de la Liberación Nacional", - ) - for year in range(1999, 2050): - self.assertNoHolidayName( - Chile(years=year), - "Día de la Liberación Nacional", - ) + self.assertNoHolidayName( + "Día de la Liberación Nacional", + Chile(years=range(1915, 1981)), + ) + self.assertNoHolidayName( + "Día de la Liberación Nacional", + Chile(years=range(1999, 2050)), + ) def test_national_unity(self): self.assertHoliday( @@ -230,13 +220,10 @@ def test_national_unity(self): "2002-09-02", ) - for year in range(1915, 2050): - if year in {1999, 2000, 2001}: - continue - self.assertNoHolidayName( - Chile(years=year), - "Día de la Unidad Nacional", - ) + self.assertNoHolidayName( + "Día de la Unidad Nacional", + Chile(years=set(range(1915, 2050)).difference({1999, 2000, 2001})), + ) def test_independence_holidays(self): self.assertHoliday(f"{year}-09-18" for year in range(1915, 2050)) @@ -257,13 +244,13 @@ def test_columbus_day(self): if year != 1973: self.assertHoliday(f"{year}-10-12") self.assertHolidayName( - Chile(years=year), "Día de la Raza [Columbus day]", + Chile(years=year), ) else: self.assertNoHolidayName( - Chile(years=year), "Día de la Raza [Columbus day]", + Chile(years=year), ) self.assertHoliday( @@ -278,17 +265,15 @@ def test_columbus_day(self): "2023-10-09", ) - for year in range(2000, 2020): - self.assertHolidayName( - Chile(years=year), - "Día del Respeto a la Diversidad", - ) + self.assertHolidayName( + "Día del Respeto a la Diversidad", + Chile(years=range(2000, 2020)), + ) - for year in range(2020, 2050): - self.assertHolidayName( - Chile(years=year), - "Día del Descubrimiento de dos Mundos", - ) + self.assertHolidayName( + "Día del Descubrimiento de dos Mundos", + Chile(years=range(2020, 2050)), + ) def test_reformation_day(self): self.assertHoliday( @@ -309,11 +294,10 @@ def test_reformation_day(self): "2022-10-31", "2023-10-27", ) - for year in range(1915, 2008): - self.assertNoHolidayName( - Chile(years=year), - "Día Nacional de las Iglesias Evangélicas y Protestantes", - ) + self.assertNoHolidayName( + "Día Nacional de las Iglesias Evangélicas y Protestantes", + Chile(years=range(1915, 2008)), + ) def test_all_saints(self): self.assertHoliday(f"{year}-11-01" for year in range(1915, 2050)) diff --git a/test/countries/test_china.py b/tests/countries/test_china.py similarity index 100% rename from test/countries/test_china.py rename to tests/countries/test_china.py diff --git a/test/countries/test_colombia.py b/tests/countries/test_colombia.py similarity index 99% rename from test/countries/test_colombia.py rename to tests/countries/test_colombia.py index 51eecb80b..27c16ca1b 100644 --- a/test/countries/test_colombia.py +++ b/tests/countries/test_colombia.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays from holidays.constants import APR, AUG, DEC, JAN, JUL, JUN, MAR, MAY, NOV, OCT @@ -25,7 +24,7 @@ def setUp(self): def _check_all_dates(self, year, expected_holidays): start_date = date(year, 1, 1) end_date = date(year, 12, 31) - delta = rd(days=+1) + delta = td(days=+1) while start_date <= end_date: if start_date in expected_holidays: diff --git a/test/countries/test_croatia.py b/tests/countries/test_croatia.py similarity index 100% rename from test/countries/test_croatia.py rename to tests/countries/test_croatia.py diff --git a/tests/countries/test_cuba.py b/tests/countries/test_cuba.py new file mode 100644 index 000000000..91adc87e6 --- /dev/null +++ b/tests/countries/test_cuba.py @@ -0,0 +1,273 @@ +# 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.cuba import Cuba, CU, CUB +from tests.common import TestCase + + +class TestCuba(TestCase): + def setUp(self): + self.holidays = Cuba() + + def test_country_aliases(self): + self.assertCountryAliases(Cuba, CU, CUB) + + def test_1968(self): + self.assertHolidayDates( + Cuba(years=1968), + "1968-01-01", + "1968-05-01", + "1968-07-25", + "1968-07-26", + "1968-07-27", + "1968-10-10", + "1968-12-25", + ) + + def test_1969(self): + self.assertHolidayDates( + Cuba(years=1969), + "1969-01-01", + "1969-05-01", + "1969-07-25", + "1969-07-26", + "1969-07-27", + "1969-10-10", + ) + + def test_1970(self): + self.assertHolidayDates( + Cuba(years=1970), + "1970-01-01", + "1970-05-01", + "1970-07-25", + "1970-07-26", + "1970-07-27", + "1970-10-10", + ) + + def test_1996(self): + self.assertHolidayDates( + Cuba(years=1996), + "1996-01-01", + "1996-05-01", + "1996-07-25", + "1996-07-26", + "1996-07-27", + "1996-10-10", + ) + + def test_1997(self): + self.assertHolidayDates( + Cuba(years=1997), + "1997-01-01", + "1997-05-01", + "1997-07-25", + "1997-07-26", + "1997-07-27", + "1997-10-10", + "1997-12-25", + ) + + def test_1998(self): + self.assertHolidayDates( + Cuba(years=1998), + "1998-01-01", + "1998-05-01", + "1998-07-25", + "1998-07-26", + "1998-07-27", + "1998-10-10", + "1998-12-25", + ) + + def test_2006(self): + self.assertHolidayDates( + Cuba(years=2006), + "2006-01-01", + "2006-01-02", + "2006-05-01", + "2006-07-25", + "2006-07-26", + "2006-07-27", + "2006-10-10", + "2006-12-25", + ) + + def test_2007(self): + self.assertHolidayDates( + Cuba(years=2007), + "2007-01-01", + "2007-05-01", + "2007-07-25", + "2007-07-26", + "2007-07-27", + "2007-10-10", + "2007-12-25", + "2007-12-31", + ) + + def test_2008(self): + self.assertHolidayDates( + Cuba(years=2008), + "2008-01-01", + "2008-01-02", + "2008-05-01", + "2008-07-25", + "2008-07-26", + "2008-07-27", + "2008-10-10", + "2008-12-25", + "2008-12-31", + ) + + def test_2011(self): + self.assertHolidayDates( + Cuba(years=2011), + "2011-01-01", + "2011-01-02", + "2011-05-01", + "2011-05-02", + "2011-07-25", + "2011-07-26", + "2011-07-27", + "2011-10-10", + "2011-12-25", + "2011-12-31", + ) + + def test_2012(self): + self.assertHolidayDates( + Cuba(years=2012), + "2012-01-01", + "2012-01-02", + "2012-04-06", + "2012-05-01", + "2012-07-25", + "2012-07-26", + "2012-07-27", + "2012-10-10", + "2012-12-25", + "2012-12-31", + ) + + def test_2013(self): + self.assertHolidayDates( + Cuba(years=2013), + "2013-01-01", + "2013-01-02", + "2013-03-29", + "2013-05-01", + "2013-07-25", + "2013-07-26", + "2013-07-27", + "2013-10-10", + "2013-12-25", + "2013-12-31", + ) + + def test_2018(self): + # https://www.officeholidays.com/countries/cuba/2018 + self.assertHolidayDates( + Cuba(years=2018), + "2018-01-01", + "2018-01-02", + "2018-03-30", + "2018-05-01", + "2018-07-25", + "2018-07-26", + "2018-07-27", + "2018-10-10", + "2018-12-25", + "2018-12-31", + ) + + def test_2019(self): + # https://www.officeholidays.com/countries/cuba/2019 + self.assertHolidayDates( + Cuba(years=2019), + "2019-01-01", + "2019-01-02", + "2019-04-19", + "2019-05-01", + "2019-07-25", + "2019-07-26", + "2019-07-27", + "2019-10-10", + "2019-12-25", + "2019-12-31", + ) + + def test_2020(self): + # https://www.officeholidays.com/countries/cuba/2020 + self.assertHolidayDates( + Cuba(years=2020), + "2020-01-01", + "2020-01-02", + "2020-04-10", + "2020-05-01", + "2020-07-25", + "2020-07-26", + "2020-07-27", + "2020-10-10", + "2020-12-25", + "2020-12-31", + ) + + def test_2021(self): + # https://www.officeholidays.com/countries/cuba/2021 + self.assertHolidayDates( + Cuba(years=2021), + "2021-01-01", + "2021-01-02", + "2021-04-02", + "2021-05-01", + "2021-07-25", + "2021-07-26", + "2021-07-27", + "2021-10-10", + "2021-10-11", + "2021-12-25", + "2021-12-31", + ) + + def test_2022(self): + # https://www.officeholidays.com/countries/cuba/2022 + self.assertHolidayDates( + Cuba(years=2022), + "2022-01-01", + "2022-01-02", + "2022-04-15", + "2022-05-01", + "2022-05-02", + "2022-07-25", + "2022-07-26", + "2022-07-27", + "2022-10-10", + "2022-12-25", + "2022-12-31", + ) + + def test_2023(self): + # https://www.officeholidays.com/countries/cuba/2023 + self.assertHolidayDates( + Cuba(years=2023), + "2023-01-01", + "2023-01-02", + "2023-04-07", + "2023-05-01", + "2023-07-25", + "2023-07-26", + "2023-07-27", + "2023-10-10", + "2023-12-25", + "2023-12-31", + ) diff --git a/test/countries/test_curacao.py b/tests/countries/test_curacao.py similarity index 100% rename from test/countries/test_curacao.py rename to tests/countries/test_curacao.py diff --git a/tests/countries/test_cyprus.py b/tests/countries/test_cyprus.py new file mode 100644 index 000000000..54bcd374d --- /dev/null +++ b/tests/countries/test_cyprus.py @@ -0,0 +1,143 @@ +# 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 holidays.countries.cyprus import Cyprus, CY, CYP +from tests.common import TestCase + + +class TestCyprus(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Cyprus) + + def test_country_aliases(self): + self.assertCountryAliases(Cyprus, CY, CYP) + + def test_fixed_holidays(self): + years = range(2000, 2025) + for y in years: + fdays = ( + (date(y, 1, 1), "Πρωτοχρονιά"), + (date(y, 1, 6), "Θεοφάνεια"), + (date(y, 3, 25), "Εικοστή Πέμπτη Μαρτίου"), + (date(y, 4, 1), "1η Απριλίου"), + (date(y, 5, 1), "Εργατική Πρωτομαγιά"), + (date(y, 8, 15), "Κοίμηση της Θεοτόκου"), + (date(y, 10, 28), "Ημέρα του Όχι"), + (date(y, 12, 25), "Χριστούγεννα"), + (date(y, 12, 26), "Δεύτερη μέρα Χριστουγέννων"), + ) + + for d, dstr in fdays: + self.assertIn(d, self.holidays) + self.assertIn(dstr, self.holidays[d]) + + def test_cy_clean_monday(self): + checkdates = ( + date(2018, 2, 19), + date(2019, 3, 11), + date(2020, 3, 2), + date(2021, 3, 15), + date(2022, 3, 7), + date(2023, 2, 27), + date(2024, 3, 18), + ) + + for d in checkdates: + self.assertIn(d, self.holidays) + self.assertIn("Καθαρά Δευτέρα", self.holidays[d]) + + def test_cy_good_friday(self): + checkdates = ( + date(2018, 4, 6), + date(2019, 4, 26), + date(2020, 4, 17), + date(2021, 4, 30), + date(2022, 4, 22), + date(2023, 4, 14), + date(2024, 5, 3), + ) + + for d in checkdates: + self.assertIn(d, self.holidays) + self.assertIn("Μεγάλη Παρασκευή", self.holidays[d]) + + def test_cy_easter_sunday(self): + checkdates = ( + date(2018, 4, 8), + date(2019, 4, 28), + date(2020, 4, 19), + date(2021, 5, 2), + date(2022, 4, 24), + date(2023, 4, 16), + date(2024, 5, 5), + ) + + for d in checkdates: + self.assertIn(d, self.holidays) + self.assertIn("Κυριακή του Πάσχα", self.holidays[d]) + + def test_cy_easter_monday(self): + checkdates = ( + date(2018, 4, 9), + date(2019, 4, 29), + date(2020, 4, 20), + date(2021, 5, 3), + date(2022, 4, 25), + date(2023, 4, 17), + date(2024, 5, 6), + ) + + for d in checkdates: + self.assertIn(d, self.holidays) + self.assertIn("Δευτέρα του Πάσχα", self.holidays[d]) + + def test_cy_monday_of_the_holy_spirit(self): + checkdates = ( + date(2018, 5, 28), + date(2019, 6, 17), + date(2020, 6, 8), + date(2021, 6, 21), + date(2022, 6, 13), + date(2023, 6, 5), + date(2024, 6, 24), + ) + + for d in checkdates: + self.assertIn(d, self.holidays) + self.assertIn("Δευτέρα του Αγίου Πνεύματος", self.holidays[d]) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + cy = Cyprus(language=language) + self.assertEqual(cy["2022-01-01"], "Πρωτοχρονιά") + self.assertEqual(cy["2022-12-25"], "Χριστούγεννα") + + run_tests((Cyprus.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Cyprus.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + cy = Cyprus(language=en_us) + self.assertEqual(cy["2022-01-01"], "New Year's Day") + self.assertEqual(cy["2022-12-25"], "Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + cy = Cyprus(language=language) + self.assertEqual(cy["2022-01-01"], "New Year's Day") + self.assertEqual(cy["2022-12-25"], "Christmas Day") diff --git a/test/countries/test_czechia.py b/tests/countries/test_czechia.py similarity index 100% rename from test/countries/test_czechia.py rename to tests/countries/test_czechia.py diff --git a/tests/countries/test_denmark.py b/tests/countries/test_denmark.py new file mode 100644 index 000000000..a6fb134a9 --- /dev/null +++ b/tests/countries/test_denmark.py @@ -0,0 +1,60 @@ +# 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 holidays.countries.denmark import Denmark, DK, DNK +from tests.common import TestCase + + +class TestDenmark(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Denmark) + + def test_country_aliases(self): + self.assertCountryAliases(Denmark, DK, DNK) + + def test_2016(self): + # http://www.officeholidays.com/countries/denmark/2016.php + self.assertIn(date(2016, 1, 1), self.holidays) + self.assertIn(date(2016, 3, 24), self.holidays) + self.assertIn(date(2016, 3, 25), self.holidays) + self.assertIn(date(2016, 3, 28), self.holidays) + self.assertIn(date(2016, 4, 22), self.holidays) + self.assertIn(date(2016, 5, 5), self.holidays) + self.assertIn(date(2016, 5, 16), self.holidays) + self.assertIn(date(2016, 12, 25), self.holidays) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + dk = Denmark(language=language) + self.assertEqual(dk["2022-01-01"], "Nytårsdag") + self.assertEqual(dk["2022-12-25"], "Juledag") + + run_tests((Denmark.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Denmark.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + dk = Denmark(language=en_us) + self.assertEqual(dk["2022-01-01"], "New Year's Day") + self.assertEqual(dk["2022-12-25"], "Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + dk = Denmark(language=language) + self.assertEqual(dk["2022-01-01"], "New Year's Day") + self.assertEqual(dk["2022-12-25"], "Christmas Day") diff --git a/test/countries/test_djibouti.py b/tests/countries/test_djibouti.py similarity index 93% rename from test/countries/test_djibouti.py rename to tests/countries/test_djibouti.py index 0a18e817d..d59d3a0c1 100644 --- a/test/countries/test_djibouti.py +++ b/tests/countries/test_djibouti.py @@ -30,7 +30,6 @@ def test_labour_day(self): def test_hijri_based(self): if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.DJ(years=[2010]) self.assertIn(date(2019, 6, 5), self.holidays) self.assertIn(date(2019, 8, 10), self.holidays) self.assertIn(date(2019, 8, 11), self.holidays) @@ -42,6 +41,8 @@ def test_hijri_based(self): # eid_aladha self.assertIn(date(2019, 8, 11), self.holidays) # islamic_new_year + self.assertIn(date(2008, 1, 10), self.holidays) + self.assertIn(date(2008, 12, 29), self.holidays) self.assertIn(date(2019, 8, 31), self.holidays) # arafat_2019 self.assertIn(date(2019, 8, 10), self.holidays) diff --git a/test/countries/test_dominican_republic.py b/tests/countries/test_dominican_republic.py similarity index 99% rename from test/countries/test_dominican_republic.py rename to tests/countries/test_dominican_republic.py index 3108cb792..e410332ae 100644 --- a/test/countries/test_dominican_republic.py +++ b/tests/countries/test_dominican_republic.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.dominican_republic import DO, DOM, DominicanRepublic -from test.common import TestCase +from tests.common import TestCase class TestDominicanRepublic(TestCase): diff --git a/test/countries/test_egypt.py b/tests/countries/test_egypt.py similarity index 96% rename from test/countries/test_egypt.py rename to tests/countries/test_egypt.py index dfbfa4f31..8de55f5d4 100644 --- a/test/countries/test_egypt.py +++ b/tests/countries/test_egypt.py @@ -64,7 +64,6 @@ def test_25_jan_from_2009(self): def test_hijri_based(self): if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.EG(years=[2010]) self.assertIn(date(2019, 6, 5), self.holidays) self.assertIn(date(2019, 8, 10), self.holidays) self.assertIn(date(2019, 8, 11), self.holidays) @@ -76,6 +75,8 @@ def test_hijri_based(self): # eid_aladha self.assertIn(date(2019, 8, 11), self.holidays) # islamic_new_year + self.assertIn(date(2008, 1, 10), self.holidays) + self.assertIn(date(2008, 12, 29), self.holidays) self.assertIn(date(2019, 8, 31), self.holidays) # eid_elfetr_2010 self.assertIn(date(2010, 9, 10), self.holidays) diff --git a/test/countries/test_estonia.py b/tests/countries/test_estonia.py similarity index 100% rename from test/countries/test_estonia.py rename to tests/countries/test_estonia.py diff --git a/tests/countries/test_eswatini.py b/tests/countries/test_eswatini.py new file mode 100644 index 000000000..8c91263b5 --- /dev/null +++ b/tests/countries/test_eswatini.py @@ -0,0 +1,125 @@ +# 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) + +import warnings + +import holidays +from holidays.countries.eswatini import Eswatini, SZ, SZW +from tests.common import TestCase + + +class TestEswatini(TestCase): + def setUp(self): + self.holidays = Eswatini() + + def test_country_aliases(self): + self.assertCountryAliases(Eswatini, SZ, SZW) + + def test_no_holidays(self): + self.assertNoHolidays(Eswatini(years=1938)) + + def test_special_holidays(self): + self.assertHoliday( + "1999-12-31", + "2000-01-03", + ) + + def test_holidays(self): + for year in range(1939, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-05-01", + f"{year}-09-06", + f"{year}-12-25", + f"{year}-12-26", + ) + + def test_kings_birthday(self): + self.assertNoHolidayName( + "King's Birthday", + Eswatini(years=range(1939, 1987)), + ) + self.assertHoliday(f"{year}-04-19" for year in range(1987, 2050)) + + def test_national_flag_day(self): + self.assertNoHoliday(f"{year}-04-25" for year in range(1939, 1969)) + self.assertNoHolidayName( + "National Flag Day", + Eswatini(years=range(1939, 1969)), + ) + self.assertHoliday(f"{year}-04-25" for year in range(1969, 2050)) + + def test_late_king_sobhuza(self): + self.assertNoHoliday(f"{year}-07-22" for year in range(1939, 1983)) + self.assertNoHolidayName( + "Birthday of Late King Sobhuza", + Eswatini(years=range(1939, 1983)), + ) + self.assertHoliday(f"{year}-07-22" for year in range(1983, 2050)) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + # Ascension Day + "2018-05-10", + "2019-05-30", + "2020-05-21", + "2021-05-13", + "2022-05-26", + ) + + def test_observed(self): + dt = ( + # New Year's Day + "2023-01-02", + # King's Birthday + "2026-04-20", + "2071-04-21", + "2076-04-21", + "2082-04-21", + # National Flag Day + "2021-04-26", + "2027-04-26", + "2038-04-27", + # Worker's Day + "2022-05-02", + # Birthday of Late King Sobhuza + "2029-07-23", + # Independence Day + "2026-09-07", + # Christmas Day + "2022-12-27", + # Boxing Day + "2021-12-27", + "2027-12-27", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Eswatini(observed=False), dt) + + def test_swaziland_deprecation_warning(self): + warnings.simplefilter("default") + with self.assertWarns(Warning): + holidays.Swaziland() + + warnings.simplefilter("error") + with self.assertRaises(Warning): + holidays.Swaziland() diff --git a/test/countries/test_ethiopia.py b/tests/countries/test_ethiopia.py similarity index 71% rename from test/countries/test_ethiopia.py rename to tests/countries/test_ethiopia.py index 8ee855fb0..5c22b9aaf 100644 --- a/test/countries/test_ethiopia.py +++ b/tests/countries/test_ethiopia.py @@ -10,15 +10,19 @@ # License: MIT (see LICENSE file) import importlib.util -import unittest from datetime import date -import holidays +from holidays.countries.ethiopia import Ethiopia, ET, ETH +from tests.common import TestCase -class TestEthiopia(unittest.TestCase): - def setUp(self): - self.holidays = holidays.ET() +class TestEthiopia(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Ethiopia) + + def test_country_aliases(self): + self.assertCountryAliases(Ethiopia, ET, ETH) # Check isleap loops def test_not_holiday(self): @@ -82,9 +86,9 @@ def test_formation_of_dergue(self): def test_hijri_based(self): if not importlib.util.find_spec("hijri_converter"): - return + return None - self.holidays = holidays.ET(years=[2019]) + self.holidays = Ethiopia(years=[2019]) # eid_alfitr self.assertIn(date(2019, 6, 4), self.holidays) # eid_aladha @@ -94,3 +98,28 @@ def test_hijri_based(self): def test_pre_1897(self): self.assertNotIn(date(1896, 3, 2), self.holidays) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + et = Ethiopia(language=language) + self.assertEqual(et["2022-01-07"], "ገና") + self.assertEqual(et["2022-09-11"], "አዲስ ዓመት እንቁጣጣሽ") + + run_tests((Ethiopia.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Ethiopia.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + et = Ethiopia(language=en_us) + self.assertEqual(et["2022-01-07"], "Orthodox Christmas Day") + self.assertEqual(et["2022-09-11"], "Ethiopian New Year's Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + et = Ethiopia(language=language) + self.assertEqual(et["2022-01-07"], "Orthodox Christmas Day") + self.assertEqual(et["2022-09-11"], "Ethiopian New Year's Day") diff --git a/test/countries/test_finland.py b/tests/countries/test_finland.py similarity index 100% rename from test/countries/test_finland.py rename to tests/countries/test_finland.py diff --git a/test/countries/test_france.py b/tests/countries/test_france.py similarity index 100% rename from test/countries/test_france.py rename to tests/countries/test_france.py diff --git a/test/countries/test_georgia.py b/tests/countries/test_georgia.py similarity index 56% rename from test/countries/test_georgia.py rename to tests/countries/test_georgia.py index a7c45abac..92e78475a 100644 --- a/test/countries/test_georgia.py +++ b/tests/countries/test_georgia.py @@ -10,12 +10,13 @@ # License: MIT (see LICENSE file) from holidays.countries.georgia import GE, GEO, Georgia -from test.common import TestCase +from tests.common import TestCase class TestGeorgia(TestCase): - def setUp(self): - self.holidays = Georgia() + @classmethod + def setUpClass(cls): + super().setUpClass(Georgia) def test_country_aliases(self): self.assertCountryAliases(Georgia, GE, GEO) @@ -50,3 +51,28 @@ def test_not_holiday(self): "2020-08-16", "2008-08-05", ) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + ge = Georgia(language=language) + self.assertEqual(ge["2022-01-01"], "ახალი წელი") + self.assertEqual(ge["2022-01-07"], "ქრისტეშობა") + + run_tests((Georgia.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Georgia.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + ge = Georgia(language=en_us) + self.assertEqual(ge["2022-01-01"], "New Year's Day") + self.assertEqual(ge["2022-01-07"], "Orthodox Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + ge = Georgia(language=language) + self.assertEqual(ge["2022-01-01"], "New Year's Day") + self.assertEqual(ge["2022-01-07"], "Orthodox Christmas Day") diff --git a/test/countries/test_germany.py b/tests/countries/test_germany.py similarity index 92% rename from test/countries/test_germany.py rename to tests/countries/test_germany.py index 010fd3074..2648a1c4b 100644 --- a/test/countries/test_germany.py +++ b/tests/countries/test_germany.py @@ -196,18 +196,30 @@ def test_weltkindertag(self): self.assertNotIn(date(y, m, d), self.prov_hols[province]) def test_frauentag(self): - known_good = [ - (2019, 3, 8), - ] + prov_yes_since_2019 = {"BE"} + prov_yes_since_2023 = prov_yes_since_2019.union({"MV"}) - provinces_that_have = {"BE"} - provinces_that_dont = ( - set(holidays.DE.subdivisions) - provinces_that_have + prov_not_since_2019 = ( + set(holidays.DE.subdivisions) - prov_yes_since_2019 + ) + prov_not_since_2023 = ( + set(holidays.DE.subdivisions) - prov_yes_since_2023 + ) + + prov_year_yes = list( + product(prov_yes_since_2019, range(2019, 2023)) + ) + list(product(prov_yes_since_2023, range(2023, 2050))) + prov_year_not = ( + list(product(set(holidays.DE.subdivisions), range(1991, 2019))) + + list(product(prov_not_since_2019, range(2019, 2023))) + + list(product(prov_not_since_2023, range(2023, 2050))) ) - for province, (y, m, d) in product(provinces_that_have, known_good): - self.assertIn(date(y, m, d), self.prov_hols[province]) - for province, (y, m, d) in product(provinces_that_dont, known_good): - self.assertNotIn(date(y, m, d), self.prov_hols[province]) + + for province, year in prov_year_yes: + self.assertIn(date(year, 3, 8), self.prov_hols[province]) + + for province, year in prov_year_not: + self.assertNotIn(date(year, 3, 8), self.prov_hols[province]) def test_pfingstsonntag(self): known_good = [ @@ -346,16 +358,3 @@ def test_buss_und_bettag(self): self.assertIn(date(y, m, d), self.prov_hols[province]) for province, (y, m, d) in product(provinces_that_dont, known_good): self.assertNotIn(date(y, m, d), self.prov_hols[province]) - - def test_internationaler_frauentag(self): - prov_that_have = {"BE"} - prov_that_dont = set(holidays.DE.subdivisions) - prov_that_have - - for province, year in product( - holidays.DE.subdivisions, range(1991, 2018) - ): - self.assertNotIn(date(year, 3, 8), self.prov_hols[province]) - for province, year in product(prov_that_have, range(2019, 2050)): - self.assertIn(date(year, 3, 8), self.prov_hols[province]) - for province, year in product(prov_that_dont, range(2019, 2050)): - self.assertNotIn(date(year, 3, 8), self.prov_hols[province]) diff --git a/test/countries/test_greece.py b/tests/countries/test_greece.py similarity index 52% rename from test/countries/test_greece.py rename to tests/countries/test_greece.py index a99d28eac..bf453096e 100644 --- a/test/countries/test_greece.py +++ b/tests/countries/test_greece.py @@ -9,43 +9,37 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -import unittest from datetime import date -import holidays +from holidays.countries.greece import Greece, GR, GRC +from tests.common import TestCase -class TestGreece(unittest.TestCase): - def setUp(self): - self.gr_holidays = holidays.GR() +class TestGreece(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Greece) + + def test_country_aliases(self): + self.assertCountryAliases(Greece, GR, GRC) def test_fixed_holidays(self): years = range(2000, 2025) for y in years: fdays = ( - (date(y, 1, 1), "Πρωτοχρονιά [New Year's Day]"), - (date(y, 1, 6), "Θεοφάνεια [Epiphany]"), - ( - date(y, 3, 25), - "Εικοστή Πέμπτη Μαρτίου " + "[Independence Day]", - ), - (date(y, 5, 1), "Εργατική Πρωτομαγιά [Labour day]"), - ( - date(y, 8, 15), - "Κοίμηση της Θεοτόκου " + "[Assumption of Mary]", - ), - (date(y, 10, 28), "Ημέρα του Όχι [Ochi Day]"), - (date(y, 12, 25), "Χριστούγεννα [Christmas]"), - ( - date(y, 12, 26), - "Επόμενη ημέρα των Χριστουγέννων " - + "[Day after Christmas]", - ), + (date(y, 1, 1), "Πρωτοχρονιά"), + (date(y, 1, 6), "Θεοφάνεια"), + (date(y, 3, 25), "Εικοστή Πέμπτη Μαρτίου"), + (date(y, 5, 1), "Εργατική Πρωτομαγιά"), + (date(y, 8, 15), "Κοίμηση της Θεοτόκου"), + (date(y, 10, 28), "Ημέρα του Όχι"), + (date(y, 12, 25), "Χριστούγεννα"), + (date(y, 12, 26), "Επόμενη ημέρα των Χριστουγέννων"), ) - for (d, dstr) in fdays: - self.assertIn(d, self.gr_holidays) - self.assertIn(dstr, self.gr_holidays[d]) + for d, dstr in fdays: + self.assertIn(d, self.holidays) + self.assertIn(dstr, self.holidays[d]) def test_gr_clean_monday(self): checkdates = ( @@ -59,8 +53,8 @@ def test_gr_clean_monday(self): ) for d in checkdates: - self.assertIn(d, self.gr_holidays) - self.assertIn("Καθαρά Δευτέρα [Clean Monday]", self.gr_holidays[d]) + self.assertIn(d, self.holidays) + self.assertIn("Καθαρά Δευτέρα", self.holidays[d]) def test_gr_easter_monday(self): checkdates = ( @@ -74,10 +68,8 @@ def test_gr_easter_monday(self): ) for d in checkdates: - self.assertIn(d, self.gr_holidays) - self.assertIn( - "Δευτέρα του Πάσχα [Easter Monday]", self.gr_holidays[d] - ) + self.assertIn(d, self.holidays) + self.assertIn("Δευτέρα του Πάσχα", self.holidays[d]) def test_gr_monday_of_the_holy_spirit(self): checkdates = ( @@ -91,11 +83,8 @@ def test_gr_monday_of_the_holy_spirit(self): ) for d in checkdates: - self.assertIn(d, self.gr_holidays) - self.assertIn( - "Δευτέρα του Αγίου Πνεύματος " + "[Monday of the Holy Spirit]", - self.gr_holidays[d], - ) + self.assertIn(d, self.holidays) + self.assertIn("Δευτέρα του Αγίου Πνεύματος", self.holidays[d]) def test_gr_labour_day_observed(self): # Dates when labour day was observed on a different date @@ -109,19 +98,13 @@ def test_gr_labour_day_observed(self): checkyears = (2017, 2018, 2019, 2020, 2023) for d in checkdates: - self.assertIn(d, self.gr_holidays) - self.assertIn( - "Εργατική Πρωτομαγιά [Labour day] (Observed)", - self.gr_holidays[d], - ) + self.assertIn(d, self.holidays) + self.assertIn("Εργατική Πρωτομαγιά", self.holidays[d]) # Check that there is no observed day created for years # when Labour Day was on May 1st for year in checkyears: for day in (2, 3, 4): d = date(year, 5, day) - if d in self.gr_holidays: - self.assertNotIn( - "Εργατική Πρωτομαγιά [Labour day] (Observed)", - self.gr_holidays[d], - ) + if d in self.holidays: + self.assertNotIn("Εργατική Πρωτομαγιά", self.holidays[d]) diff --git a/tests/countries/test_guam.py b/tests/countries/test_guam.py new file mode 100644 index 000000000..cac3fe3a0 --- /dev/null +++ b/tests/countries/test_guam.py @@ -0,0 +1,37 @@ +# 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) + +import unittest +from datetime import date + +import holidays +from holidays.constants import MAR + + +class TestGU(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysGU() + + def test_GU_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + self.assertIn( + "Guam Discovery Day", + self.holidays.get_list(date(2016, MAR, 7)), + ) + + def test_aliases(self): + """For coverage purposes""" + for h in [holidays.GU(), holidays.GUM(), holidays.Guam()]: + self.assertIsInstance(h, holidays.HolidaysGU) diff --git a/test/countries/test_honduras.py b/tests/countries/test_honduras.py similarity index 96% rename from test/countries/test_honduras.py rename to tests/countries/test_honduras.py index 22ec3790b..15b13d853 100644 --- a/test/countries/test_honduras.py +++ b/tests/countries/test_honduras.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.honduras import HN, HND, Honduras -from test.common import TestCase +from tests.common import TestCase class TestHonduras(TestCase): @@ -72,7 +72,7 @@ def test_2022(self): ("2022-01-01", "Año Nuevo [New Year's Day]"), ( "2022-04-14", - "Día de las Américas [Panamerican Day], " + "Día de las Américas [Panamerican Day]; " "Jueves Santo [Maundy Thursday]", ), ("2022-04-15", "Viernes Santo [Good Friday]"), diff --git a/test/countries/test_hongkong.py b/tests/countries/test_hongkong.py similarity index 99% rename from test/countries/test_hongkong.py rename to tests/countries/test_hongkong.py index 28b4d79dd..02c1d8c72 100644 --- a/test/countries/test_hongkong.py +++ b/tests/countries/test_hongkong.py @@ -20,8 +20,6 @@ def setUp(self): self.holidays = holidays.HK() def test_common(self): - self.assertTrue(self.holidays.is_leap_year(2000)) - self.assertFalse(self.holidays.is_leap_year(2100)) holidays_no_observed = holidays.HK(observed=False) self.assertEqual( holidays_no_observed[date(2019, 1, 1)], "The first day of January" diff --git a/test/countries/test_hungary.py b/tests/countries/test_hungary.py similarity index 100% rename from test/countries/test_hungary.py rename to tests/countries/test_hungary.py diff --git a/test/countries/test_iceland.py b/tests/countries/test_iceland.py similarity index 100% rename from test/countries/test_iceland.py rename to tests/countries/test_iceland.py diff --git a/test/countries/test_india.py b/tests/countries/test_india.py similarity index 98% rename from test/countries/test_india.py rename to tests/countries/test_india.py index 4873ff482..602421bf3 100644 --- a/test/countries/test_india.py +++ b/tests/countries/test_india.py @@ -12,12 +12,13 @@ import warnings from holidays.countries.india import IN, IND, India -from test.common import TestCase +from tests.common import TestCase class TestIndia(TestCase): def setUp(self): self.holidays = India() + warnings.simplefilter("ignore") def test_country_aliases(self): self.assertCountryAliases(India, IN, IND) diff --git a/test/countries/test_indonesia.py b/tests/countries/test_indonesia.py similarity index 99% rename from test/countries/test_indonesia.py rename to tests/countries/test_indonesia.py index 335965c3d..981b71900 100644 --- a/test/countries/test_indonesia.py +++ b/tests/countries/test_indonesia.py @@ -12,7 +12,7 @@ from datetime import date from holidays.countries.indonesia import ID, IDN, Indonesia -from test.common import TestCase +from tests.common import TestCase class TestIndonesia(TestCase): diff --git a/test/countries/test_ireland.py b/tests/countries/test_ireland.py similarity index 89% rename from test/countries/test_ireland.py rename to tests/countries/test_ireland.py index 7ff344e35..0d052fa57 100644 --- a/test/countries/test_ireland.py +++ b/tests/countries/test_ireland.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -49,8 +48,8 @@ def test_may_day(self): date(2020, 5, 4), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_st_stephens_day(self): # St. Stephen's Day @@ -59,7 +58,7 @@ def test_st_stephens_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2009, 12, 28), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.holidays.observed = True @@ -98,8 +97,8 @@ def test_st_stephens_day(self): [ "St. Stephen's Day", "St. Stephen's Day (Observed)", - "Christmas Day (Observed), St. Stephen's Day", - "St. Stephen's Day, Christmas Day (Observed)", + "Christmas Day (Observed); St. Stephen's Day", + "St. Stephen's Day; Christmas Day (Observed)", ], ) diff --git a/test/countries/test_isle_of_man.py b/tests/countries/test_isle_of_man.py similarity index 100% rename from test/countries/test_isle_of_man.py rename to tests/countries/test_isle_of_man.py diff --git a/test/countries/test_israel.py b/tests/countries/test_israel.py similarity index 83% rename from test/countries/test_israel.py rename to tests/countries/test_israel.py index 8abacee4a..b42f7c94c 100644 --- a/test/countries/test_israel.py +++ b/tests/countries/test_israel.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -42,8 +41,8 @@ def _test_observed_holidays(self, holiday_name): # Postponed il_holidays = holidays.IL(years=[2017], observed=True) - official_memorial_day = date(2017, 4, 30) + rd(days=days_delta) - observed_memorial_day = date(2017, 5, 1) + rd(days=days_delta) + official_memorial_day = date(2017, 4, 30) + td(days=days_delta) + observed_memorial_day = date(2017, 5, 1) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) self.assertIn(observed_memorial_day, il_holidays) @@ -53,8 +52,8 @@ def _test_observed_holidays(self, holiday_name): # Earlier il_holidays = holidays.IL(years=[2018], observed=True) - official_memorial_day = date(2018, 4, 19) + rd(days=days_delta) - observed_memorial_day = date(2018, 4, 18) + rd(days=days_delta) + official_memorial_day = date(2018, 4, 19) + td(days=days_delta) + observed_memorial_day = date(2018, 4, 18) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) self.assertIn(observed_memorial_day, il_holidays) @@ -64,7 +63,7 @@ def _test_observed_holidays(self, holiday_name): # On time il_holidays = holidays.IL(years=[2020], observed=True) - official_memorial_day = date(2020, 4, 28) + rd(days=days_delta) + official_memorial_day = date(2020, 4, 28) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) @@ -76,23 +75,23 @@ def _test_nonobserved_holidays(self, holiday_name): # Postponed il_holidays = holidays.IL(years=[2017], observed=False) - official_memorial_day = date(2017, 4, 30) + rd(days=days_delta) - observed_memorial_day = date(2017, 5, 1) + rd(days=days_delta) + official_memorial_day = date(2017, 4, 30) + td(days=days_delta) + observed_memorial_day = date(2017, 5, 1) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) self.assertNotEqual(il_holidays[observed_memorial_day], "Memorial Day") # Earlier il_holidays = holidays.IL(years=[2018], observed=False) - official_memorial_day = date(2018, 4, 19) + rd(days=days_delta) - observed_memorial_day = date(2018, 4, 18) + rd(days=days_delta) + official_memorial_day = date(2018, 4, 19) + td(days=days_delta) + observed_memorial_day = date(2018, 4, 18) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) self.assertNotIn(observed_memorial_day, il_holidays) # On time il_holidays = holidays.IL(years=[2020], observed=False) - official_memorial_day = date(2020, 4, 28) + rd(days=days_delta) + official_memorial_day = date(2020, 4, 28) + td(days=days_delta) self.assertIn(official_memorial_day, il_holidays) self.assertIn(holiday_name, il_holidays[official_memorial_day]) diff --git a/test/countries/test_italy.py b/tests/countries/test_italy.py similarity index 100% rename from test/countries/test_italy.py rename to tests/countries/test_italy.py diff --git a/tests/countries/test_jamaica.py b/tests/countries/test_jamaica.py new file mode 100644 index 000000000..949bf4f52 --- /dev/null +++ b/tests/countries/test_jamaica.py @@ -0,0 +1,156 @@ +# 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.jamaica import Jamaica, JM, JAM +from tests.common import TestCase + + +class TestJamaica(TestCase): + def setUp(self): + self.holidays = Jamaica() + self.holidays_no_observed = Jamaica(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Jamaica, JM, JAM) + + def test_new_years_day(self): + self.assertHoliday(f"{year}-01-01" for year in range(1950, 2050)) + dt = ( + "1995-01-02", + "2006-01-02", + "2012-01-02", + "2017-01-02", + "2023-01-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_labour_day(self): + self.assertHoliday(f"{year}-05-23" for year in range(1950, 2050)) + dt = ( + "1998-05-25", + "1999-05-24", + "2004-05-24", + "2009-05-25", + "2010-05-24", + "2015-05-25", + "2020-05-25", + "2021-05-24", + "2026-05-25", + "2027-05-24", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_emancipation_day(self): + self.assertHoliday(f"{year}-08-01" for year in range(1998, 2050)) + dt = ( + "1999-08-02", + "2004-08-02", + "2010-08-02", + "2021-08-02", + "2027-08-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + self.assertNoHolidayName("Emancipation Day", Jamaica(years=1997)) + + def test_independence_day(self): + self.assertHoliday(f"{year}-08-06" for year in range(1950, 2050)) + dt = ( + "2000-08-07", + "2006-08-07", + "2017-08-07", + "2023-08-07", + "2028-08-07", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_national_heroes_day(self): + self.assertHoliday( + "2015-10-19", + "2016-10-17", + "2017-10-16", + "2018-10-15", + "2019-10-21", + "2020-10-19", + "2021-10-18", + "2022-10-17", + "2023-10-16", + "2024-10-21", + ) + + def test_christmas_day(self): + self.assertHoliday(f"{year}-12-25" for year in range(1950, 2050)) + dt = ( + "2005-12-27", + "2011-12-27", + "2016-12-27", + "2022-12-27", + "2033-12-27", + ) + self.assertHolidaysName("Christmas Day (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_boxing_day(self): + self.assertHoliday(f"{year}-12-26" for year in range(1950, 2050)) + dt = ( + "2004-12-27", + "2010-12-27", + "2021-12-27", + "2027-12-27", + "2032-12-27", + ) + self.assertHolidaysName("Boxing Day (Observed)", dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_ash_wednesday(self): + self.assertHoliday( + "2015-02-18", + "2016-02-10", + "2017-03-01", + "2018-02-14", + "2019-03-06", + "2020-02-26", + "2021-02-17", + "2022-03-02", + "2023-02-22", + "2024-02-14", + ) + + def test_good_friday(self): + self.assertHoliday( + "2015-04-03", + "2016-03-25", + "2017-04-14", + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + "2023-04-07", + "2024-03-29", + ) + + def test_easter_monday(self): + self.assertHoliday( + "2015-04-06", + "2016-03-28", + "2017-04-17", + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + "2023-04-10", + "2024-04-01", + ) diff --git a/test/countries/test_japan.py b/tests/countries/test_japan.py similarity index 93% rename from test/countries/test_japan.py rename to tests/countries/test_japan.py index 6d2bff6e3..329fa7932 100644 --- a/test/countries/test_japan.py +++ b/tests/countries/test_japan.py @@ -9,21 +9,25 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -import unittest from datetime import date -import holidays +from holidays.countries.japan import Japan, JP, JPN +from tests.common import TestCase -class TestJapan(unittest.TestCase): - def setUp(self): - self.holidays = holidays.Japan() +class TestJapan(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Japan) + + def test_country_aliases(self): + self.assertCountryAliases(Japan, JP, JPN) def test_not_implemented(self): with self.assertRaises(NotImplementedError): - holidays.Japan(years=[1945]) + Japan(years=[1945]) with self.assertRaises(NotImplementedError): - holidays.Japan(years=[2100]) + Japan(years=[2100]) def test_new_years_day(self): for year in range(1949, 2050): @@ -574,7 +578,7 @@ def test_reiwa_emperor_holidays(self): self.assertIn(date(2019, 10, 22), self.holidays) def test_observed_holidays(self): - no_observed = holidays.Japan(observed=False) + no_observed = Japan(observed=False) hol_list = ( # 振替休日 (1973, 4, 30), @@ -719,3 +723,32 @@ def test_observed_holidays(self): for dt in hol_list: self.assertIn(date(*dt), self.holidays) self.assertNotIn(date(*dt), no_observed) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + jp = Japan(language=language) + self.assertEqual(jp["2022-01-01"], "元日") + self.assertEqual(jp["2022-11-23"], "勤労感謝の日") + + run_tests((Japan.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Japan.default_language,)) + + # def test_l10n_en_us(self): + # en_us = "en_US" + + # pl = Poland(language=en_us) + # self.assertEqual( + # pl["2018-11-12"], + # "National Independence Day - 100th anniversary", + # ) + # self.assertEqual(pl["2022-01-01"], "New Year's Day") + # self.assertEqual(pl["2022-12-25"], "Christmas (Day 1)") + + # self.set_language(en_us) + # for language in (None, en_us, "invalid"): + # pl = Poland(language=language) + # self.assertEqual(pl["2022-01-01"], "New Year's Day") + # self.assertEqual(pl["2022-12-25"], "Christmas (Day 1)") diff --git a/test/countries/test_kazakhstan.py b/tests/countries/test_kazakhstan.py similarity index 85% rename from test/countries/test_kazakhstan.py rename to tests/countries/test_kazakhstan.py index 9fe3feecd..d88f36913 100644 --- a/test/countries/test_kazakhstan.py +++ b/tests/countries/test_kazakhstan.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.kazakhstan import Kazakhstan, KZ, KAZ -from test.common import TestCase +from tests.common import TestCase class TestKazakhstan(TestCase): @@ -20,37 +20,26 @@ def setUp(self): def test_country_aliases(self): self.assertCountryAliases(Kazakhstan, KZ, KAZ) - def test2020(self): - self.assertHolidayDates( - "2020-01-01", - "2020-01-02", - "2020-01-07", - "2020-03-08", - "2020-03-09", - "2020-03-21", - "2020-03-22", - "2020-03-23", - "2020-03-24", - "2020-03-25", - "2020-05-01", - "2020-05-07", - "2020-05-09", - "2020-05-11", - "2020-07-06", - "2020-07-31", - "2020-08-30", - "2020-08-31", - "2020-12-01", - "2020-12-16", - "2020-12-17", - ) + def test_no_holidays(self): + self.assertNoHolidays(Kazakhstan(years=1990)) + + def test_new_year(self): + self.assertHoliday(f"{year}-01-01" for year in range(1991, 2100)) + self.assertHoliday(f"{year}-01-02" for year in range(1991, 2100)) + + def test_christmas(self): + self.assertHoliday(f"{year}-01-07" for year in range(2006, 2100)) + self.assertNoHoliday(f"{year}-01-07" for year in range(1991, 2006)) + + def test_womens_day(self): + self.assertHoliday(f"{year}-03-08" for year in range(1991, 2100)) def test_nauryz(self): for year in range(2010, 2100): self.assertHoliday( f"{year}-03-21", f"{year}-03-22", f"{year}-03-23" ) - for year in range(1990, 2002): + for year in range(1991, 2002): self.assertNoHoliday( f"{year}-03-21", f"{year}-03-22", f"{year}-03-23" ) @@ -61,41 +50,44 @@ def test_nauryz(self): f"{year}-03-23", ) + def test_solidarity_day(self): + self.assertHoliday(f"{year}-05-01" for year in range(1991, 2100)) + def test_defenders_day(self): self.assertHoliday(f"{year}-05-07" for year in range(2013, 2100)) - self.assertNoHoliday(f"{year}-05-07" for year in range(1990, 2013)) + self.assertNoHoliday(f"{year}-05-07" for year in range(1991, 2013)) - def test_capital_city_day(self): + def test_victory_day(self): + self.assertHoliday(f"{year}-05-09" for year in range(1991, 2100)) + + def test_capital_day(self): self.assertHoliday(f"{year}-07-06" for year in range(2009, 2100)) - self.assertNoHoliday(f"{year}-07-06" for year in range(1990, 2009)) + self.assertNoHoliday(f"{year}-07-06" for year in range(1991, 2009)) def test_constitution_day(self): self.assertHoliday(f"{year}-08-30" for year in range(1996, 2100)) - self.assertNoHoliday(f"{year}-08-30" for year in range(1990, 1996)) + self.assertNoHoliday(f"{year}-08-30" for year in range(1991, 1996)) def test_republic_day(self): self.assertHoliday(f"{year}-10-25" for year in range(1994, 2009)) self.assertHoliday(f"{year}-10-25" for year in range(2022, 2100)) + self.assertNoHoliday(f"{year}-10-25" for year in range(1991, 1994)) self.assertNoHoliday(f"{year}-10-25" for year in range(2009, 2022)) def test_first_president_day(self): self.assertHoliday(f"{year}-12-01" for year in range(2012, 2022)) - self.assertNoHoliday(f"{year}-12-01" for year in range(1990, 2012)) + self.assertNoHoliday(f"{year}-12-01" for year in range(1991, 2012)) self.assertNoHoliday(f"{year}-12-01" for year in range(2022, 2100)) def test_independence_day(self): - self.assertHoliday(f"{year}-12-16" for year in range(1990, 2100)) + self.assertHoliday(f"{year}-12-16" for year in range(1991, 2100)) self.assertHoliday(f"{year}-12-17" for year in range(2002, 2022)) - self.assertNoHoliday(f"{year}-12-17" for year in range(1990, 2002)) + self.assertNoHoliday(f"{year}-12-17" for year in range(1991, 2002)) for year in range(2022, 2100): self.assertNoHoliday( Kazakhstan(observed=False, years=year), f"{year}-12-17" ) - def test_christmas(self): - self.assertHoliday(f"{year}-01-07" for year in range(2006, 2100)) - self.assertNoHoliday(f"{year}-01-07" for year in range(1990, 2006)) - def test_kurban_ait(self): self.assertHoliday( "2006-01-10", @@ -162,5 +154,30 @@ def test_observed(self): "2022-05-02", "2022-05-10", ) - self.assertHoliday(Kazakhstan(observed=True), observed_holidays) + self.assertHoliday(observed_holidays) self.assertNoHoliday(Kazakhstan(observed=False), observed_holidays) + + def test2020(self): + self.assertHolidayDates( + "2020-01-01", + "2020-01-02", + "2020-01-07", + "2020-03-08", + "2020-03-09", + "2020-03-21", + "2020-03-22", + "2020-03-23", + "2020-03-24", + "2020-03-25", + "2020-05-01", + "2020-05-07", + "2020-05-09", + "2020-05-11", + "2020-07-06", + "2020-07-31", + "2020-08-30", + "2020-08-31", + "2020-12-01", + "2020-12-16", + "2020-12-17", + ) diff --git a/tests/countries/test_kenya.py b/tests/countries/test_kenya.py new file mode 100644 index 000000000..bf2eed8e4 --- /dev/null +++ b/tests/countries/test_kenya.py @@ -0,0 +1,165 @@ +# 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.kenya import Kenya, KE, KEN +from tests.common import TestCase + + +class TestKenya(TestCase): + def setUp(self): + self.holidays = Kenya() + + def test_country_aliases(self): + self.assertCountryAliases(Kenya, KE, KEN) + + def test_no_holidays(self): + self.assertNoHolidays(Kenya(years=1962)) + + def test_special_holidays(self): + self.assertHoliday( + "2020-02-11", + "2022-04-29", + "2022-08-09", + "2022-09-10", + "2022-09-11", + "2022-09-12", + "2022-09-13", + ) + + def test_holidays(self): + for year in range(1963, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-05-01", + f"{year}-10-20", + f"{year}-12-12", + f"{year}-12-25", + f"{year}-12-26", + ) + + def test_madaraka_day(self): + self.assertNoHoliday(f"{year}-06-01" for year in range(1963, 2010)) + self.assertNoHolidayName( + "Madaraka Day", + Kenya(years=range(1963, 2010)), + ) + self.assertHoliday(f"{year}-06-01" for year in range(2010, 2050)) + + def test_utamaduni_day(self): + name1 = "Moi Day" + name2 = "Utamaduni Day" + self.assertNoHoliday(f"{year}-10-10" for year in range(1963, 2002)) + self.assertNoHoliday(f"{year}-10-10" for year in range(2010, 2018)) + self.assertNoHolidayName(name1, Kenya(years=range(1963, 2002))) + self.assertNoHolidayName(name1, Kenya(years=range(2010, 2018))) + self.assertNoHolidayName(name2, Kenya(years=range(1963, 2002))) + self.assertNoHolidayName(name2, Kenya(years=range(2010, 2021))) + self.assertHoliday(f"{year}-10-10" for year in range(2002, 2010)) + self.assertHoliday(f"{year}-10-10" for year in range(2018, 2050)) + + def test_mashujaa_day(self): + self.assertNoHolidayName( + "Mashujaa Day", + Kenya(years=range(1963, 2010)), + ) + self.assertNoHolidayName( + "Kenyatta Day", + Kenya(years=range(2010, 2050)), + ) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + ) + + def test_observed(self): + dt = ( + # New Year's Day + "2012-01-02", + "2017-01-02", + "2023-01-02", + # Labour Day + "2011-05-02", + "2016-05-02", + "2022-05-02", + # Madaraka Day + "2014-06-02", + "2025-06-02", + # Utamaduni Day / Moi Day + "2004-10-11", + "2021-10-11", + # Mashujaa Day / Kenyatta Day + "1996-10-21", + "2002-10-21", + "2013-10-21", + "2019-10-21", + "2024-10-21", + # Jamhuri Day + "2010-12-13", + "2021-12-13", + # Christmas Day + "2011-12-27", + "2016-12-27", + "2022-12-27", + # Boxing Day + "2010-12-27", + "2021-12-27", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Kenya(observed=False), dt) + + def test_2019(self): + self.assertHolidayDates( + "2019-01-01", + "2019-04-19", + "2019-04-22", + "2019-05-01", + "2019-06-01", + "2019-10-10", + "2019-10-20", + "2019-10-21", + "2019-12-12", + "2019-12-25", + "2019-12-26", + ) + + def test_2022(self): + self.assertHolidayDates( + "2022-01-01", + "2022-04-15", + "2022-04-18", + "2022-04-29", + "2022-05-01", + "2022-05-02", + "2022-06-01", + "2022-08-09", + "2022-09-10", + "2022-09-11", + "2022-09-12", + "2022-09-13", + "2022-10-10", + "2022-10-20", + "2022-12-12", + "2022-12-25", + "2022-12-26", + "2022-12-27", + ) diff --git a/test/countries/test_kyrgyzstan.py b/tests/countries/test_kyrgyzstan.py similarity index 98% rename from test/countries/test_kyrgyzstan.py rename to tests/countries/test_kyrgyzstan.py index f4714798a..a0c92ef2e 100644 --- a/test/countries/test_kyrgyzstan.py +++ b/tests/countries/test_kyrgyzstan.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.kyrgyzstan import KG, KGZ, Kyrgyzstan -from test.common import TestCase +from tests.common import TestCase class TestKyrgyzstan(TestCase): diff --git a/test/countries/test_latvia.py b/tests/countries/test_latvia.py similarity index 100% rename from test/countries/test_latvia.py rename to tests/countries/test_latvia.py diff --git a/test/countries/test_lesotho.py b/tests/countries/test_lesotho.py similarity index 100% rename from test/countries/test_lesotho.py rename to tests/countries/test_lesotho.py diff --git a/test/countries/test_liechtenstein.py b/tests/countries/test_liechtenstein.py similarity index 100% rename from test/countries/test_liechtenstein.py rename to tests/countries/test_liechtenstein.py diff --git a/test/countries/test_lithuania.py b/tests/countries/test_lithuania.py similarity index 100% rename from test/countries/test_lithuania.py rename to tests/countries/test_lithuania.py diff --git a/test/countries/test_luxembourg.py b/tests/countries/test_luxembourg.py similarity index 100% rename from test/countries/test_luxembourg.py rename to tests/countries/test_luxembourg.py diff --git a/test/countries/test_madagascar.py b/tests/countries/test_madagascar.py similarity index 100% rename from test/countries/test_madagascar.py rename to tests/countries/test_madagascar.py diff --git a/tests/countries/test_malawi.py b/tests/countries/test_malawi.py new file mode 100644 index 000000000..77c5217cd --- /dev/null +++ b/tests/countries/test_malawi.py @@ -0,0 +1,112 @@ +# 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.malawi import Malawi, MW, MWI +from tests.common import TestCase + + +class TestMalawi(TestCase): + def setUp(self): + self.holidays = Malawi() + + def test_country_aliases(self): + self.assertCountryAliases(Malawi, MW, MWI) + + def test_no_holidays(self): + self.assertNoHolidays(Malawi(years=1999)) + + def test_holidays(self): + for year in range(2000, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-01-15", + f"{year}-03-03", + f"{year}-05-01", + f"{year}-05-14", + f"{year}-07-06", + f"{year}-10-15", + f"{year}-12-25", + f"{year}-12-26", + ) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + ) + + def test_observed(self): + dt = ( + # New Year's Day + "2011-01-03", + "2012-01-02", + "2017-01-02", + "2022-01-03", + "2023-01-02", + # John Chilembwe Day + "2011-01-17", + "2012-01-16", + "2017-01-16", + "2022-01-17", + "2023-01-16", + # Martyrs Day + "2012-03-05", + "2013-03-04", + "2018-03-05", + "2019-03-04", + "2024-03-04", + # Labour Day + "2010-05-03", + "2011-05-02", + "2016-05-02", + "2021-05-03", + "2022-05-02", + # Kamuzu Day + "2011-05-16", + "2016-05-16", + "2017-05-15", + "2022-05-16", + "2023-05-15", + # Independence Day + "2013-07-08", + "2014-07-07", + "2019-07-08", + "2024-07-08", + # Mother's Day + "2011-10-17", + "2016-10-17", + "2017-10-16", + "2022-10-17", + "2023-10-16", + # Christmas Day + "2010-12-27", + "2011-12-27", + "2016-12-27", + "2021-12-27", + "2022-12-27", + # Boxing Day + "2010-12-28", + "2015-12-28", + "2020-12-28", + "2021-12-28", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Malawi(observed=False), dt) diff --git a/test/countries/test_malaysia.py b/tests/countries/test_malaysia.py similarity index 100% rename from test/countries/test_malaysia.py rename to tests/countries/test_malaysia.py diff --git a/test/countries/test_malta.py b/tests/countries/test_malta.py similarity index 100% rename from test/countries/test_malta.py rename to tests/countries/test_malta.py diff --git a/tests/countries/test_marshall_islands.py b/tests/countries/test_marshall_islands.py new file mode 100644 index 000000000..bcf27df81 --- /dev/null +++ b/tests/countries/test_marshall_islands.py @@ -0,0 +1,65 @@ +# 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) + +import unittest +import warnings +from datetime import date + +import holidays +from holidays.constants import JAN, MAR, APR, MAY, JUL, SEP, NOV, DEC + + +class TestMH(unittest.TestCase): + def setUp(self): + self.holidays = holidays.MH() + warnings.simplefilter("ignore") + + def test_2022(self): + # https://www.register-iri.com/info-center/the-marshall-islands/ + # rmi-national-holidays/ + year = 2022 + self.assertIn(date(year, JAN, 1), self.holidays) + self.assertIn(date(year, JAN, 3), self.holidays) + self.assertIn(date(year, APR, 15), self.holidays) + self.assertIn(date(year, MAY, 1), self.holidays) + self.assertIn(date(year, JUL, 1), self.holidays) + self.assertIn(date(year, SEP, 2), self.holidays) + self.assertIn(date(year, SEP, 30), self.holidays) + self.assertIn(date(year, NOV, 17), self.holidays) + self.assertIn(date(year, DEC, 2), self.holidays) + self.assertIn(date(year, DEC, 25), self.holidays) + self.assertIn(date(year, DEC, 26), self.holidays) + # 2023: total holidays (10 + 2 falling on a Sunday) + self.assertEqual(10 + 2, len(holidays.MH(years=[year]))) + + def test_2023(self): + year = 2023 + self.assertIn(date(year, JAN, 1), self.holidays) + self.assertIn(date(year, JAN, 2), self.holidays) + self.assertIn(date(year, MAR, 1), self.holidays) + self.assertIn(date(year, APR, 7), self.holidays) + self.assertIn(date(year, MAY, 1), self.holidays) + self.assertIn(date(year, JUL, 7), self.holidays) + self.assertIn(date(year, SEP, 1), self.holidays) + self.assertIn(date(year, SEP, 29), self.holidays) + self.assertIn(date(year, NOV, 17), self.holidays) + self.assertIn(date(year, DEC, 1), self.holidays) + self.assertIn(date(year, DEC, 25), self.holidays) + # 2023: total holidays (10 + 1 falling on a Sunday) + self.assertEqual(10 + 1, len(holidays.MH(years=[year]))) + + def test_not_observed(self): + self.assertNotIn(date(2023, JAN, 2), holidays.MH(observed=False)) + + def test_aliases(self): + """For coverage purposes""" + for h in [holidays.MH(), holidays.MHL(), holidays.MarshallIslands()]: + self.assertIsInstance(h, holidays.HolidaysMH) diff --git a/test/countries/test_mexico.py b/tests/countries/test_mexico.py similarity index 86% rename from test/countries/test_mexico.py rename to tests/countries/test_mexico.py index 7ce118587..d7587a49c 100644 --- a/test/countries/test_mexico.py +++ b/tests/countries/test_mexico.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -31,8 +30,8 @@ def test_new_years(self): for year in range(1900, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_constitution_day(self): for dt in [ @@ -48,8 +47,8 @@ def test_constitution_day(self): date(2022, 2, 5), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.holidays.observed = True for dt in [ date(2005, 2, 5), @@ -89,8 +88,8 @@ def test_benito_juarez(self): date(2024, 3, 21), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.holidays.observed = True for dt in [ date(2005, 3, 21), @@ -130,8 +129,8 @@ def test_labor_day(self): for year in range(1923, 2100): dt = date(year, 5, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_independence_day(self): self.assertNotIn(date(2006, 9, 15), self.holidays) @@ -143,8 +142,8 @@ def test_independence_day(self): for year in range(1900, 2100): dt = date(year, 9, 16) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_revolution_day(self): for dt in [ @@ -162,8 +161,8 @@ def test_revolution_day(self): date(2023, 11, 20), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.holidays.observed = True for dt in [ date(2005, 11, 20), @@ -190,8 +189,8 @@ def test_change_of_government(self): dt = date(year, 12, 1) if (year >= 1970) and ((2096 - year) % 6) == 0: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) else: self.assertNotIn(dt, self.holidays) @@ -199,8 +198,8 @@ def test_christmas(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2010, 12, 24), self.holidays) self.assertNotIn(date(2016, 12, 26), self.holidays) self.holidays.observed = True diff --git a/test/countries/test_moldova.py b/tests/countries/test_moldova.py similarity index 100% rename from test/countries/test_moldova.py rename to tests/countries/test_moldova.py diff --git a/test/countries/test_monaco.py b/tests/countries/test_monaco.py similarity index 98% rename from test/countries/test_monaco.py rename to tests/countries/test_monaco.py index f3b5d8aff..f4c4df306 100644 --- a/test/countries/test_monaco.py +++ b/tests/countries/test_monaco.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.monaco import MC, MCO, Monaco -from test.common import TestCase +from tests.common import TestCase class TestMonaco(TestCase): diff --git a/test/countries/test_montenegro.py b/tests/countries/test_montenegro.py similarity index 94% rename from test/countries/test_montenegro.py rename to tests/countries/test_montenegro.py index a06f77e2e..b33335fc9 100644 --- a/test/countries/test_montenegro.py +++ b/tests/countries/test_montenegro.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.montenegro import ME, MNE, Montenegro -from test.common import TestCase +from tests.common import TestCase class TestMontenegro(TestCase): @@ -28,8 +28,8 @@ def test_2021(self): ("2021-01-07", "Orthodox Christmas"), ("2021-04-30", "Orthodox Good Friday"), ("2021-05-01", "Labour Day"), - ("2021-05-02", "Labour Day, Orthodox Easter Sunday"), - ("2021-05-03", "Labour Day (Observed), Orthodox Easter Monday"), + ("2021-05-02", "Labour Day; Orthodox Easter Sunday"), + ("2021-05-03", "Labour Day (Observed); Orthodox Easter Monday"), ("2021-05-21", "Independence Day"), ("2021-05-22", "Independence Day"), ("2021-07-13", "Statehood Day"), diff --git a/test/countries/test_morocco.py b/tests/countries/test_morocco.py similarity index 94% rename from test/countries/test_morocco.py rename to tests/countries/test_morocco.py index 67ec2ff48..6bff62a0c 100644 --- a/test/countries/test_morocco.py +++ b/tests/countries/test_morocco.py @@ -75,14 +75,13 @@ def test_independence_day(self): self.holidays = holidays.Morocco(years=[1957]) self.assertEqual( self.holidays[date(1957, 11, 18)], - "Fête de l'indépendance, Fête du Trône", + "Fête de l'indépendance; Fête du Trône", ) self.holidays = holidays.Morocco(years=[1956]) self.assertEqual(self.holidays[date(1956, 11, 18)], "Fête du Trône") def test_hijri_based(self): if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.Morocco(years=[2019, 1999]) # eid_alfitr self.assertIn(date(2019, 6, 4), self.holidays) self.assertIn(date(2019, 6, 5), self.holidays) @@ -90,6 +89,8 @@ def test_hijri_based(self): self.assertIn(date(2019, 8, 11), self.holidays) self.assertIn(date(2019, 8, 12), self.holidays) # islamic_new_year + self.assertIn(date(2008, 1, 10), self.holidays) + self.assertIn(date(2008, 12, 29), self.holidays) self.assertIn(date(2019, 8, 31), self.holidays) self.assertIn(date(2019, 11, 9), self.holidays) diff --git a/tests/countries/test_mozambique.py b/tests/countries/test_mozambique.py new file mode 100644 index 000000000..6e0402c5b --- /dev/null +++ b/tests/countries/test_mozambique.py @@ -0,0 +1,87 @@ +# 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.mozambique import Mozambique, MZ, MOZ +from tests.common import TestCase + + +class TestMozambique(TestCase): + def setUp(self): + self.holidays = Mozambique() + + def test_country_aliases(self): + self.assertCountryAliases(Mozambique, MZ, MOZ) + + def test_no_holidays(self): + self.assertNoHolidays(Mozambique(years=1974)) + + def test_holidays(self): + for year in range(1975, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-02-03", + f"{year}-04-07", + f"{year}-05-01", + f"{year}-06-25", + f"{year}-09-07", + f"{year}-09-25", + f"{year}-12-25", + ) + + self.assertNoHoliday(f"{year}-10-04" for year in range(1975, 1993)) + self.assertNoHolidayName( + "Dia da Paz e Reconciliação", + Mozambique(years=range(1975, 1993)), + ) + self.assertHoliday(f"{year}-10-04" for year in range(1993, 2050)) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Carnival + "2018-02-13", + "2019-03-05", + "2020-02-25", + "2021-02-16", + "2022-03-01", + ) + + def test_observed(self): + dt = ( + "2011-05-02", + "2011-09-26", + "2011-12-26", + "2012-01-02", + "2013-02-04", + "2013-04-08", + "2014-09-08", + "2015-10-05", + "2016-05-02", + "2016-09-26", + "2016-12-26", + "2017-01-02", + "2017-06-26", + "2019-02-04", + "2019-04-08", + "2020-10-05", + "2022-05-02", + "2022-09-26", + "2022-12-26", + "2023-01-02", + "2023-06-26", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Mozambique(observed=False), dt) diff --git a/tests/countries/test_namibia.py b/tests/countries/test_namibia.py new file mode 100644 index 000000000..0b3dac91f --- /dev/null +++ b/tests/countries/test_namibia.py @@ -0,0 +1,96 @@ +# 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.namibia import Namibia, NA, NAM +from tests.common import TestCase + + +class TestNamibia(TestCase): + def setUp(self): + self.holidays = Namibia() + + def test_country_aliases(self): + self.assertCountryAliases(Namibia, NA, NAM) + + def test_no_holidays(self): + self.assertNoHolidays(Namibia(years=1989)) + + def test_special_holidays(self): + self.assertHoliday( + "1999-12-31", + "2000-01-03", + ) + + def test_holidays(self): + for year in range(1990, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-03-21", + f"{year}-05-01", + f"{year}-05-04", + f"{year}-05-25", + f"{year}-08-26", + f"{year}-09-10", + f"{year}-12-25", + f"{year}-12-26", + ) + self.assertNoHolidayName( + "Day of the Namibian Women and International Human Rights Day", + Namibia(years=range(1990, 2005)), + ) + self.assertHolidaysName( + "International Human Rights Day", + (f"{year}-09-10" for year in range(1990, 2005)), + ) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + # Ascension Day + "2018-05-10", + "2019-05-30", + "2020-05-21", + "2021-05-13", + "2022-05-26", + ) + + def test_observed(self): + dt = ( + "2010-03-22", + "2010-12-27", + "2011-05-02", + "2012-01-02", + "2012-08-27", + "2014-05-05", + "2014-05-26", + "2016-05-02", + "2017-01-02", + "2017-09-11", + "2018-08-27", + "2021-03-22", + "2021-12-27", + "2022-05-02", + "2023-01-02", + "2023-09-11", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Namibia(observed=False), dt) diff --git a/test/countries/test_netherlands.py b/tests/countries/test_netherlands.py similarity index 100% rename from test/countries/test_netherlands.py rename to tests/countries/test_netherlands.py diff --git a/test/countries/test_new_zealand.py b/tests/countries/test_new_zealand.py similarity index 97% rename from test/countries/test_new_zealand.py rename to tests/countries/test_new_zealand.py index 821eb614d..9072e6287 100644 --- a/test/countries/test_new_zealand.py +++ b/tests/countries/test_new_zealand.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -150,8 +149,8 @@ def test_good_friday(self): date(2020, 4, 10), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_easter_monday(self): for dt in [ @@ -165,8 +164,8 @@ def test_easter_monday(self): date(2020, 4, 13), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_anzac_day(self): for year in range(1900, 1921): @@ -284,8 +283,8 @@ def test_matariki(self): ]: self.assertIn(dt, self.holidays) self.assertEqual(self.holidays[dt], "Matariki") - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_labour_day(self): for year, day in enumerate( @@ -323,7 +322,7 @@ def test_christmas_day(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) self.assertNotIn(date(2010, 12, 24), self.holidays) self.assertNotEqual( self.holidays[date(2011, 12, 26)], "Christmas Day (Observed)" @@ -367,7 +366,7 @@ def test_boxing_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2009, 12, 28), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.holidays.observed = True diff --git a/test/countries/test_nicaragua.py b/tests/countries/test_nicaragua.py similarity index 100% rename from test/countries/test_nicaragua.py rename to tests/countries/test_nicaragua.py diff --git a/test/countries/test_nigeria.py b/tests/countries/test_nigeria.py similarity index 100% rename from test/countries/test_nigeria.py rename to tests/countries/test_nigeria.py diff --git a/test/countries/test_north_macedonia.py b/tests/countries/test_north_macedonia.py similarity index 100% rename from test/countries/test_north_macedonia.py rename to tests/countries/test_north_macedonia.py diff --git a/tests/countries/test_northern_mariana_islands.py b/tests/countries/test_northern_mariana_islands.py new file mode 100644 index 000000000..b66bc6038 --- /dev/null +++ b/tests/countries/test_northern_mariana_islands.py @@ -0,0 +1,41 @@ +# 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) + +import unittest +from datetime import date + +import holidays +from holidays.constants import MAR + + +class TestMP(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysMP() + + def test_MP_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + self.assertIn( + "Commonwealth Covenant Day", + self.holidays.get_list(date(2022, MAR, 24)), + ) + + def test_aliases(self): + """For coverage purposes""" + for h in [ + holidays.MP(), + holidays.MNP(), + holidays.NorthernMarianaIslands(), + ]: + self.assertIsInstance(h, holidays.HolidaysMP) diff --git a/test/countries/test_norway.py b/tests/countries/test_norway.py similarity index 98% rename from test/countries/test_norway.py rename to tests/countries/test_norway.py index 313d85ec6..bc5db46b8 100644 --- a/test/countries/test_norway.py +++ b/tests/countries/test_norway.py @@ -13,7 +13,7 @@ from holidays.constants import MON, SUN from holidays.countries.norway import NO, NOR, Norway -from test.common import SundayHolidays +from tests.common import SundayHolidays class TestNorway(SundayHolidays): diff --git a/test/countries/test_pakistan.py b/tests/countries/test_pakistan.py similarity index 95% rename from test/countries/test_pakistan.py rename to tests/countries/test_pakistan.py index 6df6ddb60..dcb598cdc 100644 --- a/test/countries/test_pakistan.py +++ b/tests/countries/test_pakistan.py @@ -10,11 +10,10 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.countries.pakistan import Pakistan, PK, PAK -from test.common import TestCase +from tests.common import TestCase class TestPakistan(TestCase): @@ -86,8 +85,8 @@ def test_eid_ul_fitr(self): date(2023, 4, 21), ): self.assertHoliday(dt) - self.assertHoliday(dt + rd(days=+1)) - self.assertHoliday(dt + rd(days=+2)) + self.assertHoliday(dt + td(days=+1)) + self.assertHoliday(dt + td(days=+2)) self.assertIn(name, self.holidays.get(dt)) def test_eid_ul_adha(self): @@ -109,8 +108,8 @@ def test_eid_ul_adha(self): date(2023, 6, 28), ): self.assertHoliday(dt) - self.assertHoliday(dt + rd(days=+1)) - self.assertHoliday(dt + rd(days=+2)) + self.assertHoliday(dt + td(days=+1)) + self.assertHoliday(dt + td(days=+2)) self.assertIn(name, self.holidays.get(dt)) def test_eid_milad_un_nabi(self): @@ -153,5 +152,5 @@ def test_ashura(self): date(2023, 7, 28), ): self.assertHoliday(dt) - self.assertHoliday(dt + rd(days=+1)) + self.assertHoliday(dt + td(days=+1)) self.assertIn(name, self.holidays.get(dt)) diff --git a/tests/countries/test_panama.py b/tests/countries/test_panama.py new file mode 100644 index 000000000..e5fc3ff4a --- /dev/null +++ b/tests/countries/test_panama.py @@ -0,0 +1,117 @@ +# 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.panama import PA, PAN, Panama +from tests.common import TestCase + + +class TestPanama(TestCase): + def setUp(self): + self.holidays = Panama() + + def test_country_aliases(self): + self.assertCountryAliases(Panama, PA, PAN) + + def test_new_year_day(self): + self.assertHoliday(f"{year}-01-01" for year in range(1950, 2051)) + + def test_martyrs_day(self): + self.assertHoliday(f"{year}-01-09" for year in range(1950, 2051)) + + def test_labour_day(self): + self.assertHoliday(f"{year}-05-01" for year in range(1950, 2051)) + + def test_separation_day(self): + self.assertHoliday(f"{year}-11-03" for year in range(1950, 2051)) + + def test_national_symbols_day(self): + self.assertHoliday(f"{year}-11-04" for year in range(1950, 2051)) + + def test_colon_day(self): + self.assertHoliday(f"{year}-11-05" for year in range(1950, 2051)) + + def test_los_santos_uprising_day(self): + self.assertHoliday(f"{year}-11-10" for year in range(1950, 2051)) + + def test_independence_day(self): + self.assertHoliday(f"{year}-11-28" for year in range(1950, 2051)) + + def test_mothers_day(self): + self.assertHoliday(f"{year}-12-08" for year in range(1950, 2051)) + + def test_national_mourning_day(self): + self.assertHoliday(f"{year}-12-20" for year in range(2022, 2051)) + self.assertNoHoliday(f"{year}-12-20" for year in range(1950, 2022)) + self.assertNoHolidayName( + "National Mourning Day", + Panama(years=range(1950, 2022)), + ) + + def test_christmas_day(self): + self.assertHoliday(f"{year}-12-25" for year in range(1950, 2051)) + + def test_observed(self): + observed_holidays = ( + "2011-01-10", + "2011-05-02", + "2011-12-26", + "2012-01-02", + "2013-12-09", + "2016-05-02", + "2016-12-26", + "2017-01-02", + "2019-12-09", + "2021-11-29", + "2022-01-10", + "2022-05-02", + "2022-12-26", + "2023-01-02", + ) + self.assertHoliday(observed_holidays) + self.assertNoHoliday(Panama(observed=False), observed_holidays) + + def test_2022(self): + self.assertHolidays( + ("2022-01-01", "New Year's Day"), + ("2022-01-09", "Martyrs' Day"), + ("2022-01-10", "Martyrs' Day (Observed)"), + ("2022-03-01", "Carnival"), + ("2022-04-15", "Good Friday"), + ("2022-05-01", "Labour Day"), + ("2022-05-02", "Labour Day (Observed)"), + ("2022-11-03", "Separation Day"), + ("2022-11-04", "National Symbols Day"), + ("2022-11-05", "Colon Day"), + ("2022-11-10", "Los Santos Uprising Day"), + ("2022-11-28", "Independence Day"), + ("2022-12-08", "Mother's Day"), + ("2022-12-20", "National Mourning Day"), + ("2022-12-25", "Christmas Day"), + ("2022-12-26", "Christmas Day (Observed)"), + ) + + def test_2023(self): + self.assertHolidays( + ("2023-01-01", "New Year's Day"), + ("2023-01-02", "New Year's Day (Observed)"), + ("2023-01-09", "Martyrs' Day"), + ("2023-02-21", "Carnival"), + ("2023-04-07", "Good Friday"), + ("2023-05-01", "Labour Day"), + ("2023-11-03", "Separation Day"), + ("2023-11-04", "National Symbols Day"), + ("2023-11-05", "Colon Day"), + ("2023-11-10", "Los Santos Uprising Day"), + ("2023-11-28", "Independence Day"), + ("2023-12-08", "Mother's Day"), + ("2023-12-20", "National Mourning Day"), + ("2023-12-25", "Christmas Day"), + ) diff --git a/test/countries/test_paraguay.py b/tests/countries/test_paraguay.py similarity index 96% rename from test/countries/test_paraguay.py rename to tests/countries/test_paraguay.py index 01f57886e..3062022e0 100644 --- a/test/countries/test_paraguay.py +++ b/tests/countries/test_paraguay.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -154,7 +153,7 @@ def test_easter(self): (2022, 4, 17), ]: easter = date(year, month, day) - easter_thursday = easter + rd(days=-3) - easter_friday = easter + rd(days=-2) + easter_thursday = easter + td(days=-3) + easter_friday = easter + td(days=-2) for holiday in [easter_thursday, easter_friday, easter]: self.assertIn(holiday, self.holidays) diff --git a/test/countries/test_peru.py b/tests/countries/test_peru.py similarity index 100% rename from test/countries/test_peru.py rename to tests/countries/test_peru.py diff --git a/test/countries/test_philippines.py b/tests/countries/test_philippines.py similarity index 98% rename from test/countries/test_philippines.py rename to tests/countries/test_philippines.py index b5e7d5df8..125b2e97b 100644 --- a/test/countries/test_philippines.py +++ b/tests/countries/test_philippines.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.philippines import PH, PHL, Philippines -from test.common import TestCase +from tests.common import TestCase class TestPhilippines(TestCase): diff --git a/tests/countries/test_poland.py b/tests/countries/test_poland.py new file mode 100644 index 000000000..db6e53cac --- /dev/null +++ b/tests/countries/test_poland.py @@ -0,0 +1,283 @@ +# 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.poland import Poland, PL, POL +from tests.common import TestCase + + +class TestPoland(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Poland) + + def test_country_aliases(self): + self.assertCountryAliases(Poland, PL, POL) + + def test_no_holidays(self): + self.assertNoHolidays(Poland(years=1924)) + + def test_2017(self): + # http://www.officeholidays.com/countries/poland/2017.php + self.assertHolidayDates( + "2017-01-01", + "2017-01-06", + "2017-04-16", + "2017-04-17", + "2017-05-01", + "2017-05-03", + "2017-06-04", + "2017-06-15", + "2017-08-15", + "2017-11-01", + "2017-11-11", + "2017-12-25", + "2017-12-26", + ) + + def test_2022(self): + self.assertHolidayDates( + "2022-01-01", + "2022-01-06", + "2022-04-17", + "2022-04-18", + "2022-05-01", + "2022-05-03", + "2022-06-05", + "2022-06-16", + "2022-08-15", + "2022-11-01", + "2022-11-11", + "2022-12-25", + "2022-12-26", + ) + + def test_special_holidays(self): + self.assertHoliday("2018-11-12") + + def test_nowy_rok(self): + self.assertHoliday(f"{year}-01-01" for year in range(1925, 2050)) + + def test_swieto_trzech_kroli(self): + self.assertHoliday(f"{year}-01-06" for year in range(1925, 1960)) + self.assertHoliday(f"{year}-01-06" for year in range(2011, 2050)) + self.assertNoHoliday(f"{year}-01-06" for year in range(1961, 2011)) + self.assertNoHolidayName( + "Święto Trzech Króli", Poland(years=range(1961, 2011)) + ) + + def test_oczyszczenie_nmp(self): + self.assertHoliday(f"{year}-02-02" for year in range(1925, 1951)) + self.assertNoHoliday(f"{year}-02-02" for year in range(1951, 2050)) + self.assertNoHolidayName( + "Oczyszczenie Najświętszej Marii Panny", + Poland(years=range(1951, 2050)), + ) + + def test_easter_related(self): + self.assertHoliday( + # Niedziela Wielkanocna + "2015-04-05", + "2016-03-27", + "2017-04-16", + "2018-04-01", + "2019-04-21", + "2020-04-12", + "2021-04-04", + "2022-04-17", + "2023-04-09", + # Poniedziałek Wielkanocny + "2015-04-06", + "2016-03-28", + "2017-04-17", + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + "2023-04-10", + # Zielone Świątki + "2015-05-24", + "2016-05-15", + "2017-06-04", + "2018-05-20", + "2019-06-09", + "2020-05-31", + "2021-05-23", + "2022-06-05", + "2023-05-28", + # Dzień Bożego Ciała + "2015-06-04", + "2016-05-26", + "2017-06-15", + "2018-05-31", + "2019-06-20", + "2020-06-11", + "2021-06-03", + "2022-06-16", + "2023-06-08", + ) + + def test_swieto_panstwowe(self): + self.assertHoliday(f"{year}-05-01" for year in range(1950, 2050)) + self.assertNoHoliday(f"{year}-05-01" for year in range(1925, 1950)) + self.assertNoHolidayName( + "Święto Państwowe", Poland(years=range(1925, 1950)) + ) + + def test_swieto_narodowe_trzeciego_maja(self): + self.assertHoliday(f"{year}-05-03" for year in range(1925, 1951)) + self.assertHoliday(f"{year}-05-03" for year in range(1990, 2050)) + self.assertNoHoliday(f"{year}-05-03" for year in range(1951, 1990)) + self.assertNoHolidayName( + "Święto Narodowe Trzeciego Maja", Poland(years=range(1951, 1990)) + ) + + def test_narodowe_swieto_zwyciestwa_i_wolnosci(self): + self.assertHoliday(f"{year}-05-09" for year in range(1946, 1951)) + self.assertNoHoliday(f"{year}-05-09" for year in range(1925, 1946)) + self.assertNoHoliday(f"{year}-05-09" for year in range(1951, 2050)) + self.assertNoHolidayName( + "Narodowe Święto Zwycięstwa i Wolności", + Poland(years=range(1925, 1946)), + ) + self.assertNoHolidayName( + "Narodowe Święto Zwycięstwa i Wolności", + Poland(years=range(1951, 2050)), + ) + + def test_wniebowstapienie_panskie(self): + self.assertHoliday( + "1930-05-30", + "1934-05-11", + "1939-05-19", + "1945-05-11", + "1950-05-19", + ) + self.assertNoHolidayName( + "Wniebowstąpienie Pańskie", Poland(years=range(1951, 2050)) + ) + + def test_drugi_dzien_zielonych_swiatek(self): + self.assertHoliday( + "1930-06-09", + "1934-05-21", + "1939-05-29", + "1945-05-21", + "1950-05-29", + ) + self.assertNoHolidayName( + "Drugi dzień Zielonych Świątek", Poland(years=range(1951, 2050)) + ) + + def test_swietych_apostolow_piotra_i_pawla(self): + self.assertHoliday(f"{year}-06-29" for year in range(1925, 1951)) + self.assertNoHoliday(f"{year}-06-29" for year in range(1951, 2050)) + self.assertNoHolidayName( + "Uroczystość Świętych Apostołów Piotra i Pawła", + Poland(years=range(1951, 2050)), + ) + + def test_narodowe_swieto_odrodzenia_polski(self): + self.assertHoliday(f"{year}-07-22" for year in range(1945, 1990)) + self.assertNoHoliday(f"{year}-07-22" for year in range(1925, 1945)) + self.assertNoHoliday(f"{year}-07-22" for year in range(1990, 2050)) + self.assertNoHolidayName( + "Narodowe Święto Odrodzenia Polski", + Poland(years=range(1925, 1945)), + ) + self.assertNoHolidayName( + "Narodowe Święto Odrodzenia Polski", + Poland(years=range(1990, 2050)), + ) + + def test_wniebowziecie_nmp(self): + self.assertHoliday(f"{year}-08-15" for year in range(1925, 1961)) + self.assertHoliday(f"{year}-08-15" for year in range(1989, 2050)) + self.assertNoHoliday(f"{year}-08-15" for year in range(1961, 1989)) + self.assertNoHolidayName( + "Wniebowzięcie Najświętszej Marii Panny", + Poland(years=range(1961, 1989)), + ) + + def test_wszystkich_swietych(self): + self.assertHoliday(f"{year}-11-01" for year in range(1925, 2050)) + + def test_narodowe_swieto_niepodleglosci(self): + self.assertHoliday(f"{year}-11-11" for year in range(1937, 1945)) + self.assertHoliday(f"{year}-11-11" for year in range(1989, 2050)) + self.assertNoHoliday(f"{year}-11-11" for year in range(1925, 1937)) + self.assertNoHoliday(f"{year}-11-11" for year in range(1925, 1937)) + self.assertNoHolidayName( + "Narodowe Święto Niepodległości", Poland(years=range(1925, 1937)) + ) + self.assertNoHolidayName( + "Narodowe Święto Niepodległości", Poland(years=range(1925, 1937)) + ) + + def test_niepokalane_poczecie_nmp(self): + self.assertHoliday(f"{year}-12-08" for year in range(1925, 1951)) + self.assertNoHoliday(f"{year}-12-08" for year in range(1951, 2050)) + self.assertNoHolidayName( + "Niepokalane Poczęcie Najświętszej Marii Panny", + Poland(years=range(1951, 2050)), + ) + + def test_boze_narodzenie(self): + self.assertHoliday(f"{year}-12-25" for year in range(1925, 2050)) + self.assertHoliday(f"{year}-12-26" for year in range(1925, 2050)) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + pl = Poland(language=language) + self.assertEqual(pl["2022-01-01"], "Nowy Rok") + self.assertEqual( + pl["2022-12-25"], "Boże Narodzenie (pierwszy dzień)" + ) + + run_tests((Poland.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Poland.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + pl = Poland(language=en_us) + self.assertEqual( + pl["2018-11-12"], + "National Independence Day - 100th anniversary", + ) + self.assertEqual(pl["2022-01-01"], "New Year's Day") + self.assertEqual(pl["2022-12-25"], "Christmas (Day 1)") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + pl = Poland(language=language) + self.assertEqual(pl["2022-01-01"], "New Year's Day") + self.assertEqual(pl["2022-12-25"], "Christmas (Day 1)") + + def test_l10n_uk(self): + uk = "uk" + + pl = Poland(language=uk) + self.assertEqual( + pl["2018-11-12"], + "100-а річниця Дня Незалежності", + ) + self.assertEqual(pl["2022-01-01"], "Новий рік") + self.assertEqual(pl["2022-12-25"], "Перший день Різдва") + + self.set_language(uk) + for language in (None, uk, "invalid"): + pl = Poland(language=language) + self.assertEqual(pl["2022-01-01"], "Новий рік") + self.assertEqual(pl["2022-12-25"], "Перший день Різдва") diff --git a/test/countries/test_portugal.py b/tests/countries/test_portugal.py similarity index 100% rename from test/countries/test_portugal.py rename to tests/countries/test_portugal.py diff --git a/tests/countries/test_puerto_rico.py b/tests/countries/test_puerto_rico.py new file mode 100644 index 000000000..241037ab7 --- /dev/null +++ b/tests/countries/test_puerto_rico.py @@ -0,0 +1,37 @@ +# 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) + +import unittest +from datetime import date + +import holidays +from holidays.constants import NOV + + +class TestPR(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysPR() + + def test_PR_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + self.assertIn( + "Discovery Day (Observed)", + self.holidays.get_list(date(2017, NOV, 20)), + ) + + def test_aliases(self): + """For coverage purposes""" + for h in [holidays.PR(), holidays.PRI(), holidays.PuertoRico()]: + self.assertIsInstance(h, holidays.HolidaysPR) diff --git a/test/countries/test_romania.py b/tests/countries/test_romania.py similarity index 100% rename from test/countries/test_romania.py rename to tests/countries/test_romania.py diff --git a/test/countries/test_russia.py b/tests/countries/test_russia.py similarity index 51% rename from test/countries/test_russia.py rename to tests/countries/test_russia.py index a0b500d7b..44995de45 100644 --- a/test/countries/test_russia.py +++ b/tests/countries/test_russia.py @@ -9,13 +9,14 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -from holidays.countries.russia import RU, RUS, Russia -from test.common import TestCase +from holidays.countries.russia import Russia, RU, RUS +from tests.common import TestCase class TestRussia(TestCase): - def setUp(self): - self.holidays = Russia() + @classmethod + def setUpClass(cls): + super().setUpClass(Russia) def test_country_aliases(self): self.assertCountryAliases(Russia, RU, RUS) @@ -46,3 +47,28 @@ def test_2018(self): "2018-11-07", "2018-12-31", ) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + ru = Russia(language=language) + self.assertEqual(ru["2022-01-01"], "Новогодние каникулы") + self.assertEqual(ru["2022-01-07"], "Рождество Христово") + + run_tests((Russia.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Russia.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + ru = Russia(language=en_us) + self.assertEqual(ru["2022-01-01"], "New Year Holidays") + self.assertEqual(ru["2022-01-07"], "Orthodox Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + ru = Russia(language=language) + self.assertEqual(ru["2022-01-01"], "New Year Holidays") + self.assertEqual(ru["2022-01-07"], "Orthodox Christmas Day") diff --git a/test/countries/test_san_marino.py b/tests/countries/test_san_marino.py similarity index 98% rename from test/countries/test_san_marino.py rename to tests/countries/test_san_marino.py index 4bbeaf2d4..92fe56479 100644 --- a/test/countries/test_san_marino.py +++ b/tests/countries/test_san_marino.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.san_marino import SM, SMR, SanMarino -from test.common import TestCase +from tests.common import TestCase class TestSanMarino(TestCase): diff --git a/test/countries/test_saudi_arabia.py b/tests/countries/test_saudi_arabia.py similarity index 100% rename from test/countries/test_saudi_arabia.py rename to tests/countries/test_saudi_arabia.py diff --git a/test/countries/test_serbia.py b/tests/countries/test_serbia.py similarity index 69% rename from test/countries/test_serbia.py rename to tests/countries/test_serbia.py index 250643c07..8a316f310 100644 --- a/test/countries/test_serbia.py +++ b/tests/countries/test_serbia.py @@ -9,15 +9,19 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) -import unittest from datetime import date -import holidays +from holidays.countries.serbia import Serbia, RS, SRB +from tests.common import TestCase -class TestSerbia(unittest.TestCase): - def setUp(self): - self.holidays = holidays.Serbia(observed=True) +class TestSerbia(TestCase): + @classmethod + def setUpClass(cls): + super().setUpClass(Serbia) + + def test_country_aliases(self): + self.assertCountryAliases(Serbia, RS, SRB) def test_new_year(self): # If January 1st is in Weekend, test oberved @@ -67,3 +71,28 @@ def test_religious_holidays(self): self.assertIn(date(2020, 4, 19), self.holidays) self.assertIn(date(2020, 4, 20), self.holidays) self.assertNotIn(date(2020, 4, 21), self.holidays) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + rs = Serbia(language=language) + self.assertEqual(rs["2022-01-01"], "Нова година") + self.assertEqual(rs["2022-01-07"], "Божић") + + run_tests((Serbia.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Serbia.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + + rs = Serbia(language=en_us) + self.assertEqual(rs["2022-01-01"], "New Year's Day") + self.assertEqual(rs["2022-01-07"], "Orthodox Christmas Day") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + rs = Serbia(language=language) + self.assertEqual(rs["2022-01-01"], "New Year's Day") + self.assertEqual(rs["2022-01-07"], "Orthodox Christmas Day") diff --git a/test/countries/test_singapore.py b/tests/countries/test_singapore.py similarity index 100% rename from test/countries/test_singapore.py rename to tests/countries/test_singapore.py diff --git a/test/countries/test_slovakia.py b/tests/countries/test_slovakia.py similarity index 100% rename from test/countries/test_slovakia.py rename to tests/countries/test_slovakia.py diff --git a/test/countries/test_slovenia.py b/tests/countries/test_slovenia.py similarity index 100% rename from test/countries/test_slovenia.py rename to tests/countries/test_slovenia.py diff --git a/test/countries/test_south_africa.py b/tests/countries/test_south_africa.py similarity index 100% rename from test/countries/test_south_africa.py rename to tests/countries/test_south_africa.py diff --git a/test/countries/test_south_korea.py b/tests/countries/test_south_korea.py similarity index 100% rename from test/countries/test_south_korea.py rename to tests/countries/test_south_korea.py diff --git a/tests/countries/test_spain.py b/tests/countries/test_spain.py new file mode 100644 index 000000000..7690cf43a --- /dev/null +++ b/tests/countries/test_spain.py @@ -0,0 +1,324 @@ +# 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) + +import unittest +from copy import deepcopy +from datetime import date + +import holidays +from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP +from holidays.constants import OCT, NOV, DEC + + +class TestSpain(unittest.TestCase): + def setUp(self): + self.holidays = holidays.ES(observed=False) + self.holidays_observed = holidays.ES() + self.prov_holidays = { + prov: holidays.ES(observed=False, subdiv=prov) + for prov in holidays.ES.subdivisions + } + + def test_variable_days_in_2016(self): + for prov, prov_holidays in self.prov_holidays.items(): + self.assertEqual( + date(2016, MAR, 24) in prov_holidays, prov not in {"CT", "VC"} + ) + self.assertIn(date(2016, MAR, 25), prov_holidays) + self.assertEqual( + date(2016, MAR, 28) in prov_holidays, + prov in {"CM", "CT", "IB", "NC", "PV", "VC"}, + ) + + def test_fix_days_in_2022(self): + fix_days_whole_country_2022 = ( + (JAN, 1), + (JAN, 6), + (APR, 15), + (AUG, 15), + (OCT, 12), + (NOV, 1), + (DEC, 6), + (DEC, 8), + ) + for m, d in fix_days_whole_country_2022: + self.assertIn(date(2022, m, d), self.holidays_observed) + + def test_province_specific_days(self): + province_days = { + (FEB, 28): {"AN"}, + (MAR, 1): {"IB"}, + (APR, 23): {"AR", "CL"}, + (MAY, 30): {"CN"}, + (MAY, 31): {"CM"}, + (MAY, 2): {"MD"}, + (JUN, 9): {"MC", "RI"}, + (JUL, 25): {"GA"}, + (JUL, 28): {"CB"}, + (AUG, 5): {"CE"}, + (SEP, 2): {"CE"}, + (SEP, 8): {"AS", "EX", "ML"}, + (SEP, 11): {"CT"}, + (SEP, 15): {"CB"}, + (SEP, 17): {"ML"}, + (OCT, 9): {"VC"}, + } + for prov, prov_holidays in self.prov_holidays.items(): + for year in range(2010, 2021): + self.assertEqual( + date(year, DEC, 26) in prov_holidays, prov in {"CT", "IB"} + ) + if year < 2015: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, + prov + in { + "AR", + "CL", + "CM", + "EX", + "GA", + "MC", + "MD", + "ML", + "NC", + "PV", + "VC", + }, + ) + elif year == 2015: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, + prov in {"CM", "MC", "MD", "ML", "NC", "PV", "VC"}, + ) + elif year == 2016: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, + prov in {"MC", "ML", "PV", "VC"}, + ) + elif year == 2017: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, prov in {"PV"} + ) + elif 2018 <= year <= 2019: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, + prov in {"GA", "MC", "NC", "PV", "VC"}, + ) + elif 2020 <= year <= 2021: + self.assertEqual( + date(year, MAR, 19) in prov_holidays, + prov in {"CM", "GA", "MC", "NC", "PV", "VC"}, + ) + + year_province_days = deepcopy(province_days) + + for fest_day, fest_prov in year_province_days.items(): + self.assertEqual( + date(year, *fest_day) in prov_holidays, + prov in fest_prov, + "Failed date `%s`, province `%s`: %s" + % (date(year, *fest_day), prov, fest_prov), + ) + + def test_variable_days_in_2022(self): + province_days = { + (FEB, 28): {"AN"}, + (MAR, 1): {"IB"}, + (MAR, 19): {"VC"}, + (APR, 14): { + "AN", + "AR", + "AS", + "CB", + "CE", + "CL", + "CM", + "CN", + "EX", + "GA", + "IB", + "MC", + "MD", + "ML", + "NC", + "PV", + "RI", + "VC", + }, + (APR, 18): {"CT", "IB", "NC", "PV", "RI", "VC"}, + (APR, 23): {"AR", "CL"}, + (MAY, 2): {"AN", "AS", "CL", "EX", "MC", "MD", "AR"}, + (MAY, 3): {"ML"}, + (MAY, 17): {"GA"}, + (MAY, 30): {"CN"}, + (MAY, 31): {"CM"}, + (JUN, 6): {"CT"}, + (JUN, 9): {"MC", "RI"}, + (JUN, 16): {"CM"}, + (JUN, 24): {"CT", "GA", "VC"}, + (JUL, 9): {"CE"}, + (JUL, 11): {"ML"}, + (JUL, 25): {"GA", "NC", "MD", "PV"}, + (JUL, 28): {"CB"}, + (AUG, 5): {"CE"}, + (SEP, 2): {"CE"}, + (SEP, 6): {"PV"}, + (SEP, 8): {"AS", "EX", "ML"}, + (SEP, 15): {"CB"}, + (SEP, 17): {"ML"}, + (DEC, 26): { + "AN", + "AR", + "AS", + "CB", + "CL", + "CM", + "CN", + "CT", + "EX", + "IB", + "MC", + "MD", + "ML", + "NC", + "RI", + }, + } + + observed_prov_holidays = { + prov: holidays.ES(observed=True, subdiv=prov) + for prov in holidays.ES.subdivisions + } + + for fest_date, fest_provs in province_days.items(): + for prov, prov_holidays in observed_prov_holidays.items(): + self.assertEqual( + date(2022, *fest_date) in prov_holidays, + prov in fest_provs, + "Failed date `%s`, province `%s`: %s" + % (date(2022, *fest_date), prov, ", ".join(fest_provs)), + ) + + def test_variable_days_in_2023(self): + province_days = { + (JAN, 2): { + "AN", + "AR", + "AS", + "CL", + "MC", + }, + (JAN, 6): { + "AN", + "AR", + "AS", + "CB", + "CE", + "CL", + "CM", + "CN", + "CT", + "EX", + "GA", + "IB", + "MC", + "MD", + "ML", + "NC", + "PV", + "RI", + "VC", + }, + (FEB, 21): {"EX"}, + (MAR, 20): {"MD"}, + (APR, 6): { + "AN", + "AR", + "AS", + "CB", + "CE", + "CL", + "CM", + "CN", + "CT", + "EX", + "GA", + "IB", + "MC", + "MD", + "ML", + "NC", + "PV", + "RI", + "VC", + }, + (APR, 10): { + "IB", + "CT", + "VC", + "NC", + "PV", + "RI", + }, + (APR, 21): {"ML"}, + (MAY, 17): {"GA"}, + (JUN, 29): {"CE", "ML"}, + (JUN, 24): {"CT", "VC"}, + (JUN, 8): {"CM"}, + (JUL, 25): {"NC", "PV", "GA", "CL"}, + (AUG, 5): {"CE"}, + (SEP, 15): {"CB"}, + (DEC, 25): { + "AN", + "AR", + "AS", + "CB", + "CE", + "CL", + "CM", + "CN", + "CT", + "EX", + "GA", + "IB", + "MC", + "MD", + "ML", + "NC", + "PV", + "RI", + "VC", + }, + (DEC, 26): {"CT"}, + } + + observed_prov_holidays = { + prov: holidays.ES(observed=True, subdiv=prov) + for prov in holidays.ES.subdivisions + } + + for fest_date, fest_provs in province_days.items(): + for prov, prov_holidays in observed_prov_holidays.items(): + self.assertEqual( + date(2023, *fest_date) in prov_holidays, + prov in fest_provs, + "Failed date `%s`, province `%s`: %s" + % (date(2023, *fest_date), prov, ", ".join(fest_provs)), + ) + + def test_change_of_province_specific_days(self): + prov_holidays = self.prov_holidays["PV"] + self.assertNotIn(date(2010, OCT, 25), prov_holidays) + self.assertIn(date(2011, OCT, 25), prov_holidays) + self.assertIn(date(2012, OCT, 25), prov_holidays) + self.assertIn(date(2013, OCT, 25), prov_holidays) + self.assertNotIn(date(2014, OCT, 25), prov_holidays) diff --git a/test/countries/test_sweden.py b/tests/countries/test_sweden.py similarity index 99% rename from test/countries/test_sweden.py rename to tests/countries/test_sweden.py index b96bbd229..b635c10c5 100644 --- a/test/countries/test_sweden.py +++ b/tests/countries/test_sweden.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.sweden import SE, SWE, Sweden -from test.common import SundayHolidays +from tests.common import SundayHolidays class TestSweden(SundayHolidays): diff --git a/test/countries/test_switzerland.py b/tests/countries/test_switzerland.py similarity index 100% rename from test/countries/test_switzerland.py rename to tests/countries/test_switzerland.py diff --git a/test/countries/test_taiwan.py b/tests/countries/test_taiwan.py similarity index 100% rename from test/countries/test_taiwan.py rename to tests/countries/test_taiwan.py diff --git a/tests/countries/test_thailand.py b/tests/countries/test_thailand.py new file mode 100644 index 000000000..b19f14dbf --- /dev/null +++ b/tests/countries/test_thailand.py @@ -0,0 +1,510 @@ +# 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.thailand import TH, THA, Thailand +from tests.common import TestCase + + +class TestThailand(TestCase): + def setUp(self): + self.holidays = Thailand() + # Checks in lieu not observed until 2030 + self.holidays_no_observed = Thailand(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Thailand, TH, THA) + + def test_no_holidays(self): + self.assertNoHolidays(Thailand(years=1940)) + + def test_2022(self): + self.assertHolidays( + ("2022-01-01", "New Year's Day"), + ("2022-01-03", "New Year's Day (in lieu)"), + ("2022-02-16", "Makha Bucha"), + ("2022-04-06", "Chakri Memorial Day"), + ("2022-04-13", "Songkran Festival"), + ("2022-04-14", "Songkran Festival"), + ("2022-04-15", "Songkran Festival"), + ("2022-05-01", "National Labour Day"), + ("2022-05-02", "National Labour Day (in lieu)"), + ("2022-05-04", "Coronation Day"), + ("2022-05-15", "Visakha Bucha"), + ("2022-05-16", "Visakha Bucha (in lieu)"), + ("2022-05-17", "Royal Ploughing Ceremony"), + ("2022-06-03", "HM Queen Suthida's Birthday"), + ("2022-07-13", "Asarnha Bucha"), + ("2022-07-14", "Buddhist Lent Day"), + ("2022-07-15", "Bridge Public Holiday"), + ("2022-07-28", "HM King Maha Vajiralongkorn's Birthday"), + ("2022-07-29", "Bridge Public Holiday"), + ( + "2022-08-12", + "HM Queen Sirikit The Queen Mother's Birthday; National Mother's Day", # noqa: E501 + ), + ("2022-10-13", "HM King Bhumibol Adulyadej Memorial Day"), + ("2022-10-14", "Bridge Public Holiday"), + ("2022-10-23", "Chulalongkorn Memorial Day"), + ("2022-10-24", "Chulalongkorn Memorial Day (in lieu)"), + ( + "2022-12-05", + "HM King Bhumibol Adulyadej's Birthday; National Father's Day", + ), + ("2022-12-10", "Constitution Day"), + ("2022-12-12", "Constitution Day (in lieu)"), + ("2022-12-30", "Bridge Public Holiday"), + ("2022-12-31", "New Year's Eve"), + ) + + def test_new_years_day(self): + self.assertHoliday(f"{year}-01-01" for year in range(1941, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2011-01-03", + "2012-01-02", + "2017-01-02", + "2022-01-03", + "2023-01-02", + "2028-01-03", + ) + + def test_chakri_memorial_day(self): + self.assertHoliday(f"{year}-04-06" for year in range(1941, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2013-04-08", + "2014-04-07", + "2019-04-08", + "2024-04-08", + "2025-04-07", + "2030-04-08", + ) + + def test_songkran_festival(self): + name = "Songkran Festival" + + self.assertNoHolidayName(name, Thailand(years=1947)) + for year in range(1948, 1954): + self.assertHoliday( + f"{year}-04-13", f"{year}-04-14", f"{year}-04-15" + ) + self.assertNoHolidayName(name, Thailand(years=range(1954, 1957))) + self.assertHolidaysName( + name, (f"{year}-04-13" for year in range(1957, 1989)) + ) + for year in range(1989, 1998): + self.assertHoliday( + f"{year}-04-12", f"{year}-04-13", f"{year}-04-14" + ) + for year in range(1998, 2020): + self.assertHoliday( + f"{year}-04-13", f"{year}-04-14", f"{year}-04-15" + ) + self.assertNoHoliday("2020-04-13", "2020-04-14", "2020-04-15") + for year in range(2021, 2058): + self.assertHoliday( + f"{year}-04-13", f"{year}-04-14", f"{year}-04-15" + ) + + self.assertNoHoliday( + self.holidays_no_observed, + "2012-04-16", + "2013-04-16", + "2017-04-17", + "2018-04-16", + "2019-04-16", + # 2020 Songkran Festival special in lieus doesn't counts + "2023-04-17", + "2024-04-16", + "2028-04-17", + "2029-04-16", + "2030-04-16", + ) + + def test_national_labour_day(self): + name = "National Labour Day" + + self.assertNoHoliday("1973-05-01") + self.assertNoHolidayName(name, Thailand(years=1973)) + self.assertHoliday(f"{year}-05-01" for year in range(1974, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2010-05-03", + "2011-05-02", + "2016-05-02", + "2021-05-03", + "2022-05-02", + "2027-05-03", + ) + + def test_coronation_day(self): + name = "Coronation Day" + + self.assertNoHoliday("1957-05-05") + self.assertNoHolidayName(name, Thailand(years=1957)) + self.assertHoliday(f"{year}-05-05" for year in range(1958, 2017)) + self.assertNoHolidayName(name, Thailand(years=range(2017, 2020))) + self.assertHoliday(f"{year}-05-04" for year in range(2020, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2012-05-07", + "2013-05-06", + "2024-05-06", + "2025-05-05", + "2030-05-06", + ) + + def test_queen_suthida_birthday(self): + name = "HM Queen Suthida's Birthday" + + self.assertNoHoliday("2018-06-03") + self.assertNoHolidayName(name, Thailand(years=2018)) + self.assertHoliday(f"{year}-06-03" for year in range(2019, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2023-06-05", + "2028-06-05", + "2029-06-04", + ) + + def test_national_day(self): + name = "National Day" + + self.assertHoliday(f"{year}-06-24" for year in range(1941, 1960)) + self.assertNoHoliday("1960-06-24") + self.assertNoHolidayName(name, Thailand(years=1960)) + + # No in lieus during its existense + + def test_rama_x_birthday(self): + name = "HM King Maha Vajiralongkorn's Birthday" + + self.assertNoHoliday("2016-07-28") + self.assertNoHolidayName(name, Thailand(years=2016)) + self.assertHoliday(f"{year}-07-28" for year in range(2017, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2018-07-30", + "2019-07-29", + "2024-07-29", + "2029-07-30", + "2030-07-29", + ) + + def test_queen_sirikit_birthday(self): + name_ix = "HM Queen Sirikit's Birthday" + name_x = "HM Queen Sirikit The Queen Mother's Birthday" + + self.assertNoHoliday("1975-08-12") + self.assertNoHolidayName(name_ix, Thailand(years=1975)) + self.assertHolidaysName( + name_ix, (f"{year}-08-12" for year in range(1976, 2017)) + ) + self.assertNoHolidayName(name_x, Thailand(years=range(1941, 2017))) + self.assertHolidaysName( + name_x, (f"{year}-08-12" for year in range(2017, 2058)) + ) + self.assertNoHolidayName(name_ix, Thailand(years=range(2017, 2058))) + + self.assertNoHoliday( + self.holidays_no_observed, + "2012-08-13", + "2017-08-14", + "2018-08-13", + "2023-08-14", + "2028-08-14", + "2029-08-13", + ) + + def test_national_mothers_day(self): + name = "National Mother's Day" + + self.assertNoHolidayName(name, Thailand(years=1949)) + self.assertHolidaysName( + name, (f"{year}-04-15" for year in range(1950, 1958)) + ) + self.assertNoHolidayName(name, Thailand(years=range(1958, 1976))) + self.assertHolidaysName( + name, (f"{year}-08-12" for year in range(1976, 2058)) + ) + + # April 15 (1950-1958) exists prior to in lieu laws + # In lieus are same as HM Queen Sirikit's Birthday + + def test_rama_ix_memorial_day(self): + name = "HM King Bhumibol Adulyadej Memorial Day" + self.assertHoliday(f"{year}-10-13" for year in range(2017, 2058)) + self.assertNoHoliday("2016-10-13") + self.assertNoHolidayName(name, Thailand(years=2016)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2018-10-15", + "2019-10-14", + "2024-10-14", + "2029-10-15", + "2030-10-14", + ) + + def test_rama_five_memorial_day(self): + name = "Chulalongkorn Memorial Day" + self.assertHoliday(f"{year}-10-23" for year in range(1941, 2058)) + self.assertNoHoliday("1910-10-23", "1940-10-23") + self.assertNoHolidayName(name, Thailand(years=[1910, 1940])) + + self.assertNoHoliday( + self.holidays_no_observed, + "2010-10-25", + "2011-10-24", + "2016-10-24", + "2021-10-25", + "2022-10-24", + "2027-10-25", + ) + + def test_rama_ix_birthday(self): + name = "HM King Bhumibol Adulyadej's Birthday" + + self.assertNoHoliday("1959-12-05") + self.assertNoHolidayName(name, Thailand(years=1959)) + self.assertHoliday(f"{year}-12-05" for year in range(1960, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2010-12-06", + "2015-12-07", + "2020-12-07", + "2021-12-06", + "2026-12-07", + "2027-12-06", + ) + + def test_national_fathers_day(self): + name = "National Father's Day" + + # This concides with HM King Bhumibol Adulyadej's Birthday + self.assertNoHolidayName(name, Thailand(years=1979)) + self.assertHolidaysName( + name, (f"{year}-12-05" for year in range(1980, 2058)) + ) + + # In lieus are same as HM King Bhumibol Adulyadej's Birthday + + def test_constitution_day(self): + self.assertHoliday(f"{year}-12-10" for year in range(1941, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2011-12-12", + "2016-12-12", + "2017-12-11", + "2022-12-12", + "2023-12-11", + "2028-12-11", + ) + + def test_new_years_eve(self): + self.assertHoliday(f"{year}-12-31" for year in range(1941, 2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2012-01-03", + "2017-01-03", + "2018-01-02", + "2023-01-03", + "2024-01-02", + "2029-01-02", + ) + + def test_makha_bucha(self): + name = "Makha Bucha" + + dt = ( + "2010-02-28", + "2011-02-18", + "2012-03-07", + "2013-02-25", + "2014-02-14", + "2015-03-04", + "2016-02-22", + "2017-02-11", + "2018-03-01", + "2019-02-19", + "2020-02-08", + "2021-02-26", + "2022-02-16", + "2023-03-06", + "2024-02-24", + "2025-02-12", + "2026-03-03", + "2027-02-21", + "2028-02-10", + "2029-02-27", + "2030-02-17", + ) + self.assertHolidaysName(name, dt) + self.assertNoHolidayName(name, Thailand(years=2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2010-03-01", + "2017-02-13", + "2020-02-10", + "2024-02-26", + "2024-02-22", + "2030-02-18", + ) + + def test_visakha_bucha(self): + name = "Visakha Bucha" + + dt = ( + "2010-05-28", + "2011-05-17", + "2012-06-04", + "2013-05-24", + "2014-05-13", + "2015-06-01", + "2016-05-20", + "2017-05-10", + "2018-05-29", + "2019-05-18", + "2020-05-06", + "2021-05-26", + "2022-05-15", + "2023-06-03", + "2024-05-22", + "2025-05-11", + "2026-05-31", + "2027-05-20", + "2028-05-08", + "2029-05-27", + "2030-05-16", + ) + self.assertHolidaysName(name, dt) + self.assertNoHolidayName(name, Thailand(years=2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2019-05-20", + "2022-05-16", + "2023-06-05", + "2025-05-12", + "2026-06-01", + "2029-05-28", + ) + + def test_asarnha_bucha(self): + name = "Asarnha Bucha" + + dt = ( + "2010-07-26", + "2011-07-15", + "2012-08-02", + "2013-07-22", + "2014-07-11", + "2015-07-30", + "2016-07-19", + "2017-07-08", + "2018-07-27", + "2019-07-16", + "2020-07-05", + "2021-07-24", + "2022-07-13", + "2023-08-01", + "2024-07-20", + "2025-07-10", + "2026-07-29", + "2027-07-18", + "2028-07-06", + "2029-07-25", + "2030-07-14", + ) + self.assertHolidaysName(name, dt) + self.assertNoHolidayName(name, Thailand(years=2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2017-07-10", + "2020-07-07", + "2021-07-26", + "2024-07-22", + "2027-07-20", + "2030-07-16", + ) + + def test_khao_phansa(self): + name = "Buddhist Lent Day" + + dt = ( + "2010-07-27", + "2011-07-16", + "2012-08-03", + "2013-07-23", + "2014-07-12", + "2015-07-31", + "2016-07-20", + "2017-07-09", + "2018-07-28", + "2019-07-17", + "2020-07-06", + "2021-07-25", + "2022-07-14", + "2023-08-02", + "2024-07-21", + "2025-07-11", + "2026-07-30", + "2027-07-19", + "2028-07-07", + "2029-07-26", + "2030-07-15", + ) + self.assertHolidaysName(name, dt) + self.assertNoHolidayName(name, Thailand(years=2058)) + + self.assertNoHoliday( + self.holidays_no_observed, + "2011-07-18", + "2014-07-14", + "2018-07-30", + ) + + def test_raeknakhwan(self): + name = "Royal Ploughing Ceremony" + dt = ( + "2011-05-13", + "2012-05-09", + "2013-05-13", + "2014-05-09", + "2015-05-13", + "2016-05-09", + "2017-05-12", + "2018-05-14", + "2019-05-09", + "2020-05-11", + "2021-05-13", + "2022-05-17", + "2023-05-11", + ) + self.assertHolidaysName(name, dt) + self.assertNoHolidayName(name, Thailand(years=[1956, 1999])) + + self.assertHolidaysName( + name, (f"{year}-05-13" for year in range(1957, 1997)) + ) + + # No Royal Ploughing Ceremony on weekend for 1997-2023 diff --git a/test/countries/test_tunisia.py b/tests/countries/test_tunisia.py similarity index 92% rename from test/countries/test_tunisia.py rename to tests/countries/test_tunisia.py index 4c220441d..d07f7e060 100644 --- a/test/countries/test_tunisia.py +++ b/tests/countries/test_tunisia.py @@ -36,13 +36,13 @@ def test2021(self): def test_hijri_based(self): if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.TN(years=[2015]) - # eid_alfitr self.assertIn(date(2015, 7, 17), self.holidays) # eid_aladha self.assertIn(date(2015, 9, 24), self.holidays) # islamic_new_year + self.assertIn(date(2008, 1, 10), self.holidays) + self.assertIn(date(2008, 12, 29), self.holidays) self.assertIn(date(2015, 10, 14), self.holidays) # eid_elfetr_2019 diff --git a/test/countries/test_turkey.py b/tests/countries/test_turkey.py similarity index 100% rename from test/countries/test_turkey.py rename to tests/countries/test_turkey.py diff --git a/tests/countries/test_ukraine.py b/tests/countries/test_ukraine.py new file mode 100644 index 000000000..10d9102c3 --- /dev/null +++ b/tests/countries/test_ukraine.py @@ -0,0 +1,466 @@ +# 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.ukraine import Ukraine, UA, UKR +from tests.common import TestCase + + +class TestUkraine(TestCase): + def setUp(self): + super().setUp() + self.holidays_no_observed = Ukraine(observed=False) + + @classmethod + def setUpClass(cls): + super().setUpClass(Ukraine) + + def test_country_aliases(self): + self.assertCountryAliases(Ukraine, UA, UKR) + + def test_no_holidays(self): + self.assertNoHolidays(Ukraine(years=1917)) + + def test_new_year_day(self): + self.assertHoliday(f"{year}-01-01" for year in range(1918, 1930)) + self.assertNoHoliday(f"{year}-01-01" for year in range(1930, 1948)) + self.assertNoHolidayName("Новий рік", Ukraine(years=range(1930, 1948))) + self.assertHoliday(f"{year}-01-01" for year in range(1948, 2050)) + + dt = ( + "2011-01-03", + "2012-01-02", + "2017-01-02", + "2022-01-03", + "2023-01-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_christmas_julian_day(self): + self.assertNoHoliday(f"{year}-01-07" for year in range(1918, 1991)) + self.assertNoHolidayName( + "Різдво Христове (за юліанським календарем)", + Ukraine(years=range(1918, 1991)), + ) + self.assertHoliday(f"{year}-01-07" for year in range(1991, 2050)) + + dt = ( + "2012-01-09", + "2017-01-09", + "2018-01-08", + "2023-01-09", + "2024-01-08", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_womens_day(self): + self.assertNoHoliday(f"{year}-03-08" for year in range(1918, 1966)) + self.assertNoHolidayName( + "Міжнародний жіночий день", Ukraine(years=range(1918, 1966)) + ) + self.assertHoliday(f"{year}-03-08" for year in range(1966, 2050)) + + dt = ( + "2014-03-10", + "2015-03-09", + "2020-03-09", + "2025-03-10", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_easter(self): + name = "Великдень (Пасха)" + self.assertNoHolidayName(name, Ukraine(years=range(1918, 1991))) + + self.assertHolidaysName( + name, + "2010-04-04", + "2011-04-24", + "2012-04-15", + "2013-05-05", + "2014-04-20", + "2015-04-12", + "2016-05-01", + "2017-04-16", + "2018-04-08", + "2019-04-28", + "2020-04-19", + "2021-05-02", + "2022-04-24", + "2023-04-16", + ) + + dt = ( + "2010-04-05", + "2011-04-25", + "2012-04-16", + "2013-05-06", + "2014-04-21", + "2015-04-13", + "2016-05-03", + "2017-04-17", + "2018-04-09", + "2019-04-29", + "2020-04-20", + "2021-05-04", + "2022-04-25", + "2023-04-17", + # special cases + "2000-05-03", + "2005-05-03", + "2027-05-04", + "2032-05-04", + "2062-05-02", + "2073-05-02", + "2078-05-10", + "2084-05-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_trinity(self): + name = "Трійця" + self.assertNoHolidayName(name, Ukraine(years=range(1918, 1991))) + + self.assertHolidaysName( + name, + "2010-05-23", + "2011-06-12", + "2012-06-03", + "2013-06-23", + "2014-06-08", + "2015-05-31", + "2016-06-19", + "2017-06-04", + "2018-05-27", + "2019-06-16", + "2020-06-07", + "2021-06-20", + "2022-06-12", + "2023-06-04", + ) + + dt = ( + "2010-05-24", + "2011-06-13", + "2012-06-04", + "2013-06-24", + "2014-06-09", + "2015-06-01", + "2016-06-20", + "2017-06-05", + "2018-05-28", + "2019-06-17", + "2020-06-08", + "2021-06-21", + "2022-06-13", + "2023-06-05", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_labour_day(self): + name_before = "День міжнародної солідарності трудящих" + name_after = "День праці" + self.assertHoliday(f"{year}-05-01" for year in range(1918, 2050)) + self.assertHoliday(f"{year}-05-02" for year in range(1929, 2018)) + self.assertNoHoliday("1928-05-02", "2018-05-02") + self.assertNoHolidayName(name_after, Ukraine(years=range(1918, 2018))) + self.assertNoHolidayName(name_before, Ukraine(years=range(2018, 2050))) + + dt = ( + "2010-05-03", + "2010-05-04", + "2011-05-03", + "2015-05-04", + "2016-05-03", + "2021-05-03", + "2022-05-02", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_victory_day(self): + name = ( + "День перемоги над нацизмом у Другій світовій війні " + "(День перемоги)" + ) + self.assertHoliday(f"{year}-05-09" for year in range(1965, 2050)) + self.assertNoHoliday("1944-05-09", "1947-05-09", "1964-05-09") + self.assertNoHolidayName(name, Ukraine(years=range(1918, 2016))) + self.assertHoliday( + "1945-05-09", "1945-09-03", "1946-05-09", "1946-09-03" + ) + + dt = ( + "2010-05-10", + "2015-05-11", + "2020-05-11", + "2021-05-10", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_constitution_day(self): + self.assertNoHoliday(f"{year}-06-28" for year in range(1918, 1997)) + self.assertNoHolidayName( + "День Конституції України", Ukraine(years=range(1918, 1997)) + ) + self.assertHoliday(f"{year}-06-28" for year in range(1997, 2050)) + + dt = ( + "2014-06-30", + "2015-06-29", + "2020-06-29", + "2025-06-30", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_statehood_day(self): + self.assertNoHoliday(f"{year}-07-28" for year in range(1918, 2022)) + self.assertNoHolidayName( + "День Української Державності", Ukraine(years=range(1918, 2022)) + ) + self.assertHoliday(f"{year}-07-28" for year in range(2022, 2050)) + + dt = ("2024-07-29",) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_independence_day(self): + self.assertNoHoliday(f"{year}-08-24" for year in range(1918, 1992)) + self.assertNoHolidayName( + "День незалежності України", Ukraine(years=range(1918, 1991)) + ) + self.assertHoliday("1991-07-16") + self.assertNoHoliday("1990-07-16", "1992-07-16") + self.assertHoliday(f"{year}-08-24" for year in range(1992, 2050)) + + dt = ( + "2013-08-26", + "2014-08-25", + "2019-08-26", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_defenders_day(self): + name_before = "День захисника України" + name_after = "День захисників і захисниць України" + self.assertNoHoliday(f"{year}-10-14" for year in range(1918, 2015)) + self.assertHoliday(f"{year}-10-14" for year in range(2015, 2050)) + self.assertNoHolidayName(name_before, Ukraine(years=range(1918, 2015))) + self.assertNoHolidayName(name_before, Ukraine(years=range(2021, 2050))) + self.assertNoHolidayName(name_after, Ukraine(years=range(1918, 2021))) + + dt = ( + "2017-10-16", + "2018-10-15", + "2023-10-16", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_october_revolution_day(self): + self.assertHoliday(f"{year}-11-07" for year in range(1918, 2000)) + self.assertHoliday(f"{year}-11-08" for year in range(1918, 2000)) + self.assertNoHoliday(f"{year}-11-07" for year in range(2000, 2050)) + self.assertNoHoliday(f"{year}-11-08" for year in range(2000, 2050)) + self.assertNoHolidayName( + "Річниця Великої Жовтневої соціалістичної революції", + Ukraine(years=range(2000, 2050)), + ) + + dt = ( + "1997-11-10", + "1999-11-09", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_christmas_gregorian_day(self): + self.assertNoHoliday(f"{year}-12-25" for year in range(1918, 2017)) + self.assertNoHolidayName( + "Різдво Христове (за григоріанським календарем)", + Ukraine(years=range(1918, 2017)), + ) + self.assertHoliday(f"{year}-12-25" for year in range(2017, 2050)) + + dt = ( + "2021-12-27", + "2022-12-26", + ) + self.assertHoliday(dt) + self.assertNoHoliday(self.holidays_no_observed, dt) + + def test_old_holidays(self): + self.assertHoliday(f"{year}-01-22" for year in range(1918, 1951)) + self.assertNoHoliday(f"{year}-01-22" for year in range(1951, 2050)) + self.assertNoHolidayName( + "День пам’яті 9 січня 1905 року", Ukraine(years=range(1951, 2050)) + ) + + self.assertHoliday(f"{year}-03-18" for year in range(1918, 1929)) + self.assertNoHoliday(f"{year}-03-18" for year in range(1929, 2050)) + self.assertNoHolidayName( + "День Паризької Комуни", Ukraine(years=range(1929, 2050)) + ) + + self.assertHoliday(f"{year}-12-05" for year in range(1937, 1981)) + self.assertNoHoliday(f"{year}-12-05" for year in range(1981, 2050)) + self.assertHoliday(f"{year}-10-07" for year in range(1981, 1991)) + self.assertNoHoliday(f"{year}-10-07" for year in range(1991, 2050)) + self.assertNoHolidayName( + "День Конституції СРСР", Ukraine(years=range(1918, 1937)) + ) + self.assertNoHolidayName( + "День Конституції СРСР", Ukraine(years=range(1991, 2050)) + ) + + def test_2018(self): + # https://www.buhoblik.org.ua/kadry-zarplata/vremya/3678-3678-normi-trivalosti-robochogo-chasu.html + self.assertHolidayDates( + "2018-01-01", + "2018-01-07", + "2018-01-08", + "2018-03-08", + "2018-04-08", + "2018-04-09", + "2018-05-01", + "2018-05-09", + "2018-05-27", + "2018-05-28", + "2018-06-28", + "2018-08-24", + "2018-10-14", + "2018-10-15", + "2018-12-25", + ) + + def test_2019(self): + # https://www.buhoblik.org.ua/kadry-zarplata/vremya/3946-3946-normi-trivalosti-robochogo-chasu.html + self.assertHolidayDates( + "2019-01-01", + "2019-01-07", + "2019-03-08", + "2019-04-28", + "2019-04-29", + "2019-05-01", + "2019-05-09", + "2019-06-16", + "2019-06-17", + "2019-06-28", + "2019-08-24", + "2019-08-26", + "2019-10-14", + "2019-12-25", + ) + + def test_2020(self): + # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4058-4058-normi-trivalosti-robochogo-chasu.html + self.assertHolidayDates( + "2020-01-01", + "2020-01-07", + "2020-03-08", + "2020-03-09", + "2020-04-19", + "2020-04-20", + "2020-05-01", + "2020-05-09", + "2020-05-11", + "2020-06-07", + "2020-06-08", + "2020-06-28", + "2020-06-29", + "2020-08-24", + "2020-10-14", + "2020-12-25", + ) + + def test_2021(self): + # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4221-4221-norma-trivalosti-robochogo-chasu.html + self.assertHolidayDates( + "2021-01-01", + "2021-01-07", + "2021-03-08", + "2021-05-01", + "2021-05-02", + "2021-05-03", + "2021-05-04", + "2021-05-09", + "2021-05-10", + "2021-06-20", + "2021-06-21", + "2021-06-28", + "2021-08-24", + "2021-10-14", + "2021-12-25", + "2021-12-27", + ) + + def test_2022(self): + # https://www.buhoblik.org.ua/kadry-zarplata/vremya/4246-norma-trivalosti-robochogo-chasu-2022.html + self.assertHolidayDates( + "2022-01-01", + "2022-01-03", + "2022-01-07", + "2022-03-08", + "2022-04-24", + "2022-04-25", + "2022-05-01", + "2022-05-02", + "2022-05-09", + "2022-06-12", + "2022-06-13", + "2022-06-28", + "2022-07-28", + "2022-08-24", + "2022-10-14", + "2022-12-25", + "2022-12-26", + ) + + def test_l10n_default(self): + def run_tests(languages): + for language in languages: + ua = Ukraine(language=language) + self.assertEqual(ua["2022-01-01"], "Новий рік") + self.assertEqual( + ua["2022-12-25"], + "Різдво Христове (за григоріанським календарем)", + ) + + run_tests((Ukraine.default_language, None, "invalid")) + + self.set_language("en_US") + run_tests((Ukraine.default_language,)) + + def test_l10n_en_us(self): + en_us = "en_US" + ua = Ukraine(language=en_us) + + self.assertEqual(ua["2022-01-01"], "New Year's Day") + self.assertEqual(ua["2022-01-07"], "Christmas (Julian calendar)") + self.assertEqual(ua["2022-12-25"], "Christmas (Gregorian calendar)") + self.assertEqual(ua["2023-01-02"], "New Year's Day (Observed)") + + self.set_language(en_us) + for language in (None, en_us, "invalid"): + ua = Ukraine(language=language) + self.assertEqual(ua["2022-01-01"], "New Year's Day") + self.assertEqual(ua["2022-01-07"], "Christmas (Julian calendar)") + self.assertEqual( + ua["2022-12-25"], "Christmas (Gregorian calendar)" + ) + self.assertEqual(ua["2023-01-02"], "New Year's Day (Observed)") diff --git a/test/countries/test_united_arab_emirates.py b/tests/countries/test_united_arab_emirates.py similarity index 95% rename from test/countries/test_united_arab_emirates.py rename to tests/countries/test_united_arab_emirates.py index 4a5e85acf..4f311223f 100644 --- a/test/countries/test_united_arab_emirates.py +++ b/tests/countries/test_united_arab_emirates.py @@ -41,7 +41,6 @@ def test_commemoration_day_since_2015(self): def test_hijri_based(self): if importlib.util.find_spec("hijri_converter"): - self.holidays = holidays.AE(years=[2020]) # Eid Al-Fitr self.assertIn(date(2020, 5, 24), self.holidays) self.assertIn(date(2020, 5, 25), self.holidays) @@ -52,6 +51,8 @@ def test_hijri_based(self): self.assertIn(date(2020, 8, 1), self.holidays) self.assertIn(date(2020, 8, 2), self.holidays) # Islamic New Year + self.assertIn(date(2008, 1, 10), self.holidays) + self.assertIn(date(2008, 12, 29), self.holidays) self.assertIn(date(2020, 8, 23), self.holidays) # Leilat Al-Miraj 2018 self.assertIn(date(2018, 4, 13), self.holidays) diff --git a/test/countries/test_united_kingdom.py b/tests/countries/test_united_kingdom.py similarity index 90% rename from test/countries/test_united_kingdom.py rename to tests/countries/test_united_kingdom.py index 664c61c26..9f1914e06 100644 --- a/test/countries/test_united_kingdom.py +++ b/tests/countries/test_united_kingdom.py @@ -11,6 +11,7 @@ import unittest from datetime import date +from datetime import timedelta as td from dateutil.relativedelta import relativedelta as rd @@ -44,9 +45,9 @@ def test_new_years(self): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) if year == 2000: - self.assertIn(dt + rd(days=-1), self.holidays) + self.assertIn(dt + td(days=-1), self.holidays) else: - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) def test_good_friday(self): for dt in [ @@ -61,8 +62,8 @@ def test_good_friday(self): date(2020, 4, 10), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_easter_monday(self): for dt in [ @@ -77,8 +78,8 @@ def test_easter_monday(self): date(2020, 4, 13), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_royal_weddings(self): for dt in [date(1981, 7, 29), date(2011, 4, 29)]: @@ -119,8 +120,8 @@ def test_may_day(self): date(2020, 5, 8), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2020, 5, 4), self.holidays) def test_spring_bank_holiday(self): @@ -137,16 +138,16 @@ def test_spring_bank_holiday(self): date(2022, 6, 2), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) if dt != date(2022, 6, 2): - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_christmas_day(self): self.holidays.observed = False for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) self.assertNotIn(date(2010, 12, 24), self.holidays) self.assertNotEqual( self.holidays[date(2011, 12, 26)], "Christmas Day (Observed)" @@ -191,7 +192,7 @@ def test_boxing_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2009, 12, 28), self.holidays) self.assertNotIn(date(2010, 12, 27), self.holidays) self.holidays.observed = True diff --git a/test/countries/test_united_states.py b/tests/countries/test_united_states.py similarity index 92% rename from test/countries/test_united_states.py rename to tests/countries/test_united_states.py index e35db4c93..f72e29bd4 100644 --- a/test/countries/test_united_states.py +++ b/tests/countries/test_united_states.py @@ -11,11 +11,11 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays -from holidays.constants import SAT, SUN +from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, SEP, OCT +from holidays.constants import NOV, DEC, SAT, SUN class TestUS(unittest.TestCase): @@ -32,11 +32,10 @@ def test_new_years(self): for year in range(1900, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_Juneteenth_day(self): - for year in range(2010, 2020): self.assertNotIn(date(year, 6, 19), self.holidays) for year in range(2021, 2030): @@ -120,8 +119,8 @@ def test_martin_luther(self): date(2020, 1, 20), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn( "Martin Luther King Jr. Day", holidays.US(years=[1985]).values() ) @@ -288,8 +287,8 @@ def test_washingtons_birthday(self): date(2020, 2, 17), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(dt, de_holidays) self.assertNotEqual(fl_holidays.get(dt), "Washington's Birthday") self.assertNotIn(dt, ga_holidays) @@ -508,6 +507,7 @@ def test_good_friday(self): in_holidays = holidays.US(subdiv="IN") ky_holidays = holidays.US(subdiv="IN") la_holidays = holidays.US(subdiv="LA") + mp_holidays = holidays.US(subdiv="MP") nj_holidays = holidays.US(subdiv="NJ") nc_holidays = holidays.US(subdiv="NC") tn_holidays = holidays.US(subdiv="TN") @@ -531,6 +531,7 @@ def test_good_friday(self): self.assertIn(dt, in_holidays) self.assertIn(dt, ky_holidays) self.assertIn(dt, la_holidays) + self.assertIn(dt, mp_holidays) self.assertIn(dt, nj_holidays) self.assertIn(dt, nc_holidays) self.assertIn(dt, tn_holidays) @@ -622,8 +623,8 @@ def test_truman_day(self): dt = date(year, 5, 8) self.assertNotIn(dt, self.holidays) self.assertIn(dt, mo_holidays) - self.assertNotIn(dt + rd(days=-1), mo_holidays) - self.assertNotIn(dt + rd(days=+1), mo_holidays) + self.assertNotIn(dt + td(days=-1), mo_holidays) + self.assertNotIn(dt + td(days=+1), mo_holidays) self.assertNotIn(date(2004, 5, 7), mo_holidays) self.assertNotIn(date(2005, 5, 9), mo_holidays) mo_holidays.observed = True @@ -646,8 +647,8 @@ def test_memorial_day(self): date(2020, 5, 25), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_jefferson_davis_birthday(self): al_holidays = holidays.US(subdiv="AL") @@ -726,8 +727,8 @@ def test_independence_day(self): for year in range(1900, 2100): dt = date(year, 7, 4) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2010, 7, 5), self.holidays) self.assertNotIn(date(2020, 7, 3), self.holidays) self.holidays.observed = True @@ -843,8 +844,8 @@ def test_labor_day(self): date(2020, 9, 7), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_columbus_day(self): ak_holidays = holidays.US(subdiv="AK") @@ -869,8 +870,8 @@ def test_columbus_day(self): self.assertNotIn(dt, de_holidays) self.assertNotIn(dt, fl_holidays) self.assertNotIn(dt, hi_holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual(sd_holidays.get(dt), "Native American Day") self.assertEqual( vi_holidays.get(dt), @@ -988,8 +989,8 @@ def test_veterans_day(self): date(2020, 11, 11), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn("Armistice Day", holidays.US(years=[1937]).values()) self.assertNotIn("Armistice Day", holidays.US(years=[1937]).values()) self.assertIn("Armistice Day", holidays.US(years=[1938]).values()) @@ -1036,64 +1037,64 @@ def test_thanksgiving_day(self): date(2020, 11, 26), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertIn(dt + rd(days=+1), de_holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertIn(dt + td(days=+1), de_holidays) self.assertEqual( - ca_holidays.get(dt + rd(days=+1)), + ca_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - de_holidays.get(dt + rd(days=+1)), + de_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - nh_holidays.get(dt + rd(days=+1)), + nh_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - nc_holidays.get(dt + rd(days=+1)), + nc_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - ok_holidays.get(dt + rd(days=+1)), + ok_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - pa_holidays.get(dt + rd(days=+1)), + pa_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) self.assertEqual( - wv_holidays.get(dt + rd(days=+1)), + wv_holidays.get(dt + td(days=+1)), "Day After Thanksgiving", ) - self.assertIn(dt + rd(days=+1), fl_holidays) + self.assertIn(dt + td(days=+1), fl_holidays) self.assertEqual( - fl_holidays.get(dt + rd(days=+1)), + fl_holidays.get(dt + td(days=+1)), "Friday After Thanksgiving", ) - self.assertIn(dt + rd(days=+1), tx_holidays) + self.assertIn(dt + td(days=+1), tx_holidays) self.assertEqual( - tx_holidays.get(dt + rd(days=+1)), + tx_holidays.get(dt + td(days=+1)), "Friday After Thanksgiving", ) - self.assertEqual(nv_holidays.get(dt + rd(days=+1)), "Family Day") + self.assertEqual(nv_holidays.get(dt + td(days=+1)), "Family Day") self.assertEqual( - nm_holidays.get(dt + rd(days=+1)), "Presidents' Day" + nm_holidays.get(dt + td(days=+1)), "Presidents' Day" ) if dt.year >= 2008: self.assertEqual( - md_holidays.get(dt + rd(days=+1)), + md_holidays.get(dt + td(days=+1)), "American Indian Heritage Day", ) if dt.year >= 2010: self.assertEqual( - in_holidays.get(dt + rd(days=+1)), + in_holidays.get(dt + td(days=+1)), "Lincoln's Birthday", ) else: self.assertNotEqual( - in_holidays.get(dt + rd(days=+1)), + in_holidays.get(dt + td(days=+1)), "Lincoln's Birthday", ) @@ -1190,8 +1191,8 @@ def test_christmas_day(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertNotIn(date(2010, 12, 24), self.holidays) self.assertNotIn(date(2016, 12, 26), self.holidays) self.holidays.observed = True @@ -1237,3 +1238,34 @@ def test_new_years_eve(self): self.assertIn(dt, ky_holidays) self.assertIn(dt, mi_holidays) self.assertIn(dt, wi_holidays) + + def test_northern_mariana_islands_2022(self): + """Sources: + https://governor.gov.mp/archived-news/executive-actions-archive/memorandum-2022-legal-holidays/ + https://webcache.googleusercontent.com/search?q=cache:C17_7FBgPtQJ:https://governor.gov.mp/archived-news/executive-actions-archive/memorandum-2022-legal-holidays/&hl=en&gl=sg&strip=1&vwsrc=0 + """ + mp_holidays = holidays.US(subdiv="MP") + + self.assertIn(date(2022, JAN, 1), mp_holidays) + self.assertIn(date(2022, JAN, 17), mp_holidays) + self.assertIn(date(2022, FEB, 21), mp_holidays) + self.assertIn(date(2022, MAR, 24), mp_holidays) + self.assertIn(date(2022, APR, 15), mp_holidays) + self.assertIn(date(2022, MAY, 30), mp_holidays) + self.assertIn(date(2022, JUN, 19), mp_holidays) + self.assertIn(date(2022, JUN, 20), mp_holidays) + self.assertIn(date(2022, JUL, 4), mp_holidays) + self.assertIn(date(2022, SEP, 5), mp_holidays) + self.assertIn(date(2022, OCT, 10), mp_holidays) + self.assertIn(date(2022, NOV, 4), mp_holidays) + self.assertIn(date(2022, NOV, 8), mp_holidays) + self.assertIn(date(2022, NOV, 11), mp_holidays) + self.assertIn(date(2022, NOV, 24), mp_holidays) + self.assertIn(date(2022, DEC, 8), mp_holidays) + self.assertIn(date(2022, DEC, 25), mp_holidays) + self.assertIn(date(2022, DEC, 26), mp_holidays) + # 2022: total holidays (16 + 2 falling on a Sunday) + self.assertEqual( + 16 + 2, + len(holidays.US(subdiv="MP", years=[2022])), + ) diff --git a/tests/countries/test_united_states_minor_outlying_islands.py b/tests/countries/test_united_states_minor_outlying_islands.py new file mode 100644 index 000000000..fb2d41b9e --- /dev/null +++ b/tests/countries/test_united_states_minor_outlying_islands.py @@ -0,0 +1,39 @@ +# 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) + +import unittest + +import holidays + + +class TestUM(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysUM() + + def test_UM_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + # self.assertIn( + # "Christmas Eve (Observed)", + # self.holidays.get_list(date(2017, DEC, 22)), + # ) + + def test_aliases(self): + """For coverage purposes""" + for h in [ + holidays.UM(), + holidays.UMI(), + holidays.UnitedStatesMinorOutlyingIslands(), + ]: + self.assertIsInstance(h, holidays.HolidaysUM) diff --git a/tests/countries/test_united_states_virgin_islands.py b/tests/countries/test_united_states_virgin_islands.py new file mode 100644 index 000000000..c083fd223 --- /dev/null +++ b/tests/countries/test_united_states_virgin_islands.py @@ -0,0 +1,41 @@ +# 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) + +import unittest +from datetime import date + +import holidays +from holidays.constants import MAR + + +class TestVI(unittest.TestCase): + # Testing the stub for a US subdivision that is also officially assigned + # its own country code in ISO 3166-1. The actual holidays are generated by + # the US Class and tested there. + def setUp(self): + self.holidays = holidays.HolidaysVI() + + def test_VI_only(self): + """Check for a holiday that is not returned by US unless the + subdivision is specified.""" + self.assertIn( + "Transfer Day", + self.holidays.get_list(date(2020, MAR, 31)), + ) + + def test_aliases(self): + """For coverage purposes""" + for h in [ + holidays.VI(), + holidays.VIR(), + holidays.UnitedStatesVirginIslands(), + ]: + self.assertIsInstance(h, holidays.HolidaysVI) diff --git a/test/countries/test_uruguay.py b/tests/countries/test_uruguay.py similarity index 86% rename from test/countries/test_uruguay.py rename to tests/countries/test_uruguay.py index 2558f3bef..3aef0edb7 100644 --- a/test/countries/test_uruguay.py +++ b/tests/countries/test_uruguay.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -32,8 +31,8 @@ def test_new_years(self): for year in range(1900, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual(self.holidays[dt], "Año Nuevo [New Year's Day]") def test_labor_day(self): @@ -45,8 +44,8 @@ def test_labor_day(self): for year in range(1900, 2100): dt = date(year, 5, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Día de los Trabajadores [International Workers' Day]", @@ -56,8 +55,8 @@ def test_jura_de_la_constitucion_day(self): for year in range(1900, 2100): dt = date(year, 7, 18) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Jura de la Constitución [Constitution Day]" ) @@ -66,8 +65,8 @@ def test_declaratoria_de_la_independencia_day(self): for year in range(1900, 2100): dt = date(year, 8, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Día de la Independencia [Independence Day]" ) @@ -76,8 +75,8 @@ def test_christmas(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Día de la Familia [Day of the Family]" ) @@ -97,8 +96,8 @@ def test_natalicio_artigas_day(self): for year in range(1900, 2100): dt = date(year, 6, 19) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Natalicio de José Gervasio Artigas " @@ -109,8 +108,8 @@ def test_dia_de_los_difuntos_day(self): for year in range(1900, 2100): dt = date(year, 11, 2) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) self.assertEqual( self.holidays[dt], "Día de los Difuntos [All Souls' Day]" ) diff --git a/test/countries/test_uzbekistan.py b/tests/countries/test_uzbekistan.py similarity index 100% rename from test/countries/test_uzbekistan.py rename to tests/countries/test_uzbekistan.py diff --git a/test/countries/test_vatican_city.py b/tests/countries/test_vatican_city.py similarity index 98% rename from test/countries/test_vatican_city.py rename to tests/countries/test_vatican_city.py index bd1f16c79..06e2ebade 100644 --- a/test/countries/test_vatican_city.py +++ b/tests/countries/test_vatican_city.py @@ -10,7 +10,7 @@ # License: MIT (see LICENSE file) from holidays.countries.vatican_city import VA, VAT, VaticanCity -from test.common import TestCase +from tests.common import TestCase class TestVaticanCity(TestCase): diff --git a/test/countries/test_venezuela.py b/tests/countries/test_venezuela.py similarity index 98% rename from test/countries/test_venezuela.py rename to tests/countries/test_venezuela.py index dec4f1e21..eb87b5a7c 100644 --- a/test/countries/test_venezuela.py +++ b/tests/countries/test_venezuela.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, OCT, DEC @@ -25,7 +24,7 @@ def setUp(self): def _check_all_dates(self, year, expected_holidays): start_date = date(year, 1, 1) end_date = date(year, 12, 31) - delta = rd(days=+1) + delta = td(days=+1) while start_date <= end_date: if start_date in expected_holidays: diff --git a/test/countries/test_vietnam.py b/tests/countries/test_vietnam.py similarity index 95% rename from test/countries/test_vietnam.py rename to tests/countries/test_vietnam.py index 039c83f3c..f6f9a37e9 100644 --- a/test/countries/test_vietnam.py +++ b/tests/countries/test_vietnam.py @@ -10,11 +10,10 @@ # License: MIT (see LICENSE file) from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td from holidays.countries.vietnam import Vietnam, VN, VNM -from test.common import TestCase +from tests.common import TestCase class TestVietnam(TestCase): @@ -56,7 +55,7 @@ def test_lunar_new_year(self): ): self.assertHolidaysName( "Vietnamese New Year's Eve", - date(*dt) + rd(days=-1), + date(*dt) + td(days=-1), ) self.assertHolidaysName( "Vietnamese New Year", @@ -64,19 +63,19 @@ def test_lunar_new_year(self): ) self.assertHolidaysName( "The second day of Tet Holiday", - date(*dt) + rd(days=+1), + date(*dt) + td(days=+1), ) self.assertHolidaysName( "The third day of Tet Holiday", - date(*dt) + rd(days=+2), + date(*dt) + td(days=+2), ) self.assertHolidaysName( "The forth day of Tet Holiday", - date(*dt) + rd(days=+3), + date(*dt) + td(days=+3), ) self.assertHolidaysName( "The fifth day of Tet Holiday", - date(*dt) + rd(days=+4), + date(*dt) + td(days=+4), ) def test_king_hung_day(self): diff --git a/tests/countries/test_zambia.py b/tests/countries/test_zambia.py new file mode 100644 index 000000000..9886fee3e --- /dev/null +++ b/tests/countries/test_zambia.py @@ -0,0 +1,147 @@ +# 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.zambia import Zambia, ZM, ZMB +from tests.common import TestCase + + +class TestZambia(TestCase): + def setUp(self): + self.holidays = Zambia() + self.holidays_no_observed = Zambia(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Zambia, ZM, ZMB) + + def test_no_holidays(self): + self.assertNoHolidays(Zambia(years=1964)) + + def test_special_holidays(self): + self.assertHoliday( + "2016-08-11", + "2016-09-13", + "2018-03-09", + "2018-07-26", + "2021-07-02", + "2021-07-07", + "2021-08-12", + "2021-08-13", + "2021-08-24", + "2022-03-18", + ) + + def test_holidays(self): + for year in range(1965, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-03-12", + f"{year}-05-01", + f"{year}-05-25", + f"{year}-10-24", + f"{year}-12-25", + ) + + self.assertNoHoliday(f"{year}-03-08" for year in range(1965, 1991)) + self.assertNoHolidayName( + "International Women's Day", Zambia(years=range(1965, 1991)) + ) + self.assertHoliday(f"{year}-03-08" for year in range(1991, 2050)) + + self.assertNoHoliday(f"{year}-04-28" for year in range(1965, 2022)) + self.assertNoHolidayName( + "Kenneth Kaunda Day", Zambia(years=range(1965, 2022)) + ) + self.assertHoliday(f"{year}-04-28" for year in range(2022, 2050)) + + self.assertNoHoliday(f"{year}-10-18" for year in range(1965, 2015)) + self.assertNoHolidayName( + "National Prayer Day", Zambia(years=range(1965, 2015)) + ) + self.assertHoliday(f"{year}-10-18" for year in range(2015, 2050)) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Holy Saturday + "2018-03-31", + "2019-04-20", + "2020-04-11", + "2021-04-03", + "2022-04-16", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + ) + + def test_moving_holidays(self): + self.assertHoliday( + # Heroes' Day + "2018-07-02", + "2019-07-01", + "2020-07-06", + "2021-07-05", + "2022-07-04", + # Unity Day + "2018-07-03", + "2019-07-02", + "2020-07-07", + "2021-07-06", + "2022-07-05", + # Farmers' Day + "2018-08-06", + "2019-08-05", + "2020-08-03", + "2021-08-02", + "2022-08-01", + ) + + def test_observed(self): + dt = ( + "2000-03-13", + "2003-05-26", + "2004-10-25", + "2005-05-02", + "2005-12-26", + "2006-01-02", + "2006-03-13", + "2008-05-26", + "2009-03-09", + "2010-10-25", + "2011-05-02", + "2011-12-26", + "2012-01-02", + "2014-05-26", + "2015-03-09", + "2015-10-19", + "2016-05-02", + "2016-12-26", + "2017-01-02", + "2017-03-13", + "2020-03-09", + "2020-10-19", + "2021-10-25", + "2022-05-02", + "2022-12-26", + "2023-01-02", + "2023-03-13", + "2024-04-29", + "2030-04-29", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Zambia(observed=False), dt) diff --git a/tests/countries/test_zimbabwe.py b/tests/countries/test_zimbabwe.py new file mode 100644 index 000000000..2d02dfce9 --- /dev/null +++ b/tests/countries/test_zimbabwe.py @@ -0,0 +1,119 @@ +# 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.zimbabwe import Zimbabwe, ZW, ZWE +from tests.common import TestCase + + +class TestZimbabwe(TestCase): + def setUp(self): + self.holidays = Zimbabwe() + self.holidays_no_observed = Zimbabwe(observed=False) + + def test_country_aliases(self): + self.assertCountryAliases(Zimbabwe, ZW, ZWE) + + def test_no_holidays(self): + self.assertNoHolidays(Zimbabwe(years=1987)) + + def test_holidays(self): + for year in range(1988, 2050): + self.assertHoliday( + f"{year}-01-01", + f"{year}-04-18", + f"{year}-05-01", + f"{year}-05-25", + f"{year}-12-22", + f"{year}-12-25", + f"{year}-12-26", + ) + + self.assertNoHoliday(f"{year}-02-21" for year in range(1988, 2018)) + self.assertNoHolidayName( + "Robert Gabriel Mugabe National Youth Day", + Zimbabwe(years=range(1988, 2018)), + ) + self.assertHoliday(f"{year}-02-21" for year in range(2018, 2050)) + + def test_easter(self): + self.assertHoliday( + # Good Friday + "2018-03-30", + "2019-04-19", + "2020-04-10", + "2021-04-02", + "2022-04-15", + # Holy Saturday + "2018-03-31", + "2019-04-20", + "2020-04-11", + "2021-04-03", + "2022-04-16", + # Easter Monday + "2018-04-02", + "2019-04-22", + "2020-04-13", + "2021-04-05", + "2022-04-18", + ) + + def test_moving_holidays(self): + self.assertHoliday( + # Zimbabwe Heroes' Day + "2018-08-13", + "2019-08-12", + "2020-08-10", + "2021-08-09", + "2022-08-08", + # Defense Forces Day + "2018-08-14", + "2019-08-13", + "2020-08-11", + "2021-08-10", + "2022-08-09", + ) + + def test_observed(self): + dt = ( + "2002-12-23", + "2003-05-26", + "2004-04-19", + "2004-12-27", + "2005-05-02", + "2005-12-27", + "2006-01-02", + "2008-05-26", + "2010-04-19", + "2010-12-27", + "2011-05-02", + "2011-12-27", + "2012-01-02", + "2013-12-23", + "2014-05-26", + "2016-05-02", + "2016-12-27", + "2017-01-02", + "2019-12-23", + "2021-02-22", + "2021-04-19", + "2021-12-27", + "2022-05-02", + "2022-12-27", + "2023-01-02", + "2024-12-23", + "2027-02-22", + # special cases + "2049-04-20", + "2055-04-20", + "2060-04-20", + ) + self.assertHoliday(dt) + self.assertNoHoliday(Zimbabwe(observed=False), dt) diff --git a/test/financial/__init__.py b/tests/financial/__init__.py similarity index 100% rename from test/financial/__init__.py rename to tests/financial/__init__.py diff --git a/test/financial/test_european_central_bank.py b/tests/financial/test_european_central_bank.py similarity index 82% rename from test/financial/test_european_central_bank.py rename to tests/financial/test_european_central_bank.py index 262a06cb9..5aef2bdf1 100644 --- a/test/financial/test_european_central_bank.py +++ b/tests/financial/test_european_central_bank.py @@ -11,8 +11,7 @@ import unittest from datetime import date - -from dateutil.relativedelta import relativedelta as rd +from datetime import timedelta as td import holidays @@ -25,7 +24,7 @@ def test_new_years(self): for year in range(1974, 2100): dt = date(year, 1, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) def test_good_friday(self): for dt in [ @@ -40,8 +39,8 @@ def test_good_friday(self): date(2020, 4, 10), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_easter_monday(self): for dt in [ @@ -56,27 +55,27 @@ def test_easter_monday(self): date(2020, 4, 13), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_labour_day(self): for year in range(1900, 2100): dt = date(year, 5, 1) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_christmas_day(self): for year in range(1900, 2100): dt = date(year, 12, 25) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) def test_26_december_day(self): for year in range(1900, 2100): dt = date(year, 12, 26) self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_all_holidays_present(self): tar_2015 = holidays.TAR(years=[2015]) diff --git a/test/financial/test_ny_stock_exchange.py b/tests/financial/test_ny_stock_exchange.py similarity index 80% rename from test/financial/test_ny_stock_exchange.py rename to tests/financial/test_ny_stock_exchange.py index b6eb09d8a..daac66f6c 100644 --- a/test/financial/test_ny_stock_exchange.py +++ b/tests/financial/test_ny_stock_exchange.py @@ -11,9 +11,9 @@ import unittest from datetime import date +from datetime import timedelta as td from dateutil.relativedelta import WE -from dateutil.relativedelta import relativedelta as rd import holidays from holidays.constants import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP @@ -40,9 +40,9 @@ def test_new_years(self): date(2027, DEC, 31), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) def test_mlk(self): for dt in [ @@ -56,10 +56,10 @@ def test_mlk(self): date(2022, JAN, 17), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1997, JAN, 20), @@ -75,10 +75,10 @@ def test_lincoln(self): date(1968, FEB, 12), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1954, FEB, 12), @@ -110,10 +110,10 @@ def test_washington(self): date(2022, FEB, 21), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) def test_good_friday(self): for dt in [ @@ -130,10 +130,10 @@ def test_good_friday(self): date(2022, APR, 15), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) def test_memday(self): for dt in [ @@ -154,10 +154,10 @@ def test_memday(self): date(2022, MAY, 30), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) def test_flagday(self): for dt in [ @@ -169,10 +169,10 @@ def test_flagday(self): date(1953, JUN, 15), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1954, JUN, 14), @@ -187,10 +187,10 @@ def test_juneteenth(self): date(2022, JUN, 20), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1954, JUN, 18), @@ -214,10 +214,10 @@ def test_laborday(self): date(2022, SEP, 5), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1886, SEP, 6), @@ -234,10 +234,10 @@ def test_columbusday(self): date(1953, OCT, 12), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1908, OCT, 12), @@ -260,9 +260,9 @@ def test_electionday(self): date(1980, NOV, 4), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1969, NOV, 4), @@ -292,10 +292,10 @@ def test_veteransday(self): date(1953, NOV, 11), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) for dt in [ date(1917, NOV, 12), @@ -324,10 +324,10 @@ def test_thxgiving(self): date(2022, NOV, 24), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=+7), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+7), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) def test_christmas_day(self): for dt in [ @@ -344,9 +344,9 @@ def test_christmas_day(self): date(2022, DEC, 26), ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) - self.assertNotIn(dt + rd(days=-7), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) + self.assertNotIn(dt + td(days=-7), self.holidays) def test_special_holidays(self): # add to this list as new historical holidays are added @@ -420,7 +420,7 @@ def test_special_holidays(self): def _make_special_holiday_list(begin, end, days=None, weekends=False): _list = [] for d in ( - begin + rd(days=n) for n in range((end - begin).days + 1) + begin + td(days=n) for n in range((end - begin).days + 1) ): if not weekends and d.weekday() in {SAT, SUN}: continue @@ -453,14 +453,14 @@ def _make_special_holiday_list(begin, end, days=None, weekends=False): date(1968, JUN, 12), # begin paper crisis holidays ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=-1), self.holidays) + self.assertNotIn(dt + td(days=-1), self.holidays) for dt in [ date(1914, NOV, 27), # end WWI holidays date(1933, MAR, 14), # end oneoff bank holidays ]: self.assertIn(dt, self.holidays) - self.assertNotIn(dt + rd(days=+1), self.holidays) + self.assertNotIn(dt + td(days=+1), self.holidays) def test_all_modern_holidays_present(self): nyse_2021 = holidays.NewYorkStockExchange(years=[2021]) diff --git a/test/test_docs.py b/tests/test_docs.py similarity index 70% rename from test/test_docs.py rename to tests/test_docs.py index 9caf89fec..1f02b8ab0 100644 --- a/test/test_docs.py +++ b/tests/test_docs.py @@ -10,9 +10,9 @@ # License: MIT (see LICENSE file) import re +from unittest import TestCase from holidays import country_holidays, list_supported_countries -from test.common import TestCase class TestReadme(TestCase): @@ -27,7 +27,7 @@ def test_supported_countries_count(self): actual_country_count = len(list_supported_countries(unique=True)) readme_country_count = int( re.findall( - r"We currently support (\d+) countries.", + r"We currently support (\d+) country codes.", self.readme_content, )[0] ) @@ -61,14 +61,16 @@ def test_supported_countries_table(self): # 2nd column. alpha_2_code = table_content[idx + 1].strip(" -") - country_alpha_2_codes.add(alpha_2_code) + if alpha_2_code: + country_alpha_2_codes.add(alpha_2_code) # 3rd column. country_subdivisions[alpha_2_code] = [] subdivisions = table_content[idx + 2].split(".") for subdivision in subdivisions: subdivision_group = subdivision.split(";")[0].strip(" -") - if subdivision_group == "None": # Exclude empty subdivisions. + # Exclude empty subdivisions. + if subdivision_group.startswith("None") or alpha_2_code == "": country_subdivisions[alpha_2_code] = [] continue @@ -87,22 +89,39 @@ def test_supported_countries_table(self): country_names, sorted(country_names), "The supported countries table must be sorted alphabetically by " - "country name.", + "country name.\n" + + "\n".join( + ( + f"{c} != {s}" + for c, s in zip(country_names, sorted(country_names)) + if c != s + ) + ), ) - country_names = set(country_names) + country_names = set(c.split("(the)")[0] for c in country_names) supported_countries = list_supported_countries(unique=True) for country_alpha_2_code in supported_countries: country = country_holidays(country_alpha_2_code) country_name = country.__class__.__base__.__name__ # Make sure country name is shown correctly. - self.assertIn( - country_name.lower(), - country_names, - f"Country class '{country_name}' is not shown correctly " - "in the table.", - ) + if country_name.startswith("Holiday"): + self.assertIn( + country_name[8:], + country_alpha_2_codes, + f"Country class '{country_name}' is not shown correctly " + "in the table.", + ) + else: + self.assertIn( + country_name.lower().replace( + "unitedstates", "unitedstatesofamerica" + ), + country_names, + f"Country class '{country_name}' is not shown correctly " + "in the table.", + ) # Make sure country alpha-2 code is shown correctly. self.assertIn( @@ -117,5 +136,15 @@ def test_supported_countries_table(self): supported_countries[country_alpha_2_code], country_subdivisions[country_alpha_2_code], f"Country class '{country_name}' subdivisions are not " - "shown correctly in the table.", + "shown correctly in the table.\n" + + "\n".join( + ( + f"{c} != {s}" + for c, s in zip( + supported_countries[country_alpha_2_code], + country_subdivisions[country_alpha_2_code], + ) + if c != s + ) + ), ) diff --git a/test/test_holiday_base.py b/tests/test_holiday_base.py similarity index 84% rename from test/test_holiday_base.py rename to tests/test_holiday_base.py index c9d040851..16e9580dc 100644 --- a/test/test_holiday_base.py +++ b/tests/test_holiday_base.py @@ -9,11 +9,13 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) +import os import pathlib import pickle import unittest import warnings -from datetime import date, datetime, timedelta +from datetime import date, datetime +from datetime import timedelta as td from dateutil.relativedelta import MO from dateutil.relativedelta import relativedelta as rd @@ -76,21 +78,15 @@ def test_getitem(self): self.holidays[date(2013, 12, 31) : date(2014, 1, 2) : -3], [] ) self.assertListEqual( - self.holidays[ - date(2014, 1, 1) : date(2013, 12, 24) : timedelta(days=3) - ], + self.holidays[date(2014, 1, 1) : date(2013, 12, 24) : td(days=3)], [date(2014, 1, 1)], ) self.assertListEqual( - self.holidays[ - date(2014, 1, 1) : date(2013, 12, 24) : timedelta(days=7) - ], + self.holidays[date(2014, 1, 1) : date(2013, 12, 24) : td(days=7)], [date(2014, 1, 1), date(2013, 12, 25)], ) self.assertListEqual( - self.holidays[ - date(2013, 12, 31) : date(2014, 1, 2) : timedelta(days=3) - ], + self.holidays[date(2013, 12, 31) : date(2014, 1, 2) : td(days=3)], [], ) self.assertRaises( @@ -143,8 +139,8 @@ def test_str(self): self.holidays = holidays.US() self.assertEqual( str(self.holidays), - "{'observed': True, 'expand': True, 'subdiv': None, " - "'years': set()}", + "{'expand': True, 'language': None, " + "'observed': True, 'subdiv': None, 'years': set()}", ) self.holidays = holidays.US(years=1900) @@ -170,6 +166,19 @@ def test_update(self): self.assertIn("2015-01-01", h) self.assertIn(date(2015, 12, 25), h) + def test_is_leap_year(self): + self.assertTrue(holidays.HolidayBase._is_leap_year(2000)) + self.assertFalse(holidays.HolidayBase._is_leap_year(2100)) + + def test_add_observed_holiday(self): + h = holidays.HolidayBase() + + h._add_observed_holiday("1111-11-11", "Test holiday") + self.assertEqual(h["1111-11-11"], "Test holiday (Observed)") + + h._add_observed_holiday("2222-11-11", "Test holiday", "(Day Off)") + self.assertEqual(h["2222-11-11"], "Test holiday (Day Off)") + def test_is_weekend(self): h = holidays.HolidayBase() @@ -218,16 +227,38 @@ def test_eq_ne(self): ca2 = holidays.CA() ca3 = holidays.Canada(years=[2014]) ca4 = holidays.CA(years=[2014]) + ca5 = holidays.Canada(language="fr") + ca6 = holidays.CA(language="fr") self.assertEqual(us1, us2) self.assertEqual(us3, us4) self.assertEqual(ca1, ca2) self.assertEqual(ca3, ca4) + self.assertEqual(ca5, ca6) self.assertNotEqual(us1, us3) self.assertNotEqual(us1, ca1) self.assertNotEqual(us3, ca3) self.assertNotEqual(us1, us3) + self.assertNotEqual(ca1, ca5) + + self.assertNotEqual(us1, None) + self.assertNotEqual(us1, {}) + self.assertFalse(us1 == {}) - def test_add(self): + def test_copy(self): + us = holidays.UnitedStates() + self.assertEqual(us, us.copy()) + self.assertTrue(us == us.copy()) + + ca = holidays.Canada() + ca_fr = holidays.Canada(language="fr") + ca_xx = holidays.Canada(language="xx") + self.assertNotEqual(ca, ca_fr) + self.assertNotEqual(ca.copy(), ca_fr.copy()) + + self.assertNotEqual(ca, ca_xx) + self.assertNotEqual(ca.copy(), ca_xx.copy()) + + def test_add_countries(self): ca = holidays.CA() us = holidays.US() mx = holidays.MX() @@ -297,18 +328,22 @@ def test_add(self): self.assertEqual(na.get(date(1969, 7, 1)), "Dominion Day") self.assertEqual(na.get(date(1983, 7, 1)), "Canada Day") self.assertEqual( - na.get(date(1969, 12, 25)), "Christmas Day, Navidad [Christmas]" + na.get(date(1969, 12, 25)), "Christmas Day; Navidad [Christmas]" ) na = holidays.MX() + holidays.CA() + holidays.US() self.assertEqual( - na.get(date(1969, 12, 25)), "Christmas Day, Navidad [Christmas]" + na.get(date(1969, 12, 25)), "Christmas Day; Navidad [Christmas]" ) + self.assertEqual(na, na.copy()) + def test_add_financial(self): ecb = holidays.ECB() nyse = holidays.NYSE() ecb_nyse = ecb + nyse self.assertEqual(len(ecb) + len(nyse), len(ecb_nyse)) self.assertEqual(ecb_nyse.market, ["ECB", "NYSE"]) + self.assertEqual(ecb_nyse, ecb_nyse.copy()) + self.assertNotEqual(ecb_nyse, {}) def test_get_list(self): westland = holidays.NZ(subdiv="WTL") @@ -316,7 +351,7 @@ def test_get_list(self): wild = westland + chathams self.assertEqual( wild[date(1969, 12, 1)], - ("Chatham Islands Anniversary Day, West Coast Anniversary Day"), + ("Chatham Islands Anniversary Day; West Coast Anniversary Day"), ) self.assertEqual( @@ -430,8 +465,10 @@ def _populate(self, year): def test_get_named(self): us = holidays.UnitedStates(years=[2020]) + holidays_count = len(us.keys()) # check for "New Year's Day" presence in get_named("new") self.assertIn(date(2020, 1, 1), us.get_named("new")) + self.assertEqual(holidays_count, len(us.keys())) # check for searching holiday in US when the observed holiday is on # a different year than input one @@ -609,121 +646,6 @@ def test_deprecation(self): self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) -class TestCountryHolidays(unittest.TestCase): - def setUp(self): - self.holidays = holidays.country_holidays("US") - - def test_country(self): - self.assertEqual(self.holidays.country, "US") - - def test_country_single_year(self): - h = holidays.country_holidays("US", years=2021) - self.assertEqual(h.years, {2021}) - - def test_country_years(self): - h = holidays.country_holidays("US", years=[2015, 2016]) - self.assertEqual(h.years, {2015, 2016}) - - def test_country_state(self): - h = holidays.country_holidays("US", subdiv="NY") - self.assertEqual(h.subdiv, "NY") - - def test_country_province(self): - h = holidays.country_holidays("AU", subdiv="NT") - self.assertEqual(h.subdiv, "NT") - - def test_exceptions(self): - self.assertRaises( - NotImplementedError, lambda: holidays.country_holidays("XXXX") - ) - self.assertRaises( - NotImplementedError, - lambda: holidays.country_holidays("US", subdiv="XXXX"), - ) - self.assertRaises( - NotImplementedError, lambda: holidays.US(subdiv="XXXX") - ) - - -class TestFinancialHolidays(unittest.TestCase): - def setUp(self): - self.holidays = holidays.financial_holidays("NYSE") - - def test_market(self): - self.assertEqual(self.holidays.market, "NYSE") - - def test_market_single_year(self): - h = holidays.financial_holidays("NYSE", years=2021) - self.assertEqual(h.years, {2021}) - - def test_market_years(self): - h = holidays.financial_holidays("NYSE", years=[2015, 2016]) - self.assertEqual(h.years, {2015, 2016}) - - def test_exceptions(self): - self.assertRaises( - NotImplementedError, lambda: holidays.financial_holidays("XXXX") - ) - self.assertRaises( - NotImplementedError, - lambda: holidays.financial_holidays("NYSE", subdiv="XXXX"), - ) - - -class TestAllInSameYear(unittest.TestCase): - """Test that only holidays in the year(s) requested are returned.""" - - country: str - hol: datetime - year: int - - def setUp(self): - self.countries = holidays.list_supported_countries() - - def tearDown(self): - """https://stackoverflow.com/questions/4414234/""" - - def list2reason(exc_list): - if exc_list and exc_list[-1][0] is self: - return exc_list[-1][1] - - result = self.defaultTestResult() - self._feedErrorsToResult(result, self._outcome.errors) - error = list2reason(result.errors) - failure = list2reason(result.failures) - text = error if error else failure - if text: - warnings.warn( - f"{text.splitlines()[-1]} in country {self.country}: " - f"holiday {self.hol} returned for year {self.year}" - + holidays.country_holidays( - self.country, subdiv=None, years=[self.year] - ).get_list(self.hol) - ) - - def test_all_countries(self): - """ - Only holidays in the year(s) requested should be returned. This - ensures that we avoid triggering a "RuntimeError: dictionary changed - size during iteration" error. - - Here we test all countries for the 12-year period starting ten years - ago and ending 2 years from now. - - This is logic test and not a code compatibility test, so for expediency - we only run it once on the latest Python version. - """ - for self.country in self.countries: - for self.year in range( - date.today().year - 10, date.today().year + 3 - ): - hols = holidays.country_holidays( - self.country, years=[self.year] - ) - for self.hol in hols: - self.assertEqual(self.hol.year, self.year) - - class TestCountrySpecialHolidays(unittest.TestCase): def setUp(self): self.holidays = holidays.country_holidays("US") @@ -749,3 +671,14 @@ def test_populate_special_holidays(self): self.assertIn("1111-01-01", self.holidays) self.assertIn("2222-02-02", self.holidays) self.assertEqual(13, len(self.holidays)) + + +class TestHolidaysTranslation(unittest.TestCase): + def test_language_unavailable(self): + os.environ["LANGUAGE"] = "en_US" + us_xx = holidays.country_holidays("CA", language="xx") + self.assertEqual(us_xx["2022-01-01"], "New Year's Day") + + os.environ["LANGUAGE"] = "pl" + pl_xx = holidays.country_holidays("PL", language="xx") + self.assertEqual(pl_xx["2022-01-01"], "Nowy Rok") diff --git a/test/test_imports.py b/tests/test_imports.py similarity index 97% rename from test/test_imports.py rename to tests/test_imports.py index 801dd8fc7..404f6d3b2 100644 --- a/test/test_imports.py +++ b/tests/test_imports.py @@ -9,8 +9,9 @@ # Website: https://github.com/dr-prodigy/python-holidays # License: MIT (see LICENSE file) +from unittest import TestCase + import holidays -from test.common import TestCase class TestHolidaysImports(TestCase): diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 000000000..43285c93d --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,197 @@ +# 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-2022 +# ryanss (c) 2014-2017 +# Website: https://github.com/dr-prodigy/python-holidays +# License: MIT (see LICENSE file) + +import unittest +import warnings +from datetime import date + +from holidays import utils +from holidays.constants import FEB, MAR, MAY, JUN, JUL, AUG, OCT + + +class TestCountryHolidays(unittest.TestCase): + def setUp(self): + self.holidays = utils.country_holidays("US") + + def test_country(self): + self.assertEqual(self.holidays.country, "US") + + def test_country_single_year(self): + h = utils.country_holidays("US", years=2021) + self.assertEqual(h.years, {2021}) + + def test_country_years(self): + h = utils.country_holidays("US", years=(2015, 2016)) + self.assertEqual(h.years, {2015, 2016}) + + def test_country_state(self): + h = utils.country_holidays("US", subdiv="NY") + self.assertEqual(h.subdiv, "NY") + + def test_country_province(self): + h = utils.country_holidays("AU", subdiv="NT") + self.assertEqual(h.subdiv, "NT") + + def test_exceptions(self): + self.assertRaises( + NotImplementedError, lambda: utils.country_holidays("XXXX") + ) + self.assertRaises( + NotImplementedError, + lambda: utils.country_holidays("US", subdiv="XXXX"), + ) + self.assertRaises( + NotImplementedError, + lambda: utils.country_holidays("US", subdiv="XXXX"), + ) + + +class TestFinancialHolidays(unittest.TestCase): + def setUp(self): + self.holidays = utils.financial_holidays("NYSE") + + def test_market(self): + self.assertEqual(self.holidays.market, "NYSE") + + def test_market_single_year(self): + h = utils.financial_holidays("NYSE", years=2021) + self.assertEqual(h.years, {2021}) + + def test_market_years(self): + h = utils.financial_holidays("NYSE", years=(2015, 2016)) + self.assertEqual(h.years, {2015, 2016}) + + def test_exceptions(self): + self.assertRaises( + NotImplementedError, lambda: utils.financial_holidays("XXXX") + ) + self.assertRaises( + NotImplementedError, + lambda: utils.financial_holidays("NYSE", subdiv="XXXX"), + ) + + +class TestAllInSameYear(unittest.TestCase): + """Test that only holidays in the year(s) requested are returned.""" + + def test_all_countries(self): + """ + Only holidays in the year(s) requested should be returned. This + ensures that we avoid triggering a "RuntimeError: dictionary changed + size during iteration" error. + + Here we test all countries for the 12-year period starting ten years + ago and ending 2 years from now. + + This is logic test and not a code compatibility test, so for expediency + we only run it once on the latest Python version. + """ + warnings.simplefilter("ignore") + for country in utils.list_supported_countries(): + for year in range(date.today().year - 10, date.today().year + 3): + for holiday in utils.country_holidays(country, years=year): + self.assertEqual(holiday.year, year) + + +class TestThaiLuniSolarCalendar(unittest.TestCase): + def setUp(self) -> None: + super().setUpClass() + self.calendar = utils._ThaiLuniSolar() + + def test_asarnha_bucha_date(self): + asarnha_bucha_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, JUL, 13), + 2023: date(2023, AUG, 1), + 2024: date(2024, JUL, 20), + 2025: date(2025, JUL, 10), + } + for year in asarnha_bucha_year_date: + self.assertEqual( + asarnha_bucha_year_date[year], + self.calendar.asarnha_bucha_date(year), + ) + + def test_atthami_bucha_date(self): + atthami_bucha_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, MAY, 23), + 2023: date(2023, JUN, 11), + 2024: date(2024, MAY, 30), + 2025: date(2025, MAY, 19), + } + for year in atthami_bucha_year_date: + self.assertEqual( + atthami_bucha_year_date[year], + self.calendar.atthami_bucha_date(year), + ) + + def test_khao_phansa_date(self): + khao_phansa_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, JUL, 14), + 2023: date(2023, AUG, 2), + 2024: date(2024, JUL, 21), + 2025: date(2025, JUL, 11), + } + for year in khao_phansa_year_date: + self.assertEqual( + khao_phansa_year_date[year], + self.calendar.khao_phansa_date(year), + ) + + def test_makha_bucha_date(self): + makha_bucha_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, FEB, 16), + 2023: date(2023, MAR, 6), + 2024: date(2024, FEB, 24), + 2025: date(2025, FEB, 12), + } + for year in makha_bucha_year_date: + self.assertEqual( + makha_bucha_year_date[year], + self.calendar.makha_bucha_date(year), + ) + + def test_ok_phansa_date(self): + ok_phansa_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, OCT, 10), + 2023: date(2023, OCT, 29), + 2024: date(2024, OCT, 17), + 2025: date(2025, OCT, 7), + } + for year in ok_phansa_year_date: + self.assertEqual( + ok_phansa_year_date[year], + self.calendar.ok_phansa_date(year), + ) + + def test_visakha_bucha_date(self): + visakha_bucha_year_date = { + self.calendar.START_YEAR - 1: None, + self.calendar.END_YEAR + 1: None, + 2022: date(2022, MAY, 15), + 2023: date(2023, JUN, 3), + 2024: date(2024, MAY, 22), + 2025: date(2025, MAY, 11), + } + for year in visakha_bucha_year_date: + self.assertEqual( + visakha_bucha_year_date[year], + self.calendar.visakha_bucha_date(year), + ) diff --git a/tox.ini b/tox.ini index 3a1975434..5773ac3c3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,43 +1,42 @@ [pytest] -addopts = - --cov=. - --cov-config=pyproject.toml - --cov-report term - --cov-report xml - --no-cov-on-fail +filterwarnings = + # xdist/plugin.py:227 + ignore:The --rsyncdir .* are deprecated:DeprecationWarning [testenv] commands = pytest deps = - -r{toxinidir}/requirements_dev.txt + -r{toxinidir}/requirements/dev.txt [testenv:docs] # Test docs. -# We run it in Python 3.9 to match +# We run it in Python 3.11 to match # https://docs.readthedocs.io/en/stable/config-file/v2.html?#build-image allowlist_externals = cmd + make sphinx-build -basepython = python3.9 +basepython = python3.11 commands = - sphinx-build -W -j auto docs/source docs/_build + make doc deps = - -r{toxinidir}/requirements_dev.txt - -r{toxinidir}/docs/requirements.txt + -r{toxinidir}/requirements/dev.txt + -r{toxinidir}/requirements/docs.txt [testenv:pre-commit] basepython = python commands = pre-commit autoupdate - pre-commit run -a + pre-commit run --all-files deps = pre-commit [tox] envlist = - py{37,38,39,310,py3} - pre-commit docs + pre-commit + python3.{7,8,9,10,11} +isoleted_build = true minversion = 3.24.5 skip_missing_interpreters = true