holidays 0.66__py3-none-any.whl → 0.67__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- holidays/countries/__init__.py +2 -0
- holidays/countries/australia.py +6 -6
- holidays/countries/cambodia.py +1 -1
- holidays/countries/chile.py +1 -1
- holidays/countries/cuba.py +1 -1
- holidays/countries/denmark.py +1 -1
- holidays/countries/finland.py +19 -19
- holidays/countries/greenland.py +22 -19
- holidays/countries/guatemala.py +1 -1
- holidays/countries/haiti.py +3 -3
- holidays/countries/hongkong.py +124 -174
- holidays/countries/isle_of_man.py +15 -11
- holidays/countries/kazakhstan.py +1 -1
- holidays/countries/laos.py +2 -2
- holidays/countries/nicaragua.py +1 -1
- holidays/countries/panama.py +69 -31
- holidays/countries/peru.py +1 -1
- holidays/countries/saint_lucia.py +88 -0
- holidays/countries/seychelles.py +4 -4
- holidays/countries/singapore.py +1 -1
- holidays/countries/spain.py +9 -9
- holidays/countries/sri_lanka.py +1 -1
- holidays/countries/switzerland.py +1 -1
- holidays/countries/tuvalu.py +174 -0
- holidays/countries/united_kingdom.py +72 -56
- holidays/countries/united_states.py +141 -10
- holidays/countries/uruguay.py +1 -1
- holidays/financial/brasil_bolsa_balcao.py +1 -1
- holidays/holiday_base.py +62 -13
- holidays/locale/da/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/en_GB/LC_MESSAGES/GB.mo +0 -0
- holidays/locale/en_GB/LC_MESSAGES/IM.mo +0 -0
- holidays/locale/en_GB/LC_MESSAGES/TV.mo +0 -0
- holidays/locale/en_HK/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/en_LC/LC_MESSAGES/LC.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/AR.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CH.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CL.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CO.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CU.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/DK.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/FI.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/GB.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/GT.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/HT.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/IM.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/KH.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/KZ.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/LA.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/LC.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/LK.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/NI.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/PA.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/PE.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/RU.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/SC.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/TV.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/UY.mo +0 -0
- holidays/locale/es/LC_MESSAGES/PA.mo +0 -0
- holidays/locale/fi/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/is/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/kl/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/no/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/sv/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/th/LC_MESSAGES/GB.mo +0 -0
- holidays/locale/th/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/th/LC_MESSAGES/IM.mo +0 -0
- holidays/locale/tvl/LC_MESSAGES/TV.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/CR.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/DK.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/GE.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/GL.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/MC.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/MG.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/PA.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/RO.mo +0 -0
- holidays/locale/zh_CN/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/zh_HK/LC_MESSAGES/HK.mo +0 -0
- holidays/registry.py +2 -0
- holidays/version.py +1 -1
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/AUTHORS +1 -0
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/METADATA +33 -17
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/RECORD +90 -64
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/LICENSE +0 -0
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/WHEEL +0 -0
- {holidays-0.66.dist-info → holidays-0.67.dist-info}/top_level.txt +0 -0
holidays/holiday_base.py
CHANGED
|
@@ -14,13 +14,14 @@ __all__ = ("DateLike", "HolidayBase", "HolidaySum")
|
|
|
14
14
|
|
|
15
15
|
import copy
|
|
16
16
|
import warnings
|
|
17
|
+
from bisect import bisect_left, bisect_right
|
|
17
18
|
from calendar import isleap
|
|
18
19
|
from collections.abc import Iterable
|
|
19
20
|
from datetime import date, datetime, timedelta, timezone
|
|
20
21
|
from functools import cached_property
|
|
21
22
|
from gettext import gettext, translation
|
|
22
23
|
from pathlib import Path
|
|
23
|
-
from typing import Any,
|
|
24
|
+
from typing import Any, Literal, Optional, Union, cast
|
|
24
25
|
|
|
25
26
|
from dateutil.parser import parse
|
|
26
27
|
|
|
@@ -249,6 +250,8 @@ class HolidayBase(dict[date, str]):
|
|
|
249
250
|
"""Start year of holidays presence for this entity."""
|
|
250
251
|
end_year: int = DEFAULT_END_YEAR
|
|
251
252
|
"""End year of holidays presence for this entity."""
|
|
253
|
+
parent_entity: Optional[type["HolidayBase"]] = None
|
|
254
|
+
"""Optional parent entity to reference as a base."""
|
|
252
255
|
|
|
253
256
|
def __init__(
|
|
254
257
|
self,
|
|
@@ -364,16 +367,32 @@ class HolidayBase(dict[date, str]):
|
|
|
364
367
|
self.weekend_workdays = getattr(self, "weekend_workdays", set())
|
|
365
368
|
|
|
366
369
|
supported_languages = set(self.supported_languages)
|
|
367
|
-
self.
|
|
368
|
-
|
|
370
|
+
if self._entity_code is not None:
|
|
371
|
+
fallback = language not in supported_languages
|
|
372
|
+
languages = [language] if language in supported_languages else None
|
|
373
|
+
locale_directory = str(Path(__file__).with_name("locale"))
|
|
374
|
+
|
|
375
|
+
# Add entity native content translations.
|
|
376
|
+
entity_translation = translation(
|
|
369
377
|
self._entity_code,
|
|
370
|
-
fallback=
|
|
371
|
-
languages=
|
|
372
|
-
localedir=
|
|
373
|
-
)
|
|
374
|
-
if
|
|
375
|
-
|
|
376
|
-
|
|
378
|
+
fallback=fallback,
|
|
379
|
+
languages=languages,
|
|
380
|
+
localedir=locale_directory,
|
|
381
|
+
)
|
|
382
|
+
# Add a fallback if entity has parent translations.
|
|
383
|
+
if parent_entity := self.parent_entity:
|
|
384
|
+
entity_translation.add_fallback(
|
|
385
|
+
translation(
|
|
386
|
+
parent_entity.country or parent_entity.market,
|
|
387
|
+
fallback=fallback,
|
|
388
|
+
languages=languages,
|
|
389
|
+
localedir=locale_directory,
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
self.tr = entity_translation.gettext
|
|
393
|
+
else:
|
|
394
|
+
self.tr = gettext
|
|
395
|
+
|
|
377
396
|
self.years = _normalize_arguments(int, years)
|
|
378
397
|
|
|
379
398
|
# Populate holidays.
|
|
@@ -418,7 +437,7 @@ class HolidayBase(dict[date, str]):
|
|
|
418
437
|
if not isinstance(key, (date, datetime, float, int, str)):
|
|
419
438
|
raise TypeError(f"Cannot convert type '{type(key)}' to date.")
|
|
420
439
|
|
|
421
|
-
return dict.__contains__(cast("
|
|
440
|
+
return dict.__contains__(cast("dict[Any, Any]", self), self.__keytransform__(key))
|
|
422
441
|
|
|
423
442
|
def __eq__(self, other: object) -> bool:
|
|
424
443
|
if not isinstance(other, HolidayBase):
|
|
@@ -428,7 +447,7 @@ class HolidayBase(dict[date, str]):
|
|
|
428
447
|
if getattr(self, attribute_name, None) != getattr(other, attribute_name, None):
|
|
429
448
|
return False
|
|
430
449
|
|
|
431
|
-
return dict.__eq__(cast("
|
|
450
|
+
return dict.__eq__(cast("dict[Any, Any]", self), other)
|
|
432
451
|
|
|
433
452
|
def __getattr__(self, name):
|
|
434
453
|
try:
|
|
@@ -967,6 +986,36 @@ class HolidayBase(dict[date, str]):
|
|
|
967
986
|
|
|
968
987
|
raise AttributeError(f"Unknown lookup type: {lookup}")
|
|
969
988
|
|
|
989
|
+
def get_closest_holiday(
|
|
990
|
+
self,
|
|
991
|
+
target_date: DateLike = None,
|
|
992
|
+
direction: Literal["forward", "backward"] = "forward",
|
|
993
|
+
) -> Optional[tuple[date, str]]:
|
|
994
|
+
"""Return the date and name of the next holiday for a target_date
|
|
995
|
+
if direction is "forward" or the previous holiday if direction is "backward".
|
|
996
|
+
If target_date is not provided the current date will be used by default."""
|
|
997
|
+
|
|
998
|
+
if direction not in {"backward", "forward"}:
|
|
999
|
+
raise AttributeError(f"Unknown direction: {direction}")
|
|
1000
|
+
|
|
1001
|
+
dt = self.__keytransform__(target_date or datetime.now().date())
|
|
1002
|
+
if direction == "forward" and (next_year := dt.year + 1) not in self.years:
|
|
1003
|
+
self._populate(next_year)
|
|
1004
|
+
elif direction == "backward" and (previous_year := dt.year - 1) not in self.years:
|
|
1005
|
+
self._populate(previous_year)
|
|
1006
|
+
|
|
1007
|
+
sorted_dates = sorted(self.keys())
|
|
1008
|
+
position = (
|
|
1009
|
+
bisect_right(sorted_dates, dt)
|
|
1010
|
+
if direction == "forward"
|
|
1011
|
+
else bisect_left(sorted_dates, dt) - 1
|
|
1012
|
+
)
|
|
1013
|
+
if 0 <= position < len(sorted_dates):
|
|
1014
|
+
dt = sorted_dates[position]
|
|
1015
|
+
return dt, self[dt]
|
|
1016
|
+
|
|
1017
|
+
return None
|
|
1018
|
+
|
|
970
1019
|
def get_nth_working_day(self, key: DateLike, n: int) -> date:
|
|
971
1020
|
"""Return n-th working day from provided date (if n is positive)
|
|
972
1021
|
or n-th working day before provided date (if n is negative).
|
|
@@ -1201,4 +1250,4 @@ country_holidays('CA') + country_holidays('MX')
|
|
|
1201
1250
|
def _populate(self, year):
|
|
1202
1251
|
for operand in self.holidays:
|
|
1203
1252
|
operand._populate(year)
|
|
1204
|
-
self.update(cast("
|
|
1253
|
+
self.update(cast("dict[DateLike, str]", operand))
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
holidays/registry.py
CHANGED
|
@@ -142,6 +142,7 @@ COUNTRIES: RegistryDict = {
|
|
|
142
142
|
"romania": ("Romania", "RO", "ROU"),
|
|
143
143
|
"russia": ("Russia", "RU", "RUS"),
|
|
144
144
|
"saint_kitts_and_nevis": ("SaintKittsAndNevis", "KN", "KNA"),
|
|
145
|
+
"saint_lucia": ("SaintLucia", "LC", "LCA"),
|
|
145
146
|
"samoa": ("Samoa", "WS", "WSM"),
|
|
146
147
|
"san_marino": ("SanMarino", "SM", "SMR"),
|
|
147
148
|
"saudi_arabia": ("SaudiArabia", "SA", "SAU"),
|
|
@@ -163,6 +164,7 @@ COUNTRIES: RegistryDict = {
|
|
|
163
164
|
"tonga": ("Tonga", "TO", "TON"),
|
|
164
165
|
"tunisia": ("Tunisia", "TN", "TUN"),
|
|
165
166
|
"turkey": ("Turkey", "TR", "TUR"),
|
|
167
|
+
"tuvalu": ("Tuvalu", "TV", "TUV"),
|
|
166
168
|
"ukraine": ("Ukraine", "UA", "UKR"),
|
|
167
169
|
"united_arab_emirates": ("UnitedArabEmirates", "AE", "ARE"),
|
|
168
170
|
"united_kingdom": ("UnitedKingdom", "GB", "GBR", "UK"),
|
holidays/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: holidays
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.67
|
|
4
4
|
Summary: Open World Holidays Framework
|
|
5
5
|
Author: Vacanza Team
|
|
6
6
|
Maintainer: Arkadii Yakovets, Panpakorn Siripanich, Serhii Murza
|
|
@@ -96,15 +96,21 @@ flexible as possible.
|
|
|
96
96
|
:target: https://github.com/vacanza/holidays/commits/dev
|
|
97
97
|
:alt: GitHub last commit
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
|
105
|
-
|
|
106
|
-
|
|
|
107
|
-
|
|
99
|
+
.. |doi| image:: https://img.shields.io/badge/DOI-10.5281/zenodo.14847397-41B5BE?style=flat
|
|
100
|
+
:target: https://doi.org/10.5281/zenodo.14847397
|
|
101
|
+
:alt: Open World Holidays Franework DOI
|
|
102
|
+
|
|
103
|
+
+----------+------------------------------------------------+
|
|
104
|
+
| PyPI | |downloads| |version| |release date| |
|
|
105
|
+
+----------+------------------------------------------------+
|
|
106
|
+
| CI/CD | |status| |documentation| |
|
|
107
|
+
+----------+------------------------------------------------+
|
|
108
|
+
| Code | |license| |python versions| |style| |coverage| |
|
|
109
|
+
+----------+------------------------------------------------+
|
|
110
|
+
| GitHub | |stars| |forks| |contributors| |last commit| |
|
|
111
|
+
+----------+------------------------------------------------+
|
|
112
|
+
| Citation | |doi| |
|
|
113
|
+
+----------+------------------------------------------------+
|
|
108
114
|
|
|
109
115
|
Install
|
|
110
116
|
-------
|
|
@@ -183,7 +189,7 @@ Available Countries
|
|
|
183
189
|
.. _ISO 639-1 code: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
|
184
190
|
.. _ISO 639-2 code: https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
|
|
185
191
|
|
|
186
|
-
We currently support
|
|
192
|
+
We currently support 159 country codes. The standard way to refer to a country
|
|
187
193
|
is by using its `ISO 3166-1 alpha-2 code`_, the same used for domain names, and
|
|
188
194
|
for a subdivision its `ISO 3166-2 code`_. Some countries have common or foreign
|
|
189
195
|
names or abbreviations as aliases for their subdivisions. These are defined in
|
|
@@ -510,7 +516,7 @@ All other default values are highlighted with bold:
|
|
|
510
516
|
* - Greenland
|
|
511
517
|
- GL
|
|
512
518
|
-
|
|
513
|
-
- da, en_US, **kl
|
|
519
|
+
- da, en_US, fi, is, **kl**, no, sv, uk
|
|
514
520
|
- OPTIONAL
|
|
515
521
|
* - Guam
|
|
516
522
|
- GU
|
|
@@ -540,7 +546,7 @@ All other default values are highlighted with bold:
|
|
|
540
546
|
* - Hong Kong
|
|
541
547
|
- HK
|
|
542
548
|
-
|
|
543
|
-
-
|
|
549
|
+
- en_HK, en_US, th, zh_CN, **zh_HK**
|
|
544
550
|
- OPTIONAL
|
|
545
551
|
* - Hungary
|
|
546
552
|
- HU
|
|
@@ -575,7 +581,7 @@ All other default values are highlighted with bold:
|
|
|
575
581
|
* - Isle of Man
|
|
576
582
|
- IM
|
|
577
583
|
-
|
|
578
|
-
-
|
|
584
|
+
- **en_GB**, en_US, th
|
|
579
585
|
-
|
|
580
586
|
* - Israel
|
|
581
587
|
- IL
|
|
@@ -775,8 +781,8 @@ All other default values are highlighted with bold:
|
|
|
775
781
|
* - Panama
|
|
776
782
|
- PA
|
|
777
783
|
-
|
|
778
|
-
-
|
|
779
|
-
-
|
|
784
|
+
- en_US, **es**, uk
|
|
785
|
+
- BANK
|
|
780
786
|
* - Papua New Guinea
|
|
781
787
|
- PG
|
|
782
788
|
-
|
|
@@ -827,6 +833,11 @@ All other default values are highlighted with bold:
|
|
|
827
833
|
-
|
|
828
834
|
-
|
|
829
835
|
- HALF_DAY, WORKDAY
|
|
836
|
+
* - Saint Lucia
|
|
837
|
+
- LC
|
|
838
|
+
-
|
|
839
|
+
- **en_LC**, en_US
|
|
840
|
+
-
|
|
830
841
|
* - Samoa
|
|
831
842
|
- WS
|
|
832
843
|
-
|
|
@@ -932,6 +943,11 @@ All other default values are highlighted with bold:
|
|
|
932
943
|
-
|
|
933
944
|
- en_US, **tr**, uk
|
|
934
945
|
- HALF_DAY
|
|
946
|
+
* - Tuvalu
|
|
947
|
+
- TV
|
|
948
|
+
- Town/Island Councils: FUN (Funafuti), NIT (Niutao), NKF (Nukufetau), NKL (Nukulaelae), NMA (Nanumea), NMG (Nanumaga, Nanumanga), NUI (Nui), VAI (Vaitupu)
|
|
949
|
+
- en_GB, en_US, **tvl**
|
|
950
|
+
-
|
|
935
951
|
* - Ukraine
|
|
936
952
|
- UA
|
|
937
953
|
-
|
|
@@ -945,7 +961,7 @@ All other default values are highlighted with bold:
|
|
|
945
961
|
* - United Kingdom
|
|
946
962
|
- GB
|
|
947
963
|
- Subdivisions: ENG (England), NIR (Northern Ireland), SCT (Scotland), WLS (Wales)
|
|
948
|
-
-
|
|
964
|
+
- **en_GB**, en_US, th
|
|
949
965
|
-
|
|
950
966
|
* - United States Minor Outlying Islands
|
|
951
967
|
- UM
|