holidays 0.69__py3-none-any.whl → 0.71__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/__init__.py +1 -1
- holidays/calendars/__init__.py +1 -1
- holidays/calendars/balinese_saka.py +3 -3
- holidays/calendars/buddhist.py +1 -1
- holidays/calendars/chinese.py +1 -1
- holidays/calendars/custom.py +1 -1
- holidays/calendars/gregorian.py +1 -1
- holidays/calendars/hebrew.py +1 -1
- holidays/calendars/hindu.py +1 -1
- holidays/calendars/islamic.py +161 -1
- holidays/calendars/julian.py +1 -1
- holidays/calendars/julian_revised.py +1 -1
- holidays/calendars/persian.py +1 -1
- holidays/calendars/sinhala.py +1 -1
- holidays/calendars/thai.py +309 -257
- holidays/constants.py +2 -1
- holidays/countries/__init__.py +10 -1
- holidays/countries/afghanistan.py +11 -7
- holidays/countries/albania.py +10 -7
- holidays/countries/algeria.py +10 -10
- holidays/countries/american_samoa.py +6 -4
- holidays/countries/andorra.py +5 -4
- holidays/countries/angola.py +15 -14
- holidays/countries/antigua_and_barbuda.py +145 -0
- holidays/countries/argentina.py +787 -169
- holidays/countries/armenia.py +5 -6
- holidays/countries/aruba.py +11 -9
- holidays/countries/australia.py +21 -20
- holidays/countries/austria.py +3 -1
- holidays/countries/azerbaijan.py +24 -19
- holidays/countries/bahamas.py +13 -11
- holidays/countries/bahrain.py +8 -7
- holidays/countries/bangladesh.py +5 -4
- holidays/countries/barbados.py +11 -9
- holidays/countries/belarus.py +15 -15
- holidays/countries/belgium.py +8 -6
- holidays/countries/belize.py +7 -6
- holidays/countries/bolivia.py +12 -11
- holidays/countries/bosnia_and_herzegovina.py +15 -11
- holidays/countries/botswana.py +8 -6
- holidays/countries/brazil.py +8 -7
- holidays/countries/brunei.py +50 -62
- holidays/countries/bulgaria.py +9 -10
- holidays/countries/burkina_faso.py +8 -5
- holidays/countries/burundi.py +13 -12
- holidays/countries/cambodia.py +15 -24
- holidays/countries/cameroon.py +10 -7
- holidays/countries/canada.py +13 -12
- holidays/countries/chad.py +9 -6
- holidays/countries/chile.py +29 -28
- holidays/countries/china.py +39 -38
- holidays/countries/colombia.py +15 -20
- holidays/countries/congo.py +6 -7
- holidays/countries/costa_rica.py +11 -10
- holidays/countries/croatia.py +8 -5
- holidays/countries/cuba.py +30 -27
- holidays/countries/curacao.py +6 -4
- holidays/countries/cyprus.py +4 -5
- holidays/countries/czechia.py +7 -6
- holidays/countries/denmark.py +5 -6
- holidays/countries/djibouti.py +7 -3
- holidays/countries/dominica.py +18 -16
- holidays/countries/dominican_republic.py +6 -4
- holidays/countries/ecuador.py +5 -4
- holidays/countries/egypt.py +6 -11
- holidays/countries/el_salvador.py +6 -5
- holidays/countries/estonia.py +3 -1
- holidays/countries/eswatini.py +6 -4
- holidays/countries/ethiopia.py +20 -11
- holidays/countries/fiji.py +183 -0
- holidays/countries/finland.py +11 -10
- holidays/countries/france.py +7 -10
- holidays/countries/french_southern_territories.py +53 -0
- holidays/countries/gabon.py +11 -8
- holidays/countries/georgia.py +7 -7
- holidays/countries/germany.py +11 -11
- holidays/countries/ghana.py +10 -6
- holidays/countries/greece.py +4 -5
- holidays/countries/greenland.py +5 -6
- holidays/countries/guam.py +6 -4
- holidays/countries/guatemala.py +7 -9
- holidays/countries/guernsey.py +37 -34
- holidays/countries/guinea.py +182 -0
- holidays/countries/haiti.py +6 -5
- holidays/countries/honduras.py +8 -4
- holidays/countries/hongkong.py +11 -8
- holidays/countries/hungary.py +26 -23
- holidays/countries/iceland.py +5 -4
- holidays/countries/india.py +14 -10
- holidays/countries/indonesia.py +57 -53
- holidays/countries/iran.py +12 -9
- holidays/countries/ireland.py +5 -4
- holidays/countries/isle_of_man.py +2 -2
- holidays/countries/israel.py +4 -5
- holidays/countries/italy.py +5 -4
- holidays/countries/ivory_coast.py +156 -0
- holidays/countries/jamaica.py +6 -4
- holidays/countries/japan.py +5 -5
- holidays/countries/jersey.py +29 -26
- holidays/countries/jordan.py +9 -6
- holidays/countries/kazakhstan.py +66 -51
- holidays/countries/kenya.py +22 -18
- holidays/countries/kuwait.py +10 -7
- holidays/countries/kyrgyzstan.py +7 -6
- holidays/countries/laos.py +21 -29
- holidays/countries/latvia.py +7 -5
- holidays/countries/lesotho.py +6 -5
- holidays/countries/liechtenstein.py +5 -5
- holidays/countries/lithuania.py +4 -5
- holidays/countries/luxembourg.py +5 -3
- holidays/countries/macau.py +32 -26
- holidays/countries/madagascar.py +5 -4
- holidays/countries/malawi.py +6 -4
- holidays/countries/malaysia.py +29 -19
- holidays/countries/maldives.py +10 -7
- holidays/countries/malta.py +10 -19
- holidays/countries/marshall_islands.py +6 -4
- holidays/countries/mauritania.py +9 -6
- holidays/countries/mexico.py +8 -7
- holidays/countries/moldova.py +6 -4
- holidays/countries/monaco.py +6 -4
- holidays/countries/montenegro.py +10 -7
- holidays/countries/morocco.py +9 -8
- holidays/countries/mozambique.py +3 -1
- holidays/countries/namibia.py +7 -5
- holidays/countries/netherlands.py +6 -6
- holidays/countries/new_zealand.py +3 -1
- holidays/countries/nicaragua.py +6 -5
- holidays/countries/nigeria.py +9 -5
- holidays/countries/north_macedonia.py +9 -5
- holidays/countries/northern_mariana_islands.py +6 -4
- holidays/countries/norway.py +15 -15
- holidays/countries/oman.py +185 -0
- holidays/countries/pakistan.py +48 -17
- holidays/countries/palau.py +13 -11
- holidays/countries/panama.py +9 -8
- holidays/countries/papua_new_guinea.py +25 -21
- holidays/countries/paraguay.py +10 -9
- holidays/countries/peru.py +4 -5
- holidays/countries/philippines.py +25 -21
- holidays/countries/poland.py +6 -5
- holidays/countries/portugal.py +13 -15
- holidays/countries/puerto_rico.py +6 -4
- holidays/countries/qatar.py +172 -0
- holidays/countries/romania.py +6 -4
- holidays/countries/russia.py +6 -4
- holidays/countries/saint_kitts_and_nevis.py +24 -22
- holidays/countries/saint_lucia.py +8 -7
- holidays/countries/samoa.py +7 -6
- holidays/countries/san_marino.py +4 -3
- holidays/countries/saudi_arabia.py +11 -15
- holidays/countries/serbia.py +3 -4
- holidays/countries/seychelles.py +22 -26
- holidays/countries/sierra_leone.py +149 -0
- holidays/countries/singapore.py +29 -39
- holidays/countries/slovakia.py +6 -5
- holidays/countries/slovenia.py +7 -6
- holidays/countries/south_africa.py +8 -6
- holidays/countries/south_korea.py +39 -47
- holidays/countries/spain.py +25 -24
- holidays/countries/sri_lanka.py +46 -42
- holidays/countries/suriname.py +227 -0
- holidays/countries/sweden.py +20 -19
- holidays/countries/switzerland.py +6 -5
- holidays/countries/taiwan.py +52 -49
- holidays/countries/tanzania.py +28 -27
- holidays/countries/thailand.py +134 -142
- holidays/countries/timor_leste.py +20 -18
- holidays/countries/tonga.py +46 -42
- holidays/countries/tunisia.py +5 -3
- holidays/countries/turkey.py +11 -9
- holidays/countries/tuvalu.py +12 -11
- holidays/countries/ukraine.py +54 -54
- holidays/countries/united_arab_emirates.py +37 -30
- holidays/countries/united_kingdom.py +7 -6
- holidays/countries/united_states.py +50 -55
- holidays/countries/united_states_minor_outlying_islands.py +6 -4
- holidays/countries/united_states_virgin_islands.py +6 -4
- holidays/countries/uruguay.py +10 -9
- holidays/countries/uzbekistan.py +10 -7
- holidays/countries/vanuatu.py +7 -5
- holidays/countries/vatican_city.py +16 -15
- holidays/countries/venezuela.py +11 -14
- holidays/countries/vietnam.py +15 -11
- holidays/countries/zambia.py +8 -6
- holidays/countries/zimbabwe.py +6 -4
- holidays/deprecations/v1_incompatibility.py +1 -1
- holidays/financial/__init__.py +1 -1
- holidays/financial/brasil_bolsa_balcao.py +14 -13
- holidays/financial/european_central_bank.py +7 -6
- holidays/financial/ice_futures_europe.py +7 -6
- holidays/financial/ny_stock_exchange.py +13 -10
- holidays/groups/__init__.py +1 -1
- holidays/groups/balinese_saka.py +1 -1
- holidays/groups/buddhist.py +1 -1
- holidays/groups/chinese.py +1 -1
- holidays/groups/christian.py +1 -1
- holidays/groups/custom.py +1 -1
- holidays/groups/eastern.py +1 -1
- holidays/groups/hebrew.py +1 -1
- holidays/groups/hindu.py +1 -1
- holidays/groups/international.py +1 -1
- holidays/groups/islamic.py +22 -1
- holidays/groups/persian.py +1 -1
- holidays/groups/sinhala.py +1 -1
- holidays/groups/thai.py +1 -7
- holidays/helpers.py +1 -1
- holidays/holiday_base.py +393 -245
- holidays/ical.py +228 -0
- holidays/locale/ar/LC_MESSAGES/OM.mo +0 -0
- holidays/locale/ar_QA/LC_MESSAGES/QA.mo +0 -0
- holidays/locale/en_CI/LC_MESSAGES/CI.mo +0 -0
- holidays/locale/en_PK/LC_MESSAGES/PK.mo +0 -0
- holidays/locale/en_SL/LC_MESSAGES/SL.mo +0 -0
- holidays/locale/en_TL/LC_MESSAGES/TL.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/AR.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CI.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/GN.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/OM.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/PK.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/QA.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/SL.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/SR.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/TF.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/TL.mo +0 -0
- holidays/locale/es/LC_MESSAGES/AR.mo +0 -0
- holidays/locale/fr/LC_MESSAGES/CI.mo +0 -0
- holidays/locale/fr/LC_MESSAGES/GN.mo +0 -0
- holidays/locale/fr/LC_MESSAGES/TF.mo +0 -0
- holidays/locale/hi/LC_MESSAGES/IN.mo +0 -0
- holidays/locale/nl/LC_MESSAGES/SR.mo +0 -0
- holidays/locale/pt_TL/LC_MESSAGES/TL.mo +0 -0
- holidays/locale/tet/LC_MESSAGES/TL.mo +0 -0
- holidays/locale/th/LC_MESSAGES/TL.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/AR.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/TF.mo +0 -0
- holidays/locale/ur_PK/LC_MESSAGES/PK.mo +0 -0
- holidays/mixins.py +2 -2
- holidays/observed_holiday_base.py +10 -3
- holidays/registry.py +10 -1
- holidays/utils.py +203 -151
- holidays/version.py +2 -2
- holidays-0.71.dist-info/METADATA +1432 -0
- {holidays-0.69.dist-info → holidays-0.71.dist-info}/RECORD +248 -217
- {holidays-0.69.dist-info → holidays-0.71.dist-info}/WHEEL +1 -1
- holidays-0.69.dist-info/AUTHORS → holidays-0.71.dist-info/licenses/AUTHORS.md +9 -2
- {holidays-0.69.dist-info → holidays-0.71.dist-info/licenses}/LICENSE +1 -1
- holidays-0.69.dist-info/METADATA +0 -1085
- {holidays-0.69.dist-info → holidays-0.71.dist-info}/top_level.txt +0 -0
holidays/holiday_base.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# specific sets of holidays on the fly. It aims to make determining whether a
|
|
5
5
|
# specific date is a holiday as fast and flexible as possible.
|
|
6
6
|
#
|
|
7
|
-
# Authors: Vacanza Team and individual contributors (see AUTHORS file)
|
|
7
|
+
# Authors: Vacanza Team and individual contributors (see AUTHORS.md file)
|
|
8
8
|
# dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
|
|
9
9
|
# ryanss <ryanssdev@icloud.com> (c) 2014-2017
|
|
10
10
|
# Website: https://github.com/vacanza/holidays
|
|
@@ -56,19 +56,19 @@ YearArg = Union[int, Iterable[int]]
|
|
|
56
56
|
|
|
57
57
|
class HolidayBase(dict[date, str]):
|
|
58
58
|
"""
|
|
59
|
-
A dict
|
|
60
|
-
province or state if so initiated); inherits the dict class (so behaves
|
|
61
|
-
similarly to a dict). Dates without a key in the Holiday object are not
|
|
59
|
+
A `dict`-like object containing the holidays for a specific country (and
|
|
60
|
+
province or state if so initiated); inherits the `dict` class (so behaves
|
|
61
|
+
similarly to a `dict`). Dates without a key in the Holiday object are not
|
|
62
62
|
holidays.
|
|
63
63
|
|
|
64
64
|
The key of the object is the date of the holiday and the value is the name
|
|
65
65
|
of the holiday itself. When passing the date as a key, the date can be
|
|
66
66
|
expressed as one of the following formats:
|
|
67
67
|
|
|
68
|
-
* datetime.datetime type;
|
|
69
|
-
* datetime.date types;
|
|
70
|
-
* a float representing a Unix timestamp;
|
|
71
|
-
* or a string of any format (recognized by
|
|
68
|
+
* `datetime.datetime` type;
|
|
69
|
+
* `datetime.date` types;
|
|
70
|
+
* a `float` representing a Unix timestamp;
|
|
71
|
+
* or a string of any format (recognized by `dateutil.parser.parse()`).
|
|
72
72
|
|
|
73
73
|
The key is always returned as a `datetime.date` object.
|
|
74
74
|
|
|
@@ -78,11 +78,12 @@ class HolidayBase(dict[date, str]):
|
|
|
78
78
|
holidays. To pre-populate holidays, instantiate the class with the years
|
|
79
79
|
argument:
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
us_holidays = holidays.US(years=2020)
|
|
82
82
|
|
|
83
|
-
It is generally instantiated using the
|
|
83
|
+
It is generally instantiated using the
|
|
84
|
+
[country_holidays()][holidays.utils.country_holidays] function.
|
|
84
85
|
|
|
85
|
-
The key of the
|
|
86
|
+
The key of the `dict`-like `HolidayBase` object is the
|
|
86
87
|
`date` of the holiday, and the value is the name of the holiday itself.
|
|
87
88
|
Dates where a key is not present are not public holidays (or, if
|
|
88
89
|
**observed** is False, days when a public holiday is observed).
|
|
@@ -90,12 +91,12 @@ class HolidayBase(dict[date, str]):
|
|
|
90
91
|
When passing the `date` as a key, the `date` can be expressed in one of the
|
|
91
92
|
following types:
|
|
92
93
|
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* a
|
|
96
|
-
* or a
|
|
94
|
+
* `datetime.date`,
|
|
95
|
+
* `datetime.datetime`,
|
|
96
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
97
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
97
98
|
|
|
98
|
-
The key is always returned as a
|
|
99
|
+
The key is always returned as a `datetime.date` object.
|
|
99
100
|
|
|
100
101
|
To maximize speed, the list of public holidays is built on the fly as
|
|
101
102
|
needed, one calendar year at a time. When the object is instantiated
|
|
@@ -108,70 +109,70 @@ class HolidayBase(dict[date, str]):
|
|
|
108
109
|
|
|
109
110
|
Example usage:
|
|
110
111
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
>>> from holidays import country_holidays
|
|
113
|
+
>>> us_holidays = country_holidays('US')
|
|
114
|
+
# For a specific subdivisions (e.g. state or province):
|
|
115
|
+
>>> california_holidays = country_holidays('US', subdiv='CA')
|
|
115
116
|
|
|
116
117
|
The below will cause 2015 holidays to be calculated on the fly:
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
>>> from datetime import date
|
|
120
|
+
>>> assert date(2015, 1, 1) in us_holidays
|
|
120
121
|
|
|
121
122
|
This will be faster because 2015 holidays are already calculated:
|
|
122
123
|
|
|
123
|
-
|
|
124
|
+
>>> assert date(2015, 1, 2) not in us_holidays
|
|
124
125
|
|
|
125
|
-
The
|
|
126
|
+
The `HolidayBase` class also recognizes strings of many formats
|
|
126
127
|
and numbers representing a POSIX timestamp:
|
|
127
128
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
>>> assert '2014-01-01' in us_holidays
|
|
130
|
+
>>> assert '1/1/2014' in us_holidays
|
|
131
|
+
>>> assert 1388597445 in us_holidays
|
|
131
132
|
|
|
132
133
|
Show the holiday's name:
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
135
|
+
>>> us_holidays.get('2014-01-01')
|
|
136
|
+
"New Year's Day"
|
|
136
137
|
|
|
137
138
|
Check a range:
|
|
138
139
|
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
>>> us_holidays['2014-01-01': '2014-01-03']
|
|
141
|
+
[datetime.date(2014, 1, 1)]
|
|
141
142
|
|
|
142
143
|
List all 2020 holidays:
|
|
143
144
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
145
|
+
>>> us_holidays = country_holidays('US', years=2020)
|
|
146
|
+
>>> for day in sorted(us_holidays.items()):
|
|
147
|
+
... print(day)
|
|
148
|
+
(datetime.date(2020, 1, 1), "New Year's Day")
|
|
149
|
+
(datetime.date(2020, 1, 20), 'Martin Luther King Jr. Day')
|
|
150
|
+
(datetime.date(2020, 2, 17), "Washington's Birthday")
|
|
151
|
+
(datetime.date(2020, 5, 25), 'Memorial Day')
|
|
152
|
+
(datetime.date(2020, 7, 3), 'Independence Day (observed)')
|
|
153
|
+
(datetime.date(2020, 7, 4), 'Independence Day')
|
|
154
|
+
(datetime.date(2020, 9, 7), 'Labor Day')
|
|
155
|
+
(datetime.date(2020, 10, 12), 'Columbus Day')
|
|
156
|
+
(datetime.date(2020, 11, 11), 'Veterans Day')
|
|
157
|
+
(datetime.date(2020, 11, 26), 'Thanksgiving Day')
|
|
158
|
+
(datetime.date(2020, 12, 25), 'Christmas Day')
|
|
158
159
|
|
|
159
160
|
Some holidays are only present in parts of a country:
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
>>> us_pr_holidays = country_holidays('US', subdiv='PR')
|
|
163
|
+
>>> assert '2018-01-06' not in us_holidays
|
|
164
|
+
>>> assert '2018-01-06' in us_pr_holidays
|
|
164
165
|
|
|
165
166
|
Append custom holiday dates by passing one of:
|
|
166
167
|
|
|
167
|
-
* a
|
|
168
|
-
|
|
169
|
-
* a list of dates (as a
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
* or a single date item (of one of the types above); ``'Holiday'`` will be
|
|
168
|
+
* a `dict` with date/name key/value pairs (e.g.
|
|
169
|
+
`{'2010-07-10': 'My birthday!'}`),
|
|
170
|
+
* a list of dates (as a `datetime.date`, `datetime.datetime`,
|
|
171
|
+
`str`, `int`, or `float`); `'Holiday'` will be used as a description,
|
|
172
|
+
* or a single date item (of one of the types above); `'Holiday'` will be
|
|
173
173
|
used as a description:
|
|
174
174
|
|
|
175
|
+
```python
|
|
175
176
|
>>> custom_holidays = country_holidays('US', years=2015)
|
|
176
177
|
>>> custom_holidays.update({'2015-01-01': "New Year's Day"})
|
|
177
178
|
>>> custom_holidays.update(['2015-07-01', '07/04/2015'])
|
|
@@ -179,11 +180,10 @@ class HolidayBase(dict[date, str]):
|
|
|
179
180
|
>>> assert date(2015, 1, 1) in custom_holidays
|
|
180
181
|
>>> assert date(2015, 1, 2) not in custom_holidays
|
|
181
182
|
>>> assert '12/25/2015' in custom_holidays
|
|
183
|
+
```
|
|
182
184
|
|
|
183
185
|
For special (one-off) country-wide holidays handling use
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
.. code-block:: python
|
|
186
|
+
`special_public_holidays`:
|
|
187
187
|
|
|
188
188
|
special_public_holidays = {
|
|
189
189
|
1977: ((JUN, 7, "Silver Jubilee of Elizabeth II"),),
|
|
@@ -204,7 +204,8 @@ class HolidayBase(dict[date, str]):
|
|
|
204
204
|
...
|
|
205
205
|
|
|
206
206
|
For more complex logic, like 4th Monday of January, you can inherit the
|
|
207
|
-
|
|
207
|
+
[HolidayBase][holidays.holiday_base.HolidayBase] class and define your own `_populate()`
|
|
208
|
+
method.
|
|
208
209
|
See documentation for examples.
|
|
209
210
|
"""
|
|
210
211
|
|
|
@@ -265,39 +266,66 @@ class HolidayBase(dict[date, str]):
|
|
|
265
266
|
categories: Optional[CategoryArg] = None,
|
|
266
267
|
) -> None:
|
|
267
268
|
"""
|
|
268
|
-
:
|
|
269
|
-
|
|
269
|
+
Args:
|
|
270
|
+
years:
|
|
271
|
+
The year(s) to pre-calculate public holidays for at instantiation.
|
|
272
|
+
|
|
273
|
+
expand:
|
|
274
|
+
Whether the entire year is calculated when one date from that year
|
|
275
|
+
is requested.
|
|
276
|
+
|
|
277
|
+
observed:
|
|
278
|
+
Whether to include the dates when public holiday are observed
|
|
279
|
+
(e.g. a holiday falling on a Sunday being observed the
|
|
280
|
+
following Monday). This doesn't work for all countries.
|
|
281
|
+
|
|
282
|
+
subdiv:
|
|
283
|
+
The subdivision (e.g. state or province) as a ISO 3166-2 code
|
|
284
|
+
or its alias; not implemented for all countries (see documentation).
|
|
285
|
+
|
|
286
|
+
prov:
|
|
287
|
+
*deprecated* use `subdiv` instead.
|
|
288
|
+
|
|
289
|
+
state:
|
|
290
|
+
*deprecated* use `subdiv` instead.
|
|
270
291
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
is requested.
|
|
292
|
+
language:
|
|
293
|
+
Specifies the language in which holiday names are returned.
|
|
274
294
|
|
|
275
|
-
|
|
276
|
-
Whether to include the dates when public holiday are observed
|
|
277
|
-
(e.g. a holiday falling on a Sunday being observed the
|
|
278
|
-
following Monday). This doesn't work for all countries.
|
|
295
|
+
Accepts either:
|
|
279
296
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
297
|
+
* A two-letter ISO 639-1 language code (e.g., 'en' for English, 'fr' for French),
|
|
298
|
+
or
|
|
299
|
+
* A language and entity combination using an underscore (e.g., 'en_US' for U.S.
|
|
300
|
+
English, 'pt_BR' for Brazilian Portuguese).
|
|
283
301
|
|
|
284
|
-
|
|
285
|
-
|
|
302
|
+
!!! warning
|
|
303
|
+
The provided language or locale code must be supported by the holiday
|
|
304
|
+
entity. Unsupported values will result in names being shown in the entity's
|
|
305
|
+
original language.
|
|
286
306
|
|
|
287
|
-
|
|
288
|
-
|
|
307
|
+
If not explicitly set (`language=None`), the system attempts to infer the
|
|
308
|
+
language from the environment's locale settings. The following environment
|
|
309
|
+
variables are checked, in order of precedence: LANGUAGE, LC_ALL, LC_MESSAGES, LANG.
|
|
289
310
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
into. It must be an ISO 639-1 (2-letter) language code. If the
|
|
293
|
-
language translation is not supported the original holiday names
|
|
294
|
-
will be used.
|
|
311
|
+
If none of these are set or they are empty, holiday names will default to the
|
|
312
|
+
original language of the entity's holiday implementation.
|
|
295
313
|
|
|
296
|
-
|
|
297
|
-
|
|
314
|
+
!!! warning
|
|
315
|
+
This fallback mechanism may yield inconsistent results across environments
|
|
316
|
+
(e.g., between a terminal session and a Jupyter notebook).
|
|
298
317
|
|
|
299
|
-
|
|
300
|
-
|
|
318
|
+
To ensure consistent behavior, it is recommended to set the language parameter
|
|
319
|
+
explicitly. If the specified language is not supported, holiday names will remain
|
|
320
|
+
in the original language of the entity's holiday implementation.
|
|
321
|
+
|
|
322
|
+
This behavior will be updated and formalized in v1.
|
|
323
|
+
|
|
324
|
+
categories:
|
|
325
|
+
Requested holiday categories.
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
A `HolidayBase` object matching the **country** or **market**.
|
|
301
329
|
"""
|
|
302
330
|
super().__init__()
|
|
303
331
|
|
|
@@ -376,14 +404,14 @@ class HolidayBase(dict[date, str]):
|
|
|
376
404
|
|
|
377
405
|
def __add__(self, other: Union[int, "HolidayBase", "HolidaySum"]) -> "HolidayBase":
|
|
378
406
|
"""Add another dictionary of public holidays creating a
|
|
379
|
-
|
|
407
|
+
[HolidaySum][holidays.holiday_base.HolidaySum] object.
|
|
380
408
|
|
|
381
|
-
:
|
|
382
|
-
|
|
409
|
+
Args:
|
|
410
|
+
other:
|
|
411
|
+
The dictionary of public holiday to be added.
|
|
383
412
|
|
|
384
|
-
:
|
|
385
|
-
A
|
|
386
|
-
added, then :class:`self`.
|
|
413
|
+
Returns:
|
|
414
|
+
A `HolidayBase` object unless the other object cannot be added, then `self`.
|
|
387
415
|
"""
|
|
388
416
|
if isinstance(other, int) and other == 0:
|
|
389
417
|
# Required to sum() list of holidays
|
|
@@ -399,14 +427,21 @@ class HolidayBase(dict[date, str]):
|
|
|
399
427
|
return len(self) > 0
|
|
400
428
|
|
|
401
429
|
def __contains__(self, key: object) -> bool:
|
|
402
|
-
"""
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
*
|
|
407
|
-
*
|
|
408
|
-
|
|
409
|
-
* or a
|
|
430
|
+
"""Check if a given date is a holiday.
|
|
431
|
+
|
|
432
|
+
The method supports the following input types:
|
|
433
|
+
|
|
434
|
+
* `datetime.date`,
|
|
435
|
+
* `datetime.datetime`,
|
|
436
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
437
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
438
|
+
|
|
439
|
+
Args:
|
|
440
|
+
key:
|
|
441
|
+
The date to check.
|
|
442
|
+
|
|
443
|
+
Returns:
|
|
444
|
+
`True` if the date is a holiday, `False` otherwise.
|
|
410
445
|
"""
|
|
411
446
|
|
|
412
447
|
if not isinstance(key, (date, datetime, float, int, str)):
|
|
@@ -574,15 +609,21 @@ class HolidayBase(dict[date, str]):
|
|
|
574
609
|
return state
|
|
575
610
|
|
|
576
611
|
def __keytransform__(self, key: DateLike) -> date:
|
|
577
|
-
"""
|
|
612
|
+
"""Convert various date-like formats to `datetime.date`.
|
|
613
|
+
|
|
614
|
+
The method supports the following input types:
|
|
615
|
+
* `datetime.date`,
|
|
616
|
+
* `datetime.datetime`,
|
|
617
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
618
|
+
* or a `float` or `int` representing a POSIX timestamp
|
|
578
619
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
:func:`dateutil.parser.parse`,
|
|
583
|
-
* or a :class:`float` or :class:`int` representing a POSIX timestamp
|
|
620
|
+
Args:
|
|
621
|
+
key:
|
|
622
|
+
The date-like object to convert.
|
|
584
623
|
|
|
585
|
-
|
|
624
|
+
Returns:
|
|
625
|
+
The corresponding `datetime.date` representation.
|
|
626
|
+
"""
|
|
586
627
|
|
|
587
628
|
dt: Optional[date] = None
|
|
588
629
|
# Try to catch `date` and `str` type keys first.
|
|
@@ -729,7 +770,11 @@ class HolidayBase(dict[date, str]):
|
|
|
729
770
|
|
|
730
771
|
@classmethod
|
|
731
772
|
def get_subdivision_aliases(cls) -> dict[str, list]:
|
|
732
|
-
"""Get subdivision aliases.
|
|
773
|
+
"""Get subdivision aliases.
|
|
774
|
+
|
|
775
|
+
Returns:
|
|
776
|
+
A dictionary mapping subdivision aliases to their official ISO 3166-2 codes.
|
|
777
|
+
"""
|
|
733
778
|
subdivision_aliases: dict[str, list[str]] = {s: [] for s in cls.subdivisions}
|
|
734
779
|
for alias, subdivision in cls.subdivisions_aliases.items():
|
|
735
780
|
subdivision_aliases[subdivision].append(alias)
|
|
@@ -856,13 +901,13 @@ class HolidayBase(dict[date, str]):
|
|
|
856
901
|
directly from outside.
|
|
857
902
|
To add holidays to an object, use the update() method.
|
|
858
903
|
|
|
859
|
-
:
|
|
860
|
-
The year to populate with holidays.
|
|
904
|
+
Args:
|
|
905
|
+
year: The year to populate with holidays.
|
|
861
906
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
907
|
+
>>> from holidays import country_holidays
|
|
908
|
+
>>> us_holidays = country_holidays('US', years=2020)
|
|
909
|
+
# to add new holidays to the object:
|
|
910
|
+
>>> us_holidays.update(country_holidays('US', years=2021))
|
|
866
911
|
"""
|
|
867
912
|
|
|
868
913
|
if year < self.start_year or year > self.end_year:
|
|
@@ -903,7 +948,16 @@ class HolidayBase(dict[date, str]):
|
|
|
903
948
|
)
|
|
904
949
|
|
|
905
950
|
def append(self, *args: Union[dict[DateLike, str], list[DateLike], DateLike]) -> None:
|
|
906
|
-
"""Alias for
|
|
951
|
+
"""Alias for [update()][holidays.holiday_base.HolidayBase.update] to mimic list type.
|
|
952
|
+
|
|
953
|
+
Args:
|
|
954
|
+
args:
|
|
955
|
+
Holiday data to add. Can be:
|
|
956
|
+
|
|
957
|
+
* A dictionary mapping dates to holiday names.
|
|
958
|
+
* A list of dates (without names).
|
|
959
|
+
* A single date.
|
|
960
|
+
"""
|
|
907
961
|
return self.update(*args)
|
|
908
962
|
|
|
909
963
|
def copy(self):
|
|
@@ -911,64 +965,73 @@ class HolidayBase(dict[date, str]):
|
|
|
911
965
|
return copy.copy(self)
|
|
912
966
|
|
|
913
967
|
def get(self, key: DateLike, default: Union[str, Any] = None) -> Union[str, Any]:
|
|
914
|
-
"""
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
968
|
+
"""Retrieve the holiday name(s) for a given date.
|
|
969
|
+
|
|
970
|
+
If the date is a holiday, returns the holiday name as a string.
|
|
971
|
+
If multiple holidays fall on the same date, their names are joined by a semicolon (`;`).
|
|
972
|
+
If the date is not a holiday, returns the provided `default` value (defaults to `None`).
|
|
973
|
+
|
|
974
|
+
Args:
|
|
975
|
+
key:
|
|
976
|
+
The date expressed in one of the following types:
|
|
977
|
+
|
|
978
|
+
* `datetime.date`,
|
|
979
|
+
* `datetime.datetime`,
|
|
980
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
981
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
982
|
+
|
|
983
|
+
default:
|
|
984
|
+
The default value to return if no value is found.
|
|
985
|
+
|
|
986
|
+
Returns:
|
|
987
|
+
The holiday name(s) as a string if the date is a holiday,
|
|
988
|
+
or the `default` value otherwise.
|
|
931
989
|
"""
|
|
932
990
|
return dict.get(self, self.__keytransform__(key), default)
|
|
933
991
|
|
|
934
992
|
def get_list(self, key: DateLike) -> list[str]:
|
|
935
|
-
"""
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
993
|
+
"""Retrieve all holiday names for a given date.
|
|
994
|
+
|
|
995
|
+
Args:
|
|
996
|
+
key:
|
|
997
|
+
The date expressed in one of the following types:
|
|
998
|
+
|
|
999
|
+
* `datetime.date`,
|
|
1000
|
+
* `datetime.datetime`,
|
|
1001
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
1002
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
1003
|
+
|
|
1004
|
+
Returns:
|
|
1005
|
+
A list of holiday names if the date is a holiday, otherwise an empty list.
|
|
947
1006
|
"""
|
|
948
1007
|
return [name for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER) if name]
|
|
949
1008
|
|
|
950
1009
|
def get_named(
|
|
951
|
-
self, holiday_name: str, lookup="icontains", split_multiple_names=True
|
|
1010
|
+
self, holiday_name: str, lookup: str = "icontains", split_multiple_names: bool = True
|
|
952
1011
|
) -> list[date]:
|
|
953
|
-
"""
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
:
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1012
|
+
"""Find all holiday dates matching a given name.
|
|
1013
|
+
|
|
1014
|
+
The search by default is case-insensitive and includes partial matches.
|
|
1015
|
+
|
|
1016
|
+
Args:
|
|
1017
|
+
holiday_name:
|
|
1018
|
+
The holiday's name to try to match.
|
|
1019
|
+
|
|
1020
|
+
lookup:
|
|
1021
|
+
The holiday name lookup type:
|
|
1022
|
+
|
|
1023
|
+
* contains - case sensitive contains match;
|
|
1024
|
+
* exact - case sensitive exact match;
|
|
1025
|
+
* startswith - case sensitive starts with match;
|
|
1026
|
+
* icontains - case insensitive contains match;
|
|
1027
|
+
* iexact - case insensitive exact match;
|
|
1028
|
+
* istartswith - case insensitive starts with match;
|
|
1029
|
+
|
|
1030
|
+
split_multiple_names:
|
|
1031
|
+
Either use the exact name for each date or split it by holiday
|
|
1032
|
+
name delimiter.
|
|
1033
|
+
|
|
1034
|
+
Returns:
|
|
972
1035
|
A list of all holiday dates matching the provided holiday name.
|
|
973
1036
|
"""
|
|
974
1037
|
holiday_name_dates = (
|
|
@@ -1003,13 +1066,26 @@ class HolidayBase(dict[date, str]):
|
|
|
1003
1066
|
|
|
1004
1067
|
def get_closest_holiday(
|
|
1005
1068
|
self,
|
|
1006
|
-
target_date: DateLike = None,
|
|
1069
|
+
target_date: Optional[DateLike] = None,
|
|
1007
1070
|
direction: Literal["forward", "backward"] = "forward",
|
|
1008
1071
|
) -> Optional[tuple[date, str]]:
|
|
1009
|
-
"""
|
|
1010
|
-
if direction is "forward" or the previous holiday if direction is "backward".
|
|
1011
|
-
If target_date is not provided the current date will be used by default."""
|
|
1072
|
+
"""Find the closest holiday relative to a given date.
|
|
1012
1073
|
|
|
1074
|
+
If `direction` is "forward", returns the next holiday after `target_date`.
|
|
1075
|
+
If `direction` is "backward", returns the previous holiday before `target_date`.
|
|
1076
|
+
If `target_date` is not provided, the current date is used.
|
|
1077
|
+
|
|
1078
|
+
Args:
|
|
1079
|
+
target_date:
|
|
1080
|
+
The reference date. If None, defaults to today.
|
|
1081
|
+
|
|
1082
|
+
direction:
|
|
1083
|
+
Search direction, either "forward" (next holiday) or
|
|
1084
|
+
"backward" (previous holiday).
|
|
1085
|
+
|
|
1086
|
+
Returns:
|
|
1087
|
+
A tuple containing the holiday date and its name, or None if no holiday is found.
|
|
1088
|
+
"""
|
|
1013
1089
|
if direction not in {"backward", "forward"}:
|
|
1014
1090
|
raise AttributeError(f"Unknown direction: {direction}")
|
|
1015
1091
|
|
|
@@ -1032,8 +1108,20 @@ class HolidayBase(dict[date, str]):
|
|
|
1032
1108
|
return None
|
|
1033
1109
|
|
|
1034
1110
|
def get_nth_working_day(self, key: DateLike, n: int) -> date:
|
|
1035
|
-
"""
|
|
1036
|
-
|
|
1111
|
+
"""Find the n-th working day from a given date.
|
|
1112
|
+
|
|
1113
|
+
Moves forward if n is positive, or backward if n is negative.
|
|
1114
|
+
|
|
1115
|
+
Args:
|
|
1116
|
+
key:
|
|
1117
|
+
The starting date.
|
|
1118
|
+
|
|
1119
|
+
n:
|
|
1120
|
+
The number of working days to move. Positive values move forward,
|
|
1121
|
+
negative values move backward.
|
|
1122
|
+
|
|
1123
|
+
Returns:
|
|
1124
|
+
The calculated working day after shifting by n working days.
|
|
1037
1125
|
"""
|
|
1038
1126
|
direction = +1 if n > 0 else -1
|
|
1039
1127
|
dt = self.__keytransform__(key)
|
|
@@ -1044,16 +1132,20 @@ class HolidayBase(dict[date, str]):
|
|
|
1044
1132
|
return dt
|
|
1045
1133
|
|
|
1046
1134
|
def get_working_days_count(self, start: DateLike, end: DateLike) -> int:
|
|
1047
|
-
"""
|
|
1135
|
+
"""Calculate the number of working days between two dates.
|
|
1048
1136
|
|
|
1049
1137
|
The date range works in a closed interval fashion [start, end] so both
|
|
1050
1138
|
endpoints are included.
|
|
1051
1139
|
|
|
1052
|
-
:
|
|
1053
|
-
|
|
1140
|
+
Args:
|
|
1141
|
+
start:
|
|
1142
|
+
The range start date.
|
|
1054
1143
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1144
|
+
end:
|
|
1145
|
+
The range end date.
|
|
1146
|
+
|
|
1147
|
+
Returns:
|
|
1148
|
+
The total count of working days between the given dates.
|
|
1057
1149
|
"""
|
|
1058
1150
|
dt1 = self.__keytransform__(start)
|
|
1059
1151
|
dt2 = self.__keytransform__(end)
|
|
@@ -1063,55 +1155,83 @@ class HolidayBase(dict[date, str]):
|
|
|
1063
1155
|
return sum(self.is_working_day(_timedelta(dt1, n)) for n in range(days))
|
|
1064
1156
|
|
|
1065
1157
|
def is_working_day(self, key: DateLike) -> bool:
|
|
1066
|
-
"""
|
|
1158
|
+
"""Check if the given date is considered a working day.
|
|
1159
|
+
|
|
1160
|
+
Args:
|
|
1161
|
+
key:
|
|
1162
|
+
The date to check.
|
|
1163
|
+
|
|
1164
|
+
Returns:
|
|
1165
|
+
True if the date is a working day, False if it is a holiday or weekend.
|
|
1166
|
+
"""
|
|
1067
1167
|
dt = self.__keytransform__(key)
|
|
1068
1168
|
return dt in self.weekend_workdays if self._is_weekend(dt) else dt not in self
|
|
1069
1169
|
|
|
1070
1170
|
def pop(self, key: DateLike, default: Union[str, Any] = None) -> Union[str, Any]:
|
|
1071
|
-
"""
|
|
1072
|
-
default.
|
|
1171
|
+
"""Remove a holiday for a given date and return its name.
|
|
1073
1172
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1173
|
+
If the specified date is a holiday, it will be removed, and its name will
|
|
1174
|
+
be returned. If the date is not a holiday, the provided `default` value
|
|
1175
|
+
will be returned instead.
|
|
1076
1176
|
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
:func:`dateutil.parser.parse`,
|
|
1081
|
-
* or a :class:`float` or :class:`int` representing a POSIX
|
|
1082
|
-
timestamp.
|
|
1177
|
+
Args:
|
|
1178
|
+
key:
|
|
1179
|
+
The date expressed in one of the following types:
|
|
1083
1180
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1181
|
+
* `datetime.date`,
|
|
1182
|
+
* `datetime.datetime`,
|
|
1183
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
1184
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
1086
1185
|
|
|
1087
|
-
|
|
1088
|
-
|
|
1186
|
+
default:
|
|
1187
|
+
The default value to return if no match is found.
|
|
1089
1188
|
|
|
1090
|
-
:
|
|
1091
|
-
|
|
1189
|
+
Returns:
|
|
1190
|
+
The name of the removed holiday if the date was a holiday, otherwise
|
|
1191
|
+
the provided `default` value.
|
|
1192
|
+
|
|
1193
|
+
Raises:
|
|
1194
|
+
KeyError: if date is not a holiday and default is not given.
|
|
1092
1195
|
"""
|
|
1093
1196
|
if default is None:
|
|
1094
1197
|
return dict.pop(self, self.__keytransform__(key))
|
|
1095
1198
|
|
|
1096
1199
|
return dict.pop(self, self.__keytransform__(key), default)
|
|
1097
1200
|
|
|
1098
|
-
def pop_named(self,
|
|
1099
|
-
"""Remove
|
|
1100
|
-
|
|
1101
|
-
|
|
1201
|
+
def pop_named(self, holiday_name: str, lookup: str = "icontains") -> list[date]:
|
|
1202
|
+
"""Remove all holidays matching the given name.
|
|
1203
|
+
|
|
1204
|
+
This method removes all dates associated with a holiday name, so they are
|
|
1205
|
+
no longer considered holidays. The search by default is case-insensitive and
|
|
1206
|
+
includes partial matches.
|
|
1207
|
+
|
|
1208
|
+
Args:
|
|
1209
|
+
holiday_name:
|
|
1210
|
+
The holiday's name to try to match.
|
|
1211
|
+
|
|
1212
|
+
lookup:
|
|
1213
|
+
The holiday name lookup type:
|
|
1102
1214
|
|
|
1103
|
-
|
|
1104
|
-
|
|
1215
|
+
* contains - case sensitive contains match;
|
|
1216
|
+
* exact - case sensitive exact match;
|
|
1217
|
+
* startswith - case sensitive starts with match;
|
|
1218
|
+
* icontains - case insensitive contains match;
|
|
1219
|
+
* iexact - case insensitive exact match;
|
|
1220
|
+
* istartswith - case insensitive starts with match;
|
|
1105
1221
|
|
|
1106
|
-
:
|
|
1222
|
+
Returns:
|
|
1107
1223
|
A list of dates removed.
|
|
1108
1224
|
|
|
1109
|
-
:
|
|
1110
|
-
KeyError if date is not a holiday
|
|
1225
|
+
Raises:
|
|
1226
|
+
KeyError: if date is not a holiday.
|
|
1111
1227
|
"""
|
|
1112
|
-
use_exact_name = HOLIDAY_NAME_DELIMITER in
|
|
1113
|
-
if not (
|
|
1114
|
-
|
|
1228
|
+
use_exact_name = HOLIDAY_NAME_DELIMITER in holiday_name
|
|
1229
|
+
if not (
|
|
1230
|
+
dts := self.get_named(
|
|
1231
|
+
holiday_name, lookup=lookup, split_multiple_names=not use_exact_name
|
|
1232
|
+
)
|
|
1233
|
+
):
|
|
1234
|
+
raise KeyError(holiday_name)
|
|
1115
1235
|
|
|
1116
1236
|
popped = []
|
|
1117
1237
|
for dt in dts:
|
|
@@ -1120,38 +1240,55 @@ class HolidayBase(dict[date, str]):
|
|
|
1120
1240
|
popped.append(dt)
|
|
1121
1241
|
|
|
1122
1242
|
# Keep the rest of holidays falling on the same date.
|
|
1123
|
-
if
|
|
1124
|
-
|
|
1243
|
+
if use_exact_name:
|
|
1244
|
+
continue
|
|
1245
|
+
if lookup == "icontains":
|
|
1246
|
+
holiday_name_lower = holiday_name.lower()
|
|
1125
1247
|
holiday_names = [
|
|
1126
|
-
|
|
1127
|
-
for holiday_name in holiday_names
|
|
1128
|
-
if name_lower not in holiday_name.lower()
|
|
1248
|
+
name for name in holiday_names if holiday_name_lower not in name.lower()
|
|
1129
1249
|
]
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1250
|
+
elif lookup == "iexact":
|
|
1251
|
+
holiday_name_lower = holiday_name.lower()
|
|
1252
|
+
holiday_names = [
|
|
1253
|
+
name for name in holiday_names if holiday_name_lower != name.lower()
|
|
1254
|
+
]
|
|
1255
|
+
elif lookup == "istartswith":
|
|
1256
|
+
holiday_name_lower = holiday_name.lower()
|
|
1257
|
+
holiday_names = [
|
|
1258
|
+
name
|
|
1259
|
+
for name in holiday_names
|
|
1260
|
+
if holiday_name_lower != name[: len(holiday_name)].lower()
|
|
1261
|
+
]
|
|
1262
|
+
elif lookup == "contains":
|
|
1263
|
+
holiday_names = [name for name in holiday_names if holiday_name not in name]
|
|
1264
|
+
elif lookup == "exact":
|
|
1265
|
+
holiday_names = [name for name in holiday_names if holiday_name != name]
|
|
1266
|
+
else: # startswith
|
|
1267
|
+
holiday_names = [
|
|
1268
|
+
name for name in holiday_names if holiday_name != name[: len(holiday_name)]
|
|
1269
|
+
]
|
|
1270
|
+
if holiday_names:
|
|
1271
|
+
self[dt] = HOLIDAY_NAME_DELIMITER.join(holiday_names)
|
|
1133
1272
|
|
|
1134
1273
|
return popped
|
|
1135
1274
|
|
|
1136
1275
|
def update( # type: ignore[override]
|
|
1137
1276
|
self, *args: Union[dict[DateLike, str], list[DateLike], DateLike]
|
|
1138
1277
|
) -> None:
|
|
1139
|
-
# TODO: fix arguments; should not be *args (cannot properly Type hint)
|
|
1140
1278
|
"""Update the object, overwriting existing dates.
|
|
1141
1279
|
|
|
1142
|
-
:
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1280
|
+
Args:
|
|
1281
|
+
args:
|
|
1282
|
+
Either another dictionary object where keys are dates and values
|
|
1283
|
+
are holiday names, or a single date (or a list of dates) for which
|
|
1284
|
+
the value will be set to "Holiday".
|
|
1146
1285
|
|
|
1147
|
-
|
|
1286
|
+
Dates can be expressed in one or more of the following types:
|
|
1148
1287
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
* or a :class:`float` or :class:`int` representing a POSIX
|
|
1154
|
-
timestamp.
|
|
1288
|
+
* `datetime.date`,
|
|
1289
|
+
* `datetime.datetime`,
|
|
1290
|
+
* a `str` of any format recognized by `dateutil.parser.parse()`,
|
|
1291
|
+
* or a `float` or `int` representing a POSIX timestamp.
|
|
1155
1292
|
"""
|
|
1156
1293
|
for arg in args:
|
|
1157
1294
|
if isinstance(arg, dict):
|
|
@@ -1166,11 +1303,11 @@ class HolidayBase(dict[date, str]):
|
|
|
1166
1303
|
|
|
1167
1304
|
class HolidaySum(HolidayBase):
|
|
1168
1305
|
"""
|
|
1169
|
-
Returns a
|
|
1306
|
+
Returns a `dict`-like object resulting from the addition of two or
|
|
1170
1307
|
more individual dictionaries of public holidays. The original dictionaries
|
|
1171
|
-
are available as a
|
|
1172
|
-
|
|
1173
|
-
together and could become
|
|
1308
|
+
are available as a `list` in the attribute `holidays,` and
|
|
1309
|
+
`country` and `subdiv` attributes are added
|
|
1310
|
+
together and could become `list` s. Holiday names, when different,
|
|
1174
1311
|
are merged. All years are calculated (expanded) for all operands.
|
|
1175
1312
|
"""
|
|
1176
1313
|
|
|
@@ -1189,30 +1326,31 @@ class HolidaySum(HolidayBase):
|
|
|
1189
1326
|
self, h1: Union[HolidayBase, "HolidaySum"], h2: Union[HolidayBase, "HolidaySum"]
|
|
1190
1327
|
) -> None:
|
|
1191
1328
|
"""
|
|
1192
|
-
:
|
|
1193
|
-
|
|
1329
|
+
Args:
|
|
1330
|
+
h1:
|
|
1331
|
+
The first HolidayBase object to add.
|
|
1194
1332
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1333
|
+
h2:
|
|
1334
|
+
The other HolidayBase object to add.
|
|
1197
1335
|
|
|
1198
1336
|
Example:
|
|
1199
1337
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
country_holidays('CA') + country_holidays('MX')
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1338
|
+
>>> from holidays import country_holidays
|
|
1339
|
+
>>> nafta_holidays = country_holidays('US', years=2020) + \
|
|
1340
|
+
country_holidays('CA') + country_holidays('MX')
|
|
1341
|
+
>>> dates = sorted(nafta_holidays.items(), key=lambda x: x[0])
|
|
1342
|
+
>>> from pprint import pprint
|
|
1343
|
+
>>> pprint(dates[:10], width=72)
|
|
1344
|
+
[(datetime.date(2020, 1, 1), "Año Nuevo; New Year's Day"),
|
|
1345
|
+
(datetime.date(2020, 1, 20), 'Martin Luther King Jr. Day'),
|
|
1346
|
+
(datetime.date(2020, 2, 3), 'Día de la Constitución'),
|
|
1347
|
+
(datetime.date(2020, 2, 17), "Washington's Birthday"),
|
|
1348
|
+
(datetime.date(2020, 3, 16), 'Natalicio de Benito Juárez'),
|
|
1349
|
+
(datetime.date(2020, 4, 10), 'Good Friday'),
|
|
1350
|
+
(datetime.date(2020, 5, 1), 'Día del Trabajo'),
|
|
1351
|
+
(datetime.date(2020, 5, 25), 'Memorial Day'),
|
|
1352
|
+
(datetime.date(2020, 7, 1), 'Canada Day'),
|
|
1353
|
+
(datetime.date(2020, 7, 3), 'Independence Day (observed)')]
|
|
1216
1354
|
"""
|
|
1217
1355
|
# Store originals in the holidays attribute.
|
|
1218
1356
|
self.holidays = []
|
|
@@ -1260,8 +1398,18 @@ country_holidays('CA') + country_holidays('MX')
|
|
|
1260
1398
|
else:
|
|
1261
1399
|
setattr(self, attr, value)
|
|
1262
1400
|
|
|
1401
|
+
# Retain language if they match and are strings.
|
|
1402
|
+
# If language wasn't assigned, default_language acts as fallback.
|
|
1403
|
+
h1_language = h1.language or h1.default_language
|
|
1404
|
+
h2_language = h2.language or h2.default_language
|
|
1405
|
+
if isinstance(h1_language, str) and h1_language == h2_language:
|
|
1406
|
+
kwargs["language"] = h1_language
|
|
1407
|
+
|
|
1263
1408
|
HolidayBase.__init__(self, **kwargs)
|
|
1264
1409
|
|
|
1410
|
+
# supported_languages is used for iCalExporter language check as well.
|
|
1411
|
+
self.supported_languages = (h1_language,) if h1_language else ()
|
|
1412
|
+
|
|
1265
1413
|
def _populate(self, year):
|
|
1266
1414
|
for operand in self.holidays:
|
|
1267
1415
|
operand._populate(year)
|