holidays 0.80__py3-none-any.whl → 0.82__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/calendars/__init__.py +1 -0
- holidays/calendars/burmese.py +319 -0
- holidays/calendars/chinese.py +39 -1
- holidays/calendars/hebrew.py +2 -2
- holidays/calendars/thai.py +49 -2
- holidays/countries/__init__.py +16 -0
- holidays/countries/afghanistan.py +7 -5
- holidays/countries/algeria.py +89 -24
- holidays/countries/antarctica.py +58 -0
- holidays/countries/bouvet_island.py +31 -0
- holidays/countries/brazil.py +1 -1
- holidays/countries/british_indian_ocean_territory.py +31 -0
- holidays/countries/bulgaria.py +6 -1
- holidays/countries/chile.py +9 -8
- holidays/countries/china.py +4 -0
- holidays/countries/cuba.py +3 -4
- holidays/countries/djibouti.py +1 -1
- holidays/countries/heard_island_and_mcdonald_islands.py +31 -0
- holidays/countries/hongkong.py +5 -1
- holidays/countries/hungary.py +4 -5
- holidays/countries/india.py +6 -0
- holidays/countries/japan.py +22 -18
- holidays/countries/jordan.py +6 -3
- holidays/countries/kuwait.py +6 -3
- holidays/countries/macau.py +9 -0
- holidays/countries/malaysia.py +14 -3
- holidays/countries/mongolia.py +2 -0
- holidays/countries/myanmar.py +195 -0
- holidays/countries/north_korea.py +161 -0
- holidays/countries/norway.py +23 -8
- holidays/countries/oman.py +6 -2
- holidays/countries/paraguay.py +70 -23
- holidays/countries/philippines.py +11 -2
- holidays/countries/portugal.py +5 -6
- holidays/countries/qatar.py +5 -2
- holidays/countries/rwanda.py +6 -1
- holidays/countries/saint_helena_ascension_and_tristan_da_cunha.py +197 -0
- holidays/countries/saudi_arabia.py +6 -5
- holidays/countries/serbia.py +5 -0
- holidays/countries/south_africa.py +96 -53
- holidays/countries/south_korea.py +10 -1
- holidays/countries/spain.py +26 -4
- holidays/countries/sudan.py +118 -0
- holidays/countries/switzerland.py +169 -3
- holidays/countries/taiwan.py +27 -3
- holidays/countries/tajikistan.py +1 -1
- holidays/countries/tanzania.py +6 -1
- holidays/countries/thailand.py +21 -0
- holidays/countries/tonga.py +6 -1
- holidays/countries/trinidad_and_tobago.py +6 -1
- holidays/countries/united_arab_emirates.py +9 -2
- holidays/countries/united_states.py +16 -0
- holidays/countries/uruguay.py +6 -1
- holidays/countries/vietnam.py +10 -1
- holidays/countries/yemen.py +6 -3
- holidays/groups/__init__.py +1 -0
- holidays/groups/balinese_saka.py +1 -1
- holidays/groups/buddhist.py +1 -1
- holidays/groups/burmese.py +273 -0
- holidays/groups/chinese.py +27 -14
- holidays/groups/custom.py +8 -2
- holidays/groups/eastern.py +25 -3
- holidays/groups/hebrew.py +16 -14
- holidays/groups/hindu.py +15 -13
- holidays/groups/islamic.py +52 -47
- holidays/groups/mongolian.py +1 -1
- holidays/groups/sinhala.py +4 -9
- holidays/groups/tibetan.py +3 -4
- holidays/holiday_base.py +5 -4
- holidays/ical.py +6 -4
- holidays/locale/ar/LC_MESSAGES/DZ.mo +0 -0
- holidays/locale/ar_SD/LC_MESSAGES/SD.mo +0 -0
- holidays/locale/ca/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/en_GB/LC_MESSAGES/SH.mo +0 -0
- holidays/locale/en_HK/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/en_IN/LC_MESSAGES/IN.mo +0 -0
- holidays/locale/en_MO/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/en_PH/LC_MESSAGES/PH.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/BR.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/CN.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/DZ.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/IN.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/JP.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/KP.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/KR.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/MM.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/MN.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/PH.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/PY.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/SD.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/SH.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/TW.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/US.mo +0 -0
- holidays/locale/en_US/LC_MESSAGES/VN.mo +0 -0
- holidays/locale/es/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/es/LC_MESSAGES/PY.mo +0 -0
- holidays/locale/fil/LC_MESSAGES/PH.mo +0 -0
- holidays/locale/fr/LC_MESSAGES/DZ.mo +0 -0
- holidays/locale/hi/LC_MESSAGES/IN.mo +0 -0
- holidays/locale/ja/LC_MESSAGES/JP.mo +0 -0
- holidays/locale/ko/LC_MESSAGES/KR.mo +0 -0
- holidays/locale/ko_KP/LC_MESSAGES/KP.mo +0 -0
- holidays/locale/mn/LC_MESSAGES/MN.mo +0 -0
- holidays/locale/my/LC_MESSAGES/MM.mo +0 -0
- holidays/locale/pt_BR/LC_MESSAGES/BR.mo +0 -0
- holidays/locale/pt_MO/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/th/LC_MESSAGES/CN.mo +0 -0
- holidays/locale/th/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/th/LC_MESSAGES/JP.mo +0 -0
- holidays/locale/th/LC_MESSAGES/KR.mo +0 -0
- holidays/locale/th/LC_MESSAGES/MM.mo +0 -0
- holidays/locale/th/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/th/LC_MESSAGES/PH.mo +0 -0
- holidays/locale/th/LC_MESSAGES/TW.mo +0 -0
- holidays/locale/th/LC_MESSAGES/US.mo +0 -0
- holidays/locale/th/LC_MESSAGES/VN.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/BR.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/ES.mo +0 -0
- holidays/locale/uk/LC_MESSAGES/PY.mo +0 -0
- holidays/locale/vi/LC_MESSAGES/VN.mo +0 -0
- holidays/locale/zh_CN/LC_MESSAGES/CN.mo +0 -0
- holidays/locale/zh_CN/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/zh_CN/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/zh_CN/LC_MESSAGES/TW.mo +0 -0
- holidays/locale/zh_HK/LC_MESSAGES/HK.mo +0 -0
- holidays/locale/zh_MO/LC_MESSAGES/MO.mo +0 -0
- holidays/locale/zh_TW/LC_MESSAGES/CN.mo +0 -0
- holidays/locale/zh_TW/LC_MESSAGES/TW.mo +0 -0
- holidays/no_holiday_base.py +21 -0
- holidays/observed_holiday_base.py +1 -1
- holidays/registry.py +12 -0
- holidays/utils.py +5 -5
- holidays/version.py +1 -1
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/METADATA +61 -5
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/RECORD +142 -121
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/licenses/CONTRIBUTORS +2 -0
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/WHEEL +0 -0
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/licenses/LICENSE +0 -0
- {holidays-0.80.dist-info → holidays-0.82.dist-info}/top_level.txt +0 -0
holidays/calendars/__init__.py
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from holidays.calendars.balinese_saka import _BalineseSakaLunar
|
|
16
16
|
from holidays.calendars.buddhist import _BuddhistLunisolar, _CustomBuddhistHolidays
|
|
17
|
+
from holidays.calendars.burmese import _BurmeseLunisolar
|
|
17
18
|
from holidays.calendars.chinese import _ChineseLunisolar, _CustomChineseHolidays
|
|
18
19
|
from holidays.calendars.custom import _CustomCalendar
|
|
19
20
|
from holidays.calendars.gregorian import GREGORIAN_CALENDAR
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# holidays
|
|
2
|
+
# --------
|
|
3
|
+
# A fast, efficient Python library for generating country, province and state
|
|
4
|
+
# specific sets of holidays on the fly. It aims to make determining whether a
|
|
5
|
+
# specific date is a holiday as fast and flexible as possible.
|
|
6
|
+
#
|
|
7
|
+
# Authors: Vacanza Team and individual contributors (see CONTRIBUTORS file)
|
|
8
|
+
# dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
|
|
9
|
+
# ryanss <ryanssdev@icloud.com> (c) 2014-2017
|
|
10
|
+
# Website: https://github.com/vacanza/holidays
|
|
11
|
+
# License: MIT (see LICENSE file)
|
|
12
|
+
|
|
13
|
+
from datetime import date
|
|
14
|
+
from functools import cache
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
from holidays.calendars.gregorian import _timedelta
|
|
18
|
+
|
|
19
|
+
MO = 1954168.050623 # Beginning of 0 ME for MMT.
|
|
20
|
+
SY = 1577917828.0 / 4320000.0 # Solar year (365.2587565 days).
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class _BurmeseLunisolar:
|
|
24
|
+
"""Burmese Lunisolar calendar.
|
|
25
|
+
|
|
26
|
+
References:
|
|
27
|
+
* [Algorithm, Program and Calculation of Myanmar Calendar](https://web.archive.org/web/20250510011425/http://cool-emerald.blogspot.com/2013/06/algorithm-program-and-calculation-of.html)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
START_DATE = date(1939, 3, 20) # 1 Late Tagu 1301 Burmese Era.
|
|
31
|
+
START_YEAR = 1939 # 1301 Burmese Era.
|
|
32
|
+
END_YEAR = 2100 # 1463 Burmese Era.
|
|
33
|
+
|
|
34
|
+
LITTLE_WATAT_YEARS_GREGORIAN = {
|
|
35
|
+
1939,
|
|
36
|
+
1948,
|
|
37
|
+
1955,
|
|
38
|
+
1958,
|
|
39
|
+
1966,
|
|
40
|
+
1972,
|
|
41
|
+
1974,
|
|
42
|
+
1982,
|
|
43
|
+
1988,
|
|
44
|
+
1993,
|
|
45
|
+
1999,
|
|
46
|
+
2004,
|
|
47
|
+
2012,
|
|
48
|
+
2018,
|
|
49
|
+
2020,
|
|
50
|
+
2029,
|
|
51
|
+
2034,
|
|
52
|
+
2039,
|
|
53
|
+
2045,
|
|
54
|
+
2050,
|
|
55
|
+
2056,
|
|
56
|
+
2061,
|
|
57
|
+
2069,
|
|
58
|
+
2075,
|
|
59
|
+
2077,
|
|
60
|
+
2086,
|
|
61
|
+
2091,
|
|
62
|
+
2096,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
BIG_WATAT_YEARS_GREGORIAN = {
|
|
66
|
+
1942,
|
|
67
|
+
1945,
|
|
68
|
+
1950,
|
|
69
|
+
1953,
|
|
70
|
+
1961,
|
|
71
|
+
1964,
|
|
72
|
+
1969,
|
|
73
|
+
1977,
|
|
74
|
+
1980,
|
|
75
|
+
1985,
|
|
76
|
+
1991,
|
|
77
|
+
1996,
|
|
78
|
+
2001,
|
|
79
|
+
2007,
|
|
80
|
+
2010,
|
|
81
|
+
2015,
|
|
82
|
+
2023,
|
|
83
|
+
2026,
|
|
84
|
+
2031,
|
|
85
|
+
2037,
|
|
86
|
+
2042,
|
|
87
|
+
2048,
|
|
88
|
+
2053,
|
|
89
|
+
2058,
|
|
90
|
+
2064,
|
|
91
|
+
2067,
|
|
92
|
+
2072,
|
|
93
|
+
2080,
|
|
94
|
+
2083,
|
|
95
|
+
2088,
|
|
96
|
+
2094,
|
|
97
|
+
2099,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def jdn_to_gregorian(jdn: int) -> date:
|
|
102
|
+
"""Convert Julian Day Number to Gregorian date.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
jdn: Julian Day Number.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Gregorian date.
|
|
109
|
+
"""
|
|
110
|
+
j = jdn - 1721119
|
|
111
|
+
y, j = divmod(4 * j - 1, 146097)
|
|
112
|
+
d = j // 4
|
|
113
|
+
j, d = divmod(4 * d + 3, 1461)
|
|
114
|
+
d = (d + 4) // 4
|
|
115
|
+
m, d = divmod(5 * d - 3, 153)
|
|
116
|
+
d = (d + 5) // 5
|
|
117
|
+
y = 100 * y + j
|
|
118
|
+
if m < 10:
|
|
119
|
+
m += 3
|
|
120
|
+
else:
|
|
121
|
+
m -= 9
|
|
122
|
+
y += 1
|
|
123
|
+
|
|
124
|
+
return date(y, m, d)
|
|
125
|
+
|
|
126
|
+
@cache
|
|
127
|
+
def _get_start_date(self, year: int) -> Optional[date]:
|
|
128
|
+
if year < self.START_YEAR or year > self.END_YEAR:
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
delta_days = 354 * (year - self.START_YEAR)
|
|
132
|
+
for iter_year in range(self.START_YEAR, year):
|
|
133
|
+
if iter_year in self.LITTLE_WATAT_YEARS_GREGORIAN:
|
|
134
|
+
delta_days += 30
|
|
135
|
+
elif iter_year in self.BIG_WATAT_YEARS_GREGORIAN:
|
|
136
|
+
delta_days += 31
|
|
137
|
+
|
|
138
|
+
return _timedelta(self.START_DATE, delta_days)
|
|
139
|
+
|
|
140
|
+
def thingyan_dates(self, year: int) -> tuple[Optional[date], Optional[date]]:
|
|
141
|
+
"""Calculate key dates of Thingyan (Myanmar New Year festival) - Akya day
|
|
142
|
+
and Atat day.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
year:
|
|
146
|
+
Gregorian year.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Akya day date, Atat day date.
|
|
150
|
+
|
|
151
|
+
"""
|
|
152
|
+
if year < self.START_YEAR or year > self.END_YEAR:
|
|
153
|
+
return None, None
|
|
154
|
+
|
|
155
|
+
ja = SY * (year - 638) + MO
|
|
156
|
+
jk = (ja - 2.169918982) if year >= 1950 else (ja - 2.1675)
|
|
157
|
+
|
|
158
|
+
return self.jdn_to_gregorian(round(jk)), self.jdn_to_gregorian(round(ja))
|
|
159
|
+
|
|
160
|
+
def kason_full_moon_date(self, year: int) -> Optional[date]:
|
|
161
|
+
"""Calculate the Gregorian date of Full Moon Day of Kason.
|
|
162
|
+
|
|
163
|
+
15th day of 2nd month (Kason).
|
|
164
|
+
|
|
165
|
+
To calculate, we use the following time delta:
|
|
166
|
+
|
|
167
|
+
* All years:
|
|
168
|
+
29 [1] + 15 - 1 = 43.
|
|
169
|
+
|
|
170
|
+
Args:
|
|
171
|
+
year:
|
|
172
|
+
Gregorian year.
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Gregorian date of Full Moon Day of Kason.
|
|
176
|
+
`None` if the Gregorian year is out of supported range.
|
|
177
|
+
"""
|
|
178
|
+
if not (start_date := self._get_start_date(year)):
|
|
179
|
+
return None
|
|
180
|
+
|
|
181
|
+
return _timedelta(start_date, +43)
|
|
182
|
+
|
|
183
|
+
def waso_full_moon_date(self, year: int) -> Optional[date]:
|
|
184
|
+
"""Calculate the Gregorian date of Full Moon Day of Waso.
|
|
185
|
+
|
|
186
|
+
15th day of 4th month (Waso).
|
|
187
|
+
|
|
188
|
+
To calculate, we use the following time delta:
|
|
189
|
+
|
|
190
|
+
* All years:
|
|
191
|
+
Year_length - 266 [4-12] + 15 - 1 = Year_length - 252.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
year:
|
|
195
|
+
Gregorian year.
|
|
196
|
+
|
|
197
|
+
Returns:
|
|
198
|
+
Gregorian date of Full Moon Day of Waso.
|
|
199
|
+
`None` if the Gregorian year is out of supported range.
|
|
200
|
+
"""
|
|
201
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
202
|
+
return None
|
|
203
|
+
|
|
204
|
+
return _timedelta(next_year_start_date, -252)
|
|
205
|
+
|
|
206
|
+
def thadingyut_full_moon_date(self, year: int) -> Optional[date]:
|
|
207
|
+
"""Calculate the Gregorian date of Full Moon Day of Thadingyut.
|
|
208
|
+
|
|
209
|
+
15th day of 7th month (Thadingyut).
|
|
210
|
+
|
|
211
|
+
To calculate, we use the following time delta:
|
|
212
|
+
|
|
213
|
+
* All years:
|
|
214
|
+
Year_length - 177 [7-12] + 15 - 1 = Year_length - 163.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
year:
|
|
218
|
+
Gregorian year.
|
|
219
|
+
|
|
220
|
+
Returns:
|
|
221
|
+
Gregorian date of Full Moon Day of Thadingyut.
|
|
222
|
+
`None` if the Gregorian year is out of supported range.
|
|
223
|
+
"""
|
|
224
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
return _timedelta(next_year_start_date, -163)
|
|
228
|
+
|
|
229
|
+
def tazaungmon_waxing_moon_date(self, year: int) -> Optional[date]:
|
|
230
|
+
"""Calculate the Gregorian date of 1st Waxing Day of Tazaungmon.
|
|
231
|
+
|
|
232
|
+
1st day of 8th month (Tazaungmon).
|
|
233
|
+
|
|
234
|
+
To calculate, we use the following time delta:
|
|
235
|
+
|
|
236
|
+
* All years:
|
|
237
|
+
Year_length - 148 [8-12] + 1 - 1 = Year_length - 148.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
year:
|
|
241
|
+
Gregorian year.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Gregorian date of 1st Waxing Day of Tazaungmon.
|
|
245
|
+
`None` if the Gregorian year is out of supported range.
|
|
246
|
+
"""
|
|
247
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
248
|
+
return None
|
|
249
|
+
|
|
250
|
+
return _timedelta(next_year_start_date, -148)
|
|
251
|
+
|
|
252
|
+
def tazaungmon_full_moon_date(self, year: int) -> Optional[date]:
|
|
253
|
+
"""Calculate the Gregorian date of Full Moon Day of Tazaungmon.
|
|
254
|
+
|
|
255
|
+
15th day of 8th month (Tazaungmon).
|
|
256
|
+
|
|
257
|
+
To calculate, we use the following time delta:
|
|
258
|
+
|
|
259
|
+
* All years:
|
|
260
|
+
Year_length - 148 [8-12] + 15 - 1 = Year_length - 134.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
year:
|
|
264
|
+
Gregorian year.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
Gregorian date of Full Moon Day of Tazaungmon.
|
|
268
|
+
`None` if the Gregorian year is out of supported range.
|
|
269
|
+
"""
|
|
270
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
return _timedelta(next_year_start_date, -134)
|
|
274
|
+
|
|
275
|
+
def pyatho_waxing_moon_date(self, year: int) -> Optional[date]:
|
|
276
|
+
"""Calculate the Gregorian date of 1st Waxing Day of Pyatho.
|
|
277
|
+
|
|
278
|
+
1st day of 10th month (Pyatho).
|
|
279
|
+
|
|
280
|
+
To calculate, we use the following time delta:
|
|
281
|
+
|
|
282
|
+
* All years:
|
|
283
|
+
Year_length - 89 [10-12] + 1 - 1 = Year_length - 89.
|
|
284
|
+
|
|
285
|
+
Args:
|
|
286
|
+
year:
|
|
287
|
+
Gregorian year.
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
Gregorian date of 1st Waxing Day of Pyatho.
|
|
291
|
+
`None` if the Gregorian year is out of supported range.
|
|
292
|
+
"""
|
|
293
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
294
|
+
return None
|
|
295
|
+
|
|
296
|
+
return _timedelta(next_year_start_date, -89)
|
|
297
|
+
|
|
298
|
+
def tabaung_full_moon_date(self, year: int) -> Optional[date]:
|
|
299
|
+
"""Calculate the Gregorian date of Full Moon Day of Tabaung.
|
|
300
|
+
|
|
301
|
+
15th day of 12th month (Tabaung).
|
|
302
|
+
|
|
303
|
+
To calculate, we use the following time delta:
|
|
304
|
+
|
|
305
|
+
* All years:
|
|
306
|
+
Year_length - 30 [12] + 15 - 1 = Year_length - 16.
|
|
307
|
+
|
|
308
|
+
Args:
|
|
309
|
+
year:
|
|
310
|
+
Gregorian year.
|
|
311
|
+
|
|
312
|
+
Returns:
|
|
313
|
+
Gregorian date of Full Moon Day of Tabaung.
|
|
314
|
+
`None` if the Gregorian year is out of supported range.
|
|
315
|
+
"""
|
|
316
|
+
if not (next_year_start_date := self._get_start_date(year + 1)):
|
|
317
|
+
return None
|
|
318
|
+
|
|
319
|
+
return _timedelta(next_year_start_date, -16)
|
holidays/calendars/chinese.py
CHANGED
|
@@ -14,7 +14,7 @@ from datetime import date
|
|
|
14
14
|
from typing import Optional
|
|
15
15
|
|
|
16
16
|
from holidays.calendars.custom import _CustomCalendar
|
|
17
|
-
from holidays.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, SEP, OCT, NOV
|
|
17
|
+
from holidays.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, SEP, OCT, NOV, DEC
|
|
18
18
|
|
|
19
19
|
CHINESE_CALENDAR = "CHINESE_CALENDAR"
|
|
20
20
|
KOREAN_CALENDAR = "KOREAN_CALENDAR"
|
|
@@ -1307,6 +1307,24 @@ class _ChineseLunisolar:
|
|
|
1307
1307
|
2053: (FEB, 18),
|
|
1308
1308
|
}
|
|
1309
1309
|
|
|
1310
|
+
WINTER_SOLSTICE_THRESHOLDS: dict[str, dict[str, dict[int, int]]] = {
|
|
1311
|
+
# UTC+7.
|
|
1312
|
+
VIETNAMESE_CALENDAR: {
|
|
1313
|
+
"dec_21": {0: 1980, 1: 2017, 2: 2050, 3: 2083},
|
|
1314
|
+
"dec_23": {3: 1943},
|
|
1315
|
+
},
|
|
1316
|
+
# UTC+8.
|
|
1317
|
+
CHINESE_CALENDAR: {
|
|
1318
|
+
"dec_21": {0: 1988, 1: 2021, 2: 2058, 3: 2091},
|
|
1319
|
+
"dec_23": {3: 1947},
|
|
1320
|
+
},
|
|
1321
|
+
# UTC+9.
|
|
1322
|
+
KOREAN_CALENDAR: {
|
|
1323
|
+
"dec_21": {0: 1992, 1: 2029, 2: 2062, 3: 2099},
|
|
1324
|
+
"dec_23": {3: 1955},
|
|
1325
|
+
},
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1310
1328
|
def __init__(self, calendar: str = CHINESE_CALENDAR) -> None:
|
|
1311
1329
|
self.__verify_calendar(calendar)
|
|
1312
1330
|
self.__calendar = calendar
|
|
@@ -1359,6 +1377,26 @@ class _ChineseLunisolar:
|
|
|
1359
1377
|
def mid_autumn_date(self, year: int, calendar=None) -> tuple[Optional[date], bool]:
|
|
1360
1378
|
return self._get_holiday(MID_AUTUMN, year, calendar)
|
|
1361
1379
|
|
|
1380
|
+
def winter_solstice_date(self, year: int, calendar=None) -> tuple[Optional[date], bool]:
|
|
1381
|
+
"""Return Winter Solstice (22nd solar term in Chinese Lunisolar calendar) date.
|
|
1382
|
+
|
|
1383
|
+
!!! note "Note"
|
|
1384
|
+
This approximation is reliable for 1941-2099 years.
|
|
1385
|
+
"""
|
|
1386
|
+
calendar = calendar or self.__calendar
|
|
1387
|
+
self.__verify_calendar(calendar)
|
|
1388
|
+
|
|
1389
|
+
thresholds = self.WINTER_SOLSTICE_THRESHOLDS[calendar]
|
|
1390
|
+
year_mod = year % 4
|
|
1391
|
+
if year >= thresholds["dec_21"][year_mod]:
|
|
1392
|
+
day = 21
|
|
1393
|
+
elif year <= thresholds["dec_23"].get(year_mod, 0):
|
|
1394
|
+
day = 23
|
|
1395
|
+
else:
|
|
1396
|
+
day = 22
|
|
1397
|
+
|
|
1398
|
+
return date(year, DEC, day), not (1941 <= year <= 2099)
|
|
1399
|
+
|
|
1362
1400
|
|
|
1363
1401
|
class _CustomChineseHolidays(_CustomCalendar, _ChineseLunisolar):
|
|
1364
1402
|
pass
|
holidays/calendars/hebrew.py
CHANGED
|
@@ -1602,8 +1602,8 @@ class _HebrewLunisolar:
|
|
|
1602
1602
|
dt = getattr(self, f"{holiday}_DATES", {}).get(year, ())
|
|
1603
1603
|
return date(year, *dt) if dt else None
|
|
1604
1604
|
|
|
1605
|
-
def hanukkah_date(self, year: int) -> set[
|
|
1606
|
-
return {
|
|
1605
|
+
def hanukkah_date(self, year: int) -> set[date]:
|
|
1606
|
+
return {dt for y in (year - 1, year) if (dt := self._get_holiday(HANUKKAH, y)) is not None}
|
|
1607
1607
|
|
|
1608
1608
|
def israel_independence_date(self, year: int) -> Optional[date]:
|
|
1609
1609
|
return self._get_holiday(INDEPENDENCE_DAY, year)
|
holidays/calendars/thai.py
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
# License: MIT (see LICENSE file)
|
|
12
12
|
|
|
13
13
|
from datetime import date
|
|
14
|
-
from functools import
|
|
14
|
+
from functools import cache
|
|
15
15
|
from typing import Optional
|
|
16
16
|
|
|
17
17
|
from holidays.calendars.gregorian import _timedelta
|
|
@@ -100,6 +100,8 @@ class _ThaiLunisolar:
|
|
|
100
100
|
References:
|
|
101
101
|
* <https://web.archive.org/web/20241016080156/https://www.ninenik.com/แนวทางฟังก์ชั่น_php_อย่างง่ายกับการหาวันข้างขึ้นข้างแรม-1021.html>
|
|
102
102
|
* <https://web.archive.org/web/20250119171416/https://www.myhora.com/ปฏิทิน/ปฏิทิน-พ.ศ.2560.aspx>
|
|
103
|
+
* <https://web.archive.org/web/20250302100842/https://calendar.kunthet.com/#/>
|
|
104
|
+
* [2025 Khmer Lunar Calendar](https://web.archive.org/web/20250921045847/https://static1.squarespace.com/static/67722f65f2908e531b5f326d/t/678a87776503cc3f8bc538ac/1737131904673/2025Calendar-compressed.pdf)
|
|
103
105
|
|
|
104
106
|
Example:
|
|
105
107
|
|
|
@@ -293,7 +295,7 @@ class _ThaiLunisolar:
|
|
|
293
295
|
f"Unknown calendar name: {calendar}. Use `KHMER_CALENDAR` or `THAI_CALENDAR`."
|
|
294
296
|
)
|
|
295
297
|
|
|
296
|
-
@
|
|
298
|
+
@cache
|
|
297
299
|
def _get_start_date(self, year: int) -> Optional[date]:
|
|
298
300
|
"""Calculate the start date of that particular Thai Lunar Calendar Year.
|
|
299
301
|
|
|
@@ -320,6 +322,51 @@ class _ThaiLunisolar:
|
|
|
320
322
|
|
|
321
323
|
return _timedelta(_ThaiLunisolar.START_DATE, delta_days)
|
|
322
324
|
|
|
325
|
+
@cache
|
|
326
|
+
def buddhist_sabbath_dates(self, year: int) -> set[date]:
|
|
327
|
+
"""Return all Buddhist Sabbath (Uposatha) days in a given Gregorian year.
|
|
328
|
+
|
|
329
|
+
This function works independently of the calendar system in use,
|
|
330
|
+
whether `THAI_CALENDAR` or `KHMER_CALENDAR`.
|
|
331
|
+
|
|
332
|
+
Args:
|
|
333
|
+
year:
|
|
334
|
+
The Gregorian year.
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
A set of `date` objects representing all Buddhist Sabbath days in the specified
|
|
338
|
+
Gregorian year. Returns an empty set if the year is outside the supported range.
|
|
339
|
+
"""
|
|
340
|
+
start_date = self._get_start_date(year)
|
|
341
|
+
if not start_date:
|
|
342
|
+
return set()
|
|
343
|
+
|
|
344
|
+
# Initializes Thai lunar month lengths.
|
|
345
|
+
months = [29, 30] * 6
|
|
346
|
+
if year in _ThaiLunisolar.ATHIKAMAT_YEARS_GREGORIAN:
|
|
347
|
+
months.insert(7, 30)
|
|
348
|
+
elif year in _ThaiLunisolar.ATHIKAWAN_YEARS_GREGORIAN:
|
|
349
|
+
months[6] += 1
|
|
350
|
+
# Includes first two months of the next Thai lunar year to ensure all Buddhist Sabbaths
|
|
351
|
+
# in the Gregorian year are captured.
|
|
352
|
+
months.extend([29, 30])
|
|
353
|
+
|
|
354
|
+
buddhist_sabbaths: set[date] = set()
|
|
355
|
+
day_cursor = start_date
|
|
356
|
+
for month_days in months:
|
|
357
|
+
if day_cursor.year > year:
|
|
358
|
+
break
|
|
359
|
+
# Buddhist Sabbaths: 8 Waxing, 15 Waxing, 8 Waning, 14/15 Waning.
|
|
360
|
+
for offset in (7, 14, 22, month_days - 1):
|
|
361
|
+
buddhist_sabbath = _timedelta(day_cursor, offset)
|
|
362
|
+
if buddhist_sabbath.year == year:
|
|
363
|
+
buddhist_sabbaths.add(buddhist_sabbath)
|
|
364
|
+
elif buddhist_sabbath.year > year:
|
|
365
|
+
break
|
|
366
|
+
day_cursor = _timedelta(day_cursor, month_days)
|
|
367
|
+
|
|
368
|
+
return buddhist_sabbaths
|
|
369
|
+
|
|
323
370
|
def makha_bucha_date(self, year: int, calendar=None) -> Optional[date]:
|
|
324
371
|
"""Calculate the estimated Gregorian date of Makha Bucha.
|
|
325
372
|
|
holidays/countries/__init__.py
CHANGED
|
@@ -20,6 +20,7 @@ from holidays.countries.american_samoa import AmericanSamoa, AS, ASM, HolidaysAS
|
|
|
20
20
|
from holidays.countries.andorra import Andorra, AD, AND
|
|
21
21
|
from holidays.countries.angola import Angola, AO, AGO
|
|
22
22
|
from holidays.countries.anguilla import Anguilla, AI, AIA
|
|
23
|
+
from holidays.countries.antarctica import Antarctica, AQ, ATA
|
|
23
24
|
from holidays.countries.antigua_and_barbuda import AntiguaAndBarbuda, AG, ATG
|
|
24
25
|
from holidays.countries.argentina import Argentina, AR, ARG
|
|
25
26
|
from holidays.countries.armenia import Armenia, AM, ARM
|
|
@@ -41,7 +42,9 @@ from holidays.countries.bolivia import Bolivia, BO, BOL
|
|
|
41
42
|
from holidays.countries.bonaire_sint_eustatius_and_saba import BonaireSintEustatiusAndSaba, BQ, BES
|
|
42
43
|
from holidays.countries.bosnia_and_herzegovina import BosniaAndHerzegovina, BA, BIH
|
|
43
44
|
from holidays.countries.botswana import Botswana, BW, BWA
|
|
45
|
+
from holidays.countries.bouvet_island import BouvetIsland, BV, BVT
|
|
44
46
|
from holidays.countries.brazil import Brazil, BR, BRA
|
|
47
|
+
from holidays.countries.british_indian_ocean_territory import BritishIndianOceanTerritory, IO, IOT
|
|
45
48
|
from holidays.countries.british_virgin_islands import BritishVirginIslands, VG, VGB
|
|
46
49
|
from holidays.countries.brunei import Brunei, BN, BRN
|
|
47
50
|
from holidays.countries.bulgaria import Bulgaria, BG, BLG
|
|
@@ -111,6 +114,11 @@ from holidays.countries.guinea import Guinea, GN, GIN
|
|
|
111
114
|
from holidays.countries.guinea_bissau import GuineaBissau, GW, GNB
|
|
112
115
|
from holidays.countries.guyana import Guyana, GY, GUY
|
|
113
116
|
from holidays.countries.haiti import Haiti, HT, HTI
|
|
117
|
+
from holidays.countries.heard_island_and_mcdonald_islands import (
|
|
118
|
+
HeardIslandAndMcDonaldIslands,
|
|
119
|
+
HM,
|
|
120
|
+
HMD,
|
|
121
|
+
)
|
|
114
122
|
from holidays.countries.honduras import Honduras, HN, HND
|
|
115
123
|
from holidays.countries.hongkong import HongKong, HK, HKG
|
|
116
124
|
from holidays.countries.hungary import Hungary, HU, HUN
|
|
@@ -163,6 +171,7 @@ from holidays.countries.montenegro import Montenegro, ME, MNE
|
|
|
163
171
|
from holidays.countries.montserrat import Montserrat, MS, MSR
|
|
164
172
|
from holidays.countries.morocco import Morocco, MA, MOR
|
|
165
173
|
from holidays.countries.mozambique import Mozambique, MZ, MOZ
|
|
174
|
+
from holidays.countries.myanmar import Myanmar, MM, MMR
|
|
166
175
|
from holidays.countries.namibia import Namibia, NA, NAM
|
|
167
176
|
from holidays.countries.nauru import Nauru, NR, NRU
|
|
168
177
|
from holidays.countries.nepal import Nepal, NP, NPL
|
|
@@ -174,6 +183,7 @@ from holidays.countries.niger import Niger, NE, NER
|
|
|
174
183
|
from holidays.countries.nigeria import Nigeria, NG, NGA
|
|
175
184
|
from holidays.countries.niue import Niue, NU, NIU
|
|
176
185
|
from holidays.countries.norfolk_island import NorfolkIsland, NF, NFK
|
|
186
|
+
from holidays.countries.north_korea import NorthKorea, KP, PRK
|
|
177
187
|
from holidays.countries.north_macedonia import NorthMacedonia, MK, MKD
|
|
178
188
|
from holidays.countries.northern_mariana_islands import NorthernMarianaIslands, MP, MNP, HolidaysMP
|
|
179
189
|
from holidays.countries.norway import Norway, NO, NOR
|
|
@@ -196,6 +206,11 @@ from holidays.countries.romania import Romania, RO, ROU
|
|
|
196
206
|
from holidays.countries.russia import Russia, RU, RUS
|
|
197
207
|
from holidays.countries.rwanda import Rwanda, RW, RWA
|
|
198
208
|
from holidays.countries.saint_barthelemy import SaintBarthelemy, BL, BLM, HolidaysBL
|
|
209
|
+
from holidays.countries.saint_helena_ascension_and_tristan_da_cunha import (
|
|
210
|
+
SaintHelenaAscensionAndTristanDaCunha,
|
|
211
|
+
SH,
|
|
212
|
+
SHN,
|
|
213
|
+
)
|
|
199
214
|
from holidays.countries.saint_kitts_and_nevis import SaintKittsAndNevis, KN, KNA
|
|
200
215
|
from holidays.countries.saint_lucia import SaintLucia, LC, LCA
|
|
201
216
|
from holidays.countries.saint_martin import SaintMartin, MF, MAF, HolidaysMF
|
|
@@ -234,6 +249,7 @@ from holidays.countries.south_korea import SouthKorea, KR, KOR, Korea
|
|
|
234
249
|
from holidays.countries.south_sudan import SouthSudan, SS, SSD
|
|
235
250
|
from holidays.countries.spain import Spain, ES, ESP
|
|
236
251
|
from holidays.countries.sri_lanka import SriLanka, LK, LKA
|
|
252
|
+
from holidays.countries.sudan import Sudan, SD, SDN
|
|
237
253
|
from holidays.countries.suriname import Suriname, SR, SUR
|
|
238
254
|
from holidays.countries.svalbard_and_jan_mayen import SvalbardAndJanMayen, SJ, SJM, HolidaysSJ
|
|
239
255
|
from holidays.countries.sweden import Sweden, SE, SWE
|
|
@@ -23,7 +23,7 @@ class Afghanistan(HolidayBase, InternationalHolidays, IslamicHolidays, PersianCa
|
|
|
23
23
|
|
|
24
24
|
References:
|
|
25
25
|
* <https://en.wikipedia.org/wiki/Public_holidays_in_Afghanistan>
|
|
26
|
-
* <https://web.archive.org/web/
|
|
26
|
+
* <https://web.archive.org/web/20250903162748/https://www.timeanddate.com/holidays/afghanistan>
|
|
27
27
|
* <https://en.wikipedia.org/wiki/Workweek_and_weekend>
|
|
28
28
|
"""
|
|
29
29
|
|
|
@@ -131,16 +131,17 @@ class AfghanistanIslamicHolidays(_CustomIslamicHolidays):
|
|
|
131
131
|
2021: (AUG, 19),
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
EID_AL_ADHA_DATES_CONFIRMED_YEARS = (2014,
|
|
134
|
+
EID_AL_ADHA_DATES_CONFIRMED_YEARS = (2014, 2025)
|
|
135
135
|
EID_AL_ADHA_DATES = {
|
|
136
136
|
2014: (OCT, 5),
|
|
137
137
|
2016: (SEP, 13),
|
|
138
138
|
2017: (SEP, 2),
|
|
139
139
|
2018: (AUG, 22),
|
|
140
140
|
2024: (JUN, 17),
|
|
141
|
+
2025: (JUN, 7),
|
|
141
142
|
}
|
|
142
143
|
|
|
143
|
-
EID_AL_FITR_DATES_CONFIRMED_YEARS = (2014,
|
|
144
|
+
EID_AL_FITR_DATES_CONFIRMED_YEARS = (2014, 2025)
|
|
144
145
|
EID_AL_FITR_DATES = {
|
|
145
146
|
2014: (JUL, 29),
|
|
146
147
|
2015: (JUL, 18),
|
|
@@ -150,7 +151,7 @@ class AfghanistanIslamicHolidays(_CustomIslamicHolidays):
|
|
|
150
151
|
2023: (APR, 22),
|
|
151
152
|
}
|
|
152
153
|
|
|
153
|
-
MAWLID_DATES_CONFIRMED_YEARS = (2014,
|
|
154
|
+
MAWLID_DATES_CONFIRMED_YEARS = (2014, 2025)
|
|
154
155
|
MAWLID_DATES = {
|
|
155
156
|
2014: (JAN, 14),
|
|
156
157
|
2015: ((JAN, 3), (DEC, 24)),
|
|
@@ -160,9 +161,10 @@ class AfghanistanIslamicHolidays(_CustomIslamicHolidays):
|
|
|
160
161
|
2019: (NOV, 10),
|
|
161
162
|
2021: (OCT, 19),
|
|
162
163
|
2024: (SEP, 16),
|
|
164
|
+
2025: (SEP, 5),
|
|
163
165
|
}
|
|
164
166
|
|
|
165
|
-
RAMADAN_BEGINNING_DATES_CONFIRMED_YEARS = (2014,
|
|
167
|
+
RAMADAN_BEGINNING_DATES_CONFIRMED_YEARS = (2014, 2025)
|
|
166
168
|
RAMADAN_BEGINNING_DATES = {
|
|
167
169
|
2014: (JUN, 29),
|
|
168
170
|
2016: (JUN, 7),
|