holidays 0.25__py3-none-any.whl → 0.27__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.
Files changed (331) hide show
  1. holidays/__init__.py +1 -1
  2. holidays/calendars/__init__.py +9 -7
  3. holidays/calendars/buddhist.py +445 -0
  4. holidays/calendars/chinese.py +1238 -431
  5. holidays/calendars/custom.py +1 -3
  6. holidays/calendars/hebrew.py +2 -2
  7. holidays/calendars/hindu.py +445 -0
  8. holidays/calendars/islamic.py +1347 -1347
  9. holidays/calendars/thai.py +229 -38
  10. holidays/countries/__init__.py +8 -0
  11. holidays/countries/albania.py +6 -17
  12. holidays/countries/andorra.py +2 -6
  13. holidays/countries/angola.py +53 -39
  14. holidays/countries/argentina.py +25 -35
  15. holidays/countries/armenia.py +1 -0
  16. holidays/countries/aruba.py +109 -48
  17. holidays/countries/australia.py +31 -69
  18. holidays/countries/austria.py +1 -0
  19. holidays/countries/azerbaijan.py +44 -71
  20. holidays/countries/bahrain.py +7 -7
  21. holidays/countries/bangladesh.py +1 -3
  22. holidays/countries/belarus.py +2 -3
  23. holidays/countries/belize.py +128 -0
  24. holidays/countries/bolivia.py +2 -6
  25. holidays/countries/bosnia_and_herzegovina.py +5 -17
  26. holidays/countries/botswana.py +37 -44
  27. holidays/countries/brazil.py +4 -7
  28. holidays/countries/brunei.py +427 -0
  29. holidays/countries/bulgaria.py +3 -6
  30. holidays/countries/burkina_faso.py +141 -0
  31. holidays/countries/burundi.py +2 -5
  32. holidays/countries/cambodia.py +323 -0
  33. holidays/countries/cameroon.py +183 -0
  34. holidays/countries/canada.py +20 -28
  35. holidays/countries/chad.py +133 -0
  36. holidays/countries/chile.py +6 -13
  37. holidays/countries/china.py +21 -25
  38. holidays/countries/colombia.py +18 -15
  39. holidays/countries/costa_rica.py +25 -27
  40. holidays/countries/cuba.py +28 -15
  41. holidays/countries/curacao.py +100 -46
  42. holidays/countries/cyprus.py +3 -6
  43. holidays/countries/czechia.py +4 -12
  44. holidays/countries/denmark.py +2 -3
  45. holidays/countries/dominican_republic.py +2 -3
  46. holidays/countries/ecuador.py +55 -54
  47. holidays/countries/egypt.py +2 -5
  48. holidays/countries/el_salvador.py +101 -0
  49. holidays/countries/eswatini.py +34 -44
  50. holidays/countries/ethiopia.py +7 -14
  51. holidays/countries/finland.py +2 -3
  52. holidays/countries/france.py +1 -0
  53. holidays/countries/gabon.py +139 -0
  54. holidays/countries/georgia.py +1 -0
  55. holidays/countries/germany.py +1 -0
  56. holidays/countries/greece.py +7 -6
  57. holidays/countries/honduras.py +17 -13
  58. holidays/countries/hongkong.py +117 -126
  59. holidays/countries/hungary.py +93 -92
  60. holidays/countries/iceland.py +1 -0
  61. holidays/countries/india.py +4 -11
  62. holidays/countries/indonesia.py +178 -142
  63. holidays/countries/ireland.py +5 -15
  64. holidays/countries/isle_of_man.py +23 -5
  65. holidays/countries/israel.py +12 -24
  66. holidays/countries/italy.py +6 -7
  67. holidays/countries/jamaica.py +10 -18
  68. holidays/countries/japan.py +11 -16
  69. holidays/countries/kazakhstan.py +7 -22
  70. holidays/countries/kenya.py +44 -26
  71. holidays/countries/kyrgyzstan.py +2 -5
  72. holidays/countries/latvia.py +2 -6
  73. holidays/countries/lesotho.py +52 -32
  74. holidays/countries/liechtenstein.py +1 -0
  75. holidays/countries/lithuania.py +4 -12
  76. holidays/countries/madagascar.py +3 -9
  77. holidays/countries/malawi.py +34 -26
  78. holidays/countries/malaysia.py +335 -343
  79. holidays/countries/marshall_islands.py +4 -9
  80. holidays/countries/mexico.py +2 -3
  81. holidays/countries/moldova.py +4 -6
  82. holidays/countries/monaco.py +17 -26
  83. holidays/countries/montenegro.py +34 -24
  84. holidays/countries/morocco.py +8 -5
  85. holidays/countries/mozambique.py +35 -31
  86. holidays/countries/namibia.py +54 -35
  87. holidays/countries/netherlands.py +1 -0
  88. holidays/countries/new_zealand.py +166 -134
  89. holidays/countries/nicaragua.py +27 -22
  90. holidays/countries/nigeria.py +6 -17
  91. holidays/countries/north_macedonia.py +3 -8
  92. holidays/countries/norway.py +2 -3
  93. holidays/countries/pakistan.py +73 -75
  94. holidays/countries/panama.py +25 -24
  95. holidays/countries/paraguay.py +55 -47
  96. holidays/countries/peru.py +1 -0
  97. holidays/countries/philippines.py +6 -2
  98. holidays/countries/poland.py +4 -9
  99. holidays/countries/portugal.py +4 -11
  100. holidays/countries/romania.py +4 -5
  101. holidays/countries/russia.py +1 -0
  102. holidays/countries/san_marino.py +26 -27
  103. holidays/countries/saudi_arabia.py +8 -22
  104. holidays/countries/serbia.py +22 -31
  105. holidays/countries/singapore.py +181 -189
  106. holidays/countries/slovakia.py +2 -4
  107. holidays/countries/south_africa.py +60 -62
  108. holidays/countries/south_korea.py +59 -26
  109. holidays/countries/spain.py +7 -10
  110. holidays/countries/sweden.py +2 -3
  111. holidays/countries/switzerland.py +1 -0
  112. holidays/countries/taiwan.py +20 -20
  113. holidays/countries/thailand.py +36 -82
  114. holidays/countries/turkey.py +1 -3
  115. holidays/countries/ukraine.py +7 -18
  116. holidays/countries/united_arab_emirates.py +23 -31
  117. holidays/countries/united_kingdom.py +124 -116
  118. holidays/countries/united_states.py +42 -72
  119. holidays/countries/uruguay.py +1 -0
  120. holidays/countries/vatican_city.py +64 -32
  121. holidays/countries/venezuela.py +9 -6
  122. holidays/countries/vietnam.py +6 -20
  123. holidays/countries/zambia.py +63 -33
  124. holidays/countries/zimbabwe.py +56 -37
  125. holidays/financial/european_central_bank.py +15 -16
  126. holidays/financial/ny_stock_exchange.py +80 -86
  127. holidays/groups/__init__.py +18 -0
  128. holidays/groups/buddhist.py +71 -0
  129. holidays/groups/chinese.py +235 -0
  130. holidays/groups/christian.py +483 -0
  131. holidays/groups/hindu.py +71 -0
  132. holidays/groups/international.py +157 -0
  133. holidays/groups/islamic.py +288 -0
  134. holidays/groups/thai.py +157 -0
  135. holidays/helpers.py +20 -0
  136. holidays/holiday_base.py +54 -76
  137. holidays/holiday_groups.py +11 -1053
  138. holidays/locale/am/LC_MESSAGES/ET.mo +0 -0
  139. holidays/locale/am/LC_MESSAGES/ET.po +20 -15
  140. holidays/locale/ar/LC_MESSAGES/CA.mo +0 -0
  141. holidays/locale/ar/LC_MESSAGES/CA.po +184 -0
  142. holidays/locale/ar/LC_MESSAGES/ET.mo +0 -0
  143. holidays/locale/ar/LC_MESSAGES/ET.po +92 -0
  144. holidays/locale/ar/LC_MESSAGES/UA.mo +0 -0
  145. holidays/locale/ar/LC_MESSAGES/UA.po +97 -0
  146. holidays/locale/be/LC_MESSAGES/BY.po +11 -13
  147. holidays/locale/bg/LC_MESSAGES/BG.po +13 -15
  148. holidays/locale/da/LC_MESSAGES/DK.po +13 -12
  149. holidays/locale/de/LC_MESSAGES/AT.po +14 -14
  150. holidays/locale/de/LC_MESSAGES/CH.po +91 -56
  151. holidays/locale/de/LC_MESSAGES/DE.po +32 -32
  152. holidays/locale/de/LC_MESSAGES/LI.po +23 -23
  153. holidays/locale/el/LC_MESSAGES/CY.po +16 -16
  154. holidays/locale/el/LC_MESSAGES/GR.mo +0 -0
  155. holidays/locale/el/LC_MESSAGES/GR.po +21 -17
  156. holidays/locale/en/LC_MESSAGES/CA.po +43 -43
  157. holidays/locale/en_US/LC_MESSAGES/AM.mo +0 -0
  158. holidays/locale/en_US/LC_MESSAGES/AM.po +20 -20
  159. holidays/locale/en_US/LC_MESSAGES/AR.mo +0 -0
  160. holidays/locale/en_US/LC_MESSAGES/AR.po +34 -33
  161. holidays/locale/en_US/LC_MESSAGES/AT.po +13 -13
  162. holidays/locale/en_US/LC_MESSAGES/AW.mo +0 -0
  163. holidays/locale/en_US/LC_MESSAGES/AW.po +87 -0
  164. holidays/locale/en_US/LC_MESSAGES/BG.po +13 -15
  165. holidays/locale/en_US/LC_MESSAGES/BN.mo +0 -0
  166. holidays/locale/en_US/LC_MESSAGES/BN.po +96 -0
  167. holidays/locale/en_US/LC_MESSAGES/BY.po +11 -13
  168. holidays/locale/en_US/LC_MESSAGES/CA.mo +0 -0
  169. holidays/locale/en_US/LC_MESSAGES/CA.po +70 -37
  170. holidays/locale/en_US/LC_MESSAGES/CH.po +91 -56
  171. holidays/locale/en_US/LC_MESSAGES/CL.po +39 -38
  172. holidays/locale/en_US/LC_MESSAGES/CO.mo +0 -0
  173. holidays/locale/en_US/LC_MESSAGES/CO.po +27 -27
  174. holidays/locale/en_US/LC_MESSAGES/CR.mo +0 -0
  175. holidays/locale/en_US/LC_MESSAGES/CR.po +19 -19
  176. holidays/locale/en_US/LC_MESSAGES/CU.po +10 -10
  177. holidays/locale/en_US/LC_MESSAGES/CW.mo +0 -0
  178. holidays/locale/en_US/LC_MESSAGES/CW.po +82 -0
  179. holidays/locale/en_US/LC_MESSAGES/CY.po +16 -16
  180. holidays/locale/en_US/LC_MESSAGES/DE.po +30 -30
  181. holidays/locale/en_US/LC_MESSAGES/DK.po +12 -11
  182. holidays/locale/en_US/LC_MESSAGES/DO.po +12 -12
  183. holidays/locale/en_US/LC_MESSAGES/EC.po +11 -12
  184. holidays/locale/en_US/LC_MESSAGES/ET.mo +0 -0
  185. holidays/locale/en_US/LC_MESSAGES/ET.po +20 -15
  186. holidays/locale/en_US/LC_MESSAGES/FI.po +15 -15
  187. holidays/locale/en_US/LC_MESSAGES/FR.po +27 -24
  188. holidays/locale/en_US/LC_MESSAGES/GE.po +23 -27
  189. holidays/locale/en_US/LC_MESSAGES/GR.mo +0 -0
  190. holidays/locale/en_US/LC_MESSAGES/GR.po +21 -17
  191. holidays/locale/en_US/LC_MESSAGES/HN.mo +0 -0
  192. holidays/locale/en_US/LC_MESSAGES/HN.po +17 -12
  193. holidays/locale/en_US/LC_MESSAGES/HU.mo +0 -0
  194. holidays/locale/en_US/LC_MESSAGES/HU.po +109 -0
  195. holidays/locale/en_US/LC_MESSAGES/IS.po +17 -17
  196. holidays/locale/en_US/LC_MESSAGES/JP.po +25 -25
  197. holidays/locale/en_US/LC_MESSAGES/KH.mo +0 -0
  198. holidays/locale/en_US/LC_MESSAGES/KH.po +139 -0
  199. holidays/locale/en_US/LC_MESSAGES/LI.po +22 -22
  200. holidays/locale/en_US/LC_MESSAGES/MC.mo +0 -0
  201. holidays/locale/en_US/LC_MESSAGES/MC.po +27 -27
  202. holidays/locale/en_US/LC_MESSAGES/MD.po +13 -13
  203. holidays/locale/en_US/LC_MESSAGES/MX.po +9 -12
  204. holidays/locale/en_US/LC_MESSAGES/NI.mo +0 -0
  205. holidays/locale/en_US/LC_MESSAGES/NI.po +15 -15
  206. holidays/locale/en_US/LC_MESSAGES/NL.po +12 -12
  207. holidays/locale/en_US/LC_MESSAGES/NO.po +13 -13
  208. holidays/locale/en_US/LC_MESSAGES/PE.po +30 -30
  209. holidays/locale/en_US/LC_MESSAGES/PL.po +38 -21
  210. holidays/locale/en_US/LC_MESSAGES/PT.po +39 -36
  211. holidays/locale/en_US/LC_MESSAGES/PY.po +16 -16
  212. holidays/locale/en_US/LC_MESSAGES/RO.po +12 -12
  213. holidays/locale/en_US/LC_MESSAGES/RS.mo +0 -0
  214. holidays/locale/en_US/LC_MESSAGES/RS.po +17 -19
  215. holidays/locale/en_US/LC_MESSAGES/RU.po +11 -10
  216. holidays/locale/en_US/LC_MESSAGES/SE.po +19 -19
  217. holidays/locale/en_US/LC_MESSAGES/SK.po +17 -18
  218. holidays/locale/en_US/LC_MESSAGES/TH.po +41 -41
  219. holidays/locale/en_US/LC_MESSAGES/UA.po +18 -19
  220. holidays/locale/en_US/LC_MESSAGES/UY.po +15 -15
  221. holidays/locale/en_US/LC_MESSAGES/VE.po +16 -16
  222. holidays/locale/es/LC_MESSAGES/AR.mo +0 -0
  223. holidays/locale/es/LC_MESSAGES/AR.po +34 -33
  224. holidays/locale/es/LC_MESSAGES/CL.po +39 -38
  225. holidays/locale/es/LC_MESSAGES/CO.mo +0 -0
  226. holidays/locale/es/LC_MESSAGES/CO.po +24 -24
  227. holidays/locale/es/LC_MESSAGES/CR.mo +0 -0
  228. holidays/locale/es/LC_MESSAGES/CR.po +19 -19
  229. holidays/locale/es/LC_MESSAGES/CU.po +10 -10
  230. holidays/locale/es/LC_MESSAGES/DO.po +12 -12
  231. holidays/locale/es/LC_MESSAGES/EC.po +11 -12
  232. holidays/locale/es/LC_MESSAGES/HN.mo +0 -0
  233. holidays/locale/es/LC_MESSAGES/HN.po +17 -12
  234. holidays/locale/es/LC_MESSAGES/MX.po +9 -12
  235. holidays/locale/es/LC_MESSAGES/NI.po +12 -12
  236. holidays/locale/es/LC_MESSAGES/PE.po +30 -30
  237. holidays/locale/es/LC_MESSAGES/PY.po +16 -16
  238. holidays/locale/es/LC_MESSAGES/UY.po +15 -15
  239. holidays/locale/es/LC_MESSAGES/VE.po +16 -16
  240. holidays/locale/fi/LC_MESSAGES/FI.po +16 -16
  241. holidays/locale/fr/LC_MESSAGES/CA.po +43 -43
  242. holidays/locale/fr/LC_MESSAGES/CH.po +91 -56
  243. holidays/locale/fr/LC_MESSAGES/FR.po +27 -24
  244. holidays/locale/fr/LC_MESSAGES/MC.po +23 -23
  245. holidays/locale/hu/LC_MESSAGES/HU.mo +0 -0
  246. holidays/locale/hu/LC_MESSAGES/HU.po +109 -0
  247. holidays/locale/hy/LC_MESSAGES/AM.po +16 -16
  248. holidays/locale/is/LC_MESSAGES/IS.po +18 -18
  249. holidays/locale/it/LC_MESSAGES/CH.po +91 -56
  250. holidays/locale/ja/LC_MESSAGES/JP.po +25 -25
  251. holidays/locale/ka/LC_MESSAGES/GE.po +23 -27
  252. holidays/locale/km/LC_MESSAGES/KH.mo +0 -0
  253. holidays/locale/km/LC_MESSAGES/KH.po +139 -0
  254. holidays/locale/ms/LC_MESSAGES/BN.mo +0 -0
  255. holidays/locale/ms/LC_MESSAGES/BN.po +96 -0
  256. holidays/locale/nl/LC_MESSAGES/AW.mo +0 -0
  257. holidays/locale/nl/LC_MESSAGES/AW.po +87 -0
  258. holidays/locale/nl/LC_MESSAGES/CW.mo +0 -0
  259. holidays/locale/nl/LC_MESSAGES/CW.po +82 -0
  260. holidays/locale/nl/LC_MESSAGES/NL.po +13 -13
  261. holidays/locale/no/LC_MESSAGES/NO.po +14 -14
  262. holidays/locale/pap/LC_MESSAGES/AW.mo +0 -0
  263. holidays/locale/pap/LC_MESSAGES/AW.po +87 -0
  264. holidays/locale/pap/LC_MESSAGES/CW.mo +0 -0
  265. holidays/locale/pap/LC_MESSAGES/CW.po +82 -0
  266. holidays/locale/pl/LC_MESSAGES/PL.po +38 -21
  267. holidays/locale/pt_PT/LC_MESSAGES/PT.po +39 -36
  268. holidays/locale/ro/LC_MESSAGES/MD.po +14 -15
  269. holidays/locale/ro/LC_MESSAGES/RO.po +13 -14
  270. holidays/locale/ru/LC_MESSAGES/RU.po +11 -9
  271. holidays/locale/sk/LC_MESSAGES/SK.po +17 -18
  272. holidays/locale/sr/LC_MESSAGES/RS.mo +0 -0
  273. holidays/locale/sr/LC_MESSAGES/RS.po +15 -17
  274. holidays/locale/sv/LC_MESSAGES/FI.po +16 -16
  275. holidays/locale/sv/LC_MESSAGES/SE.po +20 -20
  276. holidays/locale/th/LC_MESSAGES/BN.mo +0 -0
  277. holidays/locale/th/LC_MESSAGES/BN.po +96 -0
  278. holidays/locale/th/LC_MESSAGES/CA.po +42 -42
  279. holidays/locale/th/LC_MESSAGES/KH.mo +0 -0
  280. holidays/locale/th/LC_MESSAGES/KH.po +145 -0
  281. holidays/locale/th/LC_MESSAGES/TH.po +41 -41
  282. holidays/locale/uk/LC_MESSAGES/AR.mo +0 -0
  283. holidays/locale/uk/LC_MESSAGES/AR.po +35 -35
  284. holidays/locale/uk/LC_MESSAGES/AT.po +15 -16
  285. holidays/locale/uk/LC_MESSAGES/AW.mo +0 -0
  286. holidays/locale/uk/LC_MESSAGES/AW.po +87 -0
  287. holidays/locale/uk/LC_MESSAGES/CH.po +92 -58
  288. holidays/locale/uk/LC_MESSAGES/CL.po +40 -40
  289. holidays/locale/uk/LC_MESSAGES/CO.mo +0 -0
  290. holidays/locale/uk/LC_MESSAGES/CO.po +28 -29
  291. holidays/locale/uk/LC_MESSAGES/CR.mo +0 -0
  292. holidays/locale/uk/LC_MESSAGES/CR.po +20 -21
  293. holidays/locale/uk/LC_MESSAGES/CU.po +11 -12
  294. holidays/locale/uk/LC_MESSAGES/CW.mo +0 -0
  295. holidays/locale/uk/LC_MESSAGES/CW.po +82 -0
  296. holidays/locale/uk/LC_MESSAGES/DE.po +33 -34
  297. holidays/locale/uk/LC_MESSAGES/DK.po +14 -14
  298. holidays/locale/uk/LC_MESSAGES/DO.po +13 -14
  299. holidays/locale/uk/LC_MESSAGES/EC.po +12 -14
  300. holidays/locale/uk/LC_MESSAGES/FI.po +17 -18
  301. holidays/locale/uk/LC_MESSAGES/FR.po +28 -26
  302. holidays/locale/uk/LC_MESSAGES/HN.mo +0 -0
  303. holidays/locale/uk/LC_MESSAGES/HN.po +18 -14
  304. holidays/locale/uk/LC_MESSAGES/HU.mo +0 -0
  305. holidays/locale/uk/LC_MESSAGES/HU.po +109 -0
  306. holidays/locale/uk/LC_MESSAGES/IS.po +19 -20
  307. holidays/locale/uk/LC_MESSAGES/LI.po +24 -25
  308. holidays/locale/uk/LC_MESSAGES/MC.po +27 -28
  309. holidays/locale/uk/LC_MESSAGES/MD.po +14 -15
  310. holidays/locale/uk/LC_MESSAGES/MX.po +10 -14
  311. holidays/locale/uk/LC_MESSAGES/NI.mo +0 -0
  312. holidays/locale/uk/LC_MESSAGES/NI.po +16 -17
  313. holidays/locale/uk/LC_MESSAGES/NL.po +14 -15
  314. holidays/locale/uk/LC_MESSAGES/NO.po +15 -16
  315. holidays/locale/uk/LC_MESSAGES/PE.po +31 -32
  316. holidays/locale/uk/LC_MESSAGES/PL.po +38 -21
  317. holidays/locale/uk/LC_MESSAGES/PY.po +17 -18
  318. holidays/locale/uk/LC_MESSAGES/RO.po +13 -14
  319. holidays/locale/uk/LC_MESSAGES/SE.po +21 -22
  320. holidays/locale/uk/LC_MESSAGES/SK.po +18 -20
  321. holidays/locale/uk/LC_MESSAGES/UA.po +17 -17
  322. holidays/locale/uk/LC_MESSAGES/UY.po +16 -17
  323. holidays/locale/uk/LC_MESSAGES/VE.po +17 -18
  324. holidays/registry.py +21 -12
  325. holidays/utils.py +87 -17
  326. {holidays-0.25.dist-info → holidays-0.27.dist-info}/METADATA +282 -265
  327. holidays-0.27.dist-info/RECORD +449 -0
  328. holidays-0.25.dist-info/RECORD +0 -390
  329. {holidays-0.25.dist-info → holidays-0.27.dist-info}/LICENSE +0 -0
  330. {holidays-0.25.dist-info → holidays-0.27.dist-info}/WHEEL +0 -0
  331. {holidays-0.25.dist-info → holidays-0.27.dist-info}/top_level.txt +0 -0
holidays/holiday_base.py CHANGED
@@ -15,19 +15,19 @@ import copy
15
15
  import os
16
16
  import warnings
17
17
  from calendar import isleap
18
- from datetime import date, datetime, timedelta
18
+ from datetime import date, datetime, timedelta, timezone
19
19
  from gettext import NullTranslations, gettext, translation
20
20
  from pathlib import Path
21
- from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple
22
- from typing import Union, cast
21
+ from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Tuple, Union, cast
23
22
 
24
23
  from dateutil.parser import parse
25
24
 
26
- from holidays.constants import HOLIDAY_NAME_DELIMITER, MON, TUE, WED, THU, FRI
27
- from holidays.constants import SAT, SUN
25
+ from holidays.constants import HOLIDAY_NAME_DELIMITER, MON, TUE, WED, THU, FRI, SAT, SUN
26
+ from holidays.helpers import _normalize_tuple
28
27
 
29
28
  DateArg = Union[date, Tuple[int, int]]
30
29
  DateLike = Union[date, datetime, str, float, int]
30
+ SpecialHoliday = Union[Tuple[int, int, str], Tuple[Tuple[int, int, str], ...]]
31
31
 
32
32
  gettext = gettext
33
33
 
@@ -201,7 +201,7 @@ class HolidayBase(Dict[date, str]):
201
201
  """Whether dates when public holiday are observed are included."""
202
202
  subdiv: Optional[str] = None
203
203
  """The subdiv requested."""
204
- special_holidays: Dict[int, Tuple[Tuple[int, int, str], ...]] = {}
204
+ special_holidays: Dict[int, SpecialHoliday] = {}
205
205
  """A list of the country-wide special (as opposite to regular) holidays for
206
206
  a specific year."""
207
207
  _deprecated_subdivisions: Tuple[str, ...] = ()
@@ -209,6 +209,10 @@ class HolidayBase(Dict[date, str]):
209
209
  ones."""
210
210
  weekend: Set[int] = {SAT, SUN}
211
211
  """Country weekend days."""
212
+ default_language: Optional[str] = None
213
+ """The entity language used by default."""
214
+ supported_languages: Tuple[str, ...] = ()
215
+ """All languages supported by this entity."""
212
216
 
213
217
  def __init__(
214
218
  self,
@@ -269,19 +273,11 @@ class HolidayBase(Dict[date, str]):
269
273
  )
270
274
 
271
275
  if not isinstance(self, HolidaySum):
272
- if subdiv and subdiv not in set(
273
- self.subdivisions + self._deprecated_subdivisions
274
- ):
276
+ if subdiv and subdiv not in set(self.subdivisions + self._deprecated_subdivisions):
275
277
  if hasattr(self, "market"):
276
- error = (
277
- f"Market '{self.market}' does not have subdivision "
278
- f"'{subdiv}'"
279
- )
278
+ error = f"Market '{self.market}' does not have subdivision " f"'{subdiv}'"
280
279
  else:
281
- error = (
282
- f"Country '{self.country}' does not have subdivision "
283
- f"'{subdiv}'"
284
- )
280
+ error = f"Country '{self.country}' does not have subdivision " f"'{subdiv}'"
285
281
  raise NotImplementedError(error)
286
282
 
287
283
  if subdiv and subdiv in self._deprecated_subdivisions:
@@ -326,9 +322,7 @@ class HolidayBase(Dict[date, str]):
326
322
  for year in self.years:
327
323
  self._populate(year)
328
324
 
329
- def __add__(
330
- self, other: Union[int, "HolidayBase", "HolidaySum"]
331
- ) -> "HolidayBase":
325
+ def __add__(self, other: Union[int, "HolidayBase", "HolidaySum"]) -> "HolidayBase":
332
326
  """Add another dictionary of public holidays creating a
333
327
  :class:`HolidaySum` object.
334
328
 
@@ -345,9 +339,7 @@ class HolidayBase(Dict[date, str]):
345
339
  return self
346
340
 
347
341
  if not isinstance(other, (HolidayBase, HolidaySum)):
348
- raise TypeError(
349
- "Holiday objects can only be added with other Holiday objects"
350
- )
342
+ raise TypeError("Holiday objects can only be added with other Holiday objects")
351
343
 
352
344
  return HolidaySum(self, other)
353
345
 
@@ -368,18 +360,14 @@ class HolidayBase(Dict[date, str]):
368
360
  if not isinstance(key, (date, datetime, float, int, str)):
369
361
  raise TypeError(f"Cannot convert type '{type(key)}' to date.")
370
362
 
371
- return dict.__contains__(
372
- cast("Mapping[Any, Any]", self), self.__keytransform__(key)
373
- )
363
+ return dict.__contains__(cast("Mapping[Any, Any]", self), self.__keytransform__(key))
374
364
 
375
365
  def __eq__(self, other: object) -> bool:
376
366
  if not isinstance(other, HolidayBase):
377
367
  return False
378
368
 
379
369
  for attribute_name in self.__attribute_names:
380
- if getattr(self, attribute_name, None) != getattr(
381
- other, attribute_name, None
382
- ):
370
+ if getattr(self, attribute_name, None) != getattr(other, attribute_name, None):
383
371
  return False
384
372
 
385
373
  return dict.__eq__(self, other)
@@ -399,9 +387,7 @@ class HolidayBase(Dict[date, str]):
399
387
  elif isinstance(key.step, int):
400
388
  step = key.step
401
389
  else:
402
- raise TypeError(
403
- f"Cannot convert type '{type(key.step)}' to int."
404
- )
390
+ raise TypeError(f"Cannot convert type '{type(key.step)}' to int.")
405
391
 
406
392
  if step == 0:
407
393
  raise ValueError("Step value must not be zero.")
@@ -450,10 +436,8 @@ class HolidayBase(Dict[date, str]):
450
436
  elif isinstance(key, date): # Key type is derived from `date`.
451
437
  dt = key
452
438
 
453
- elif isinstance(
454
- key, (float, int)
455
- ): # Key type is derived from `float` or `int`.
456
- dt = datetime.utcfromtimestamp(key).date()
439
+ elif isinstance(key, (float, int)): # Key type is derived from `float` or `int`.
440
+ dt = datetime.fromtimestamp(key, timezone.utc).date()
457
441
 
458
442
  else: # Key type is not supported.
459
443
  raise TypeError(f"Cannot convert type '{type(key)}' to date.")
@@ -470,9 +454,7 @@ class HolidayBase(Dict[date, str]):
470
454
  return True
471
455
 
472
456
  for attribute_name in self.__attribute_names:
473
- if getattr(self, attribute_name, None) != getattr(
474
- other, attribute_name, None
475
- ):
457
+ if getattr(self, attribute_name, None) != getattr(other, attribute_name, None):
476
458
  return True
477
459
 
478
460
  return dict.__ne__(self, other)
@@ -524,10 +506,7 @@ class HolidayBase(Dict[date, str]):
524
506
 
525
507
  parts = []
526
508
  for attribute_name in self.__attribute_names:
527
- parts.append(
528
- "'%s': %s"
529
- % (attribute_name, getattr(self, attribute_name, None))
530
- )
509
+ parts.append("'%s': %s" % (attribute_name, getattr(self, attribute_name, None)))
531
510
 
532
511
  return f"{{{', '.join(parts)}}}"
533
512
 
@@ -566,10 +545,8 @@ class HolidayBase(Dict[date, str]):
566
545
  def _add_subdiv_holidays(self):
567
546
  """Populate subdivision holidays."""
568
547
  if self.subdiv is not None:
569
- subdiv = self.subdiv.replace("-", "_").lower()
570
- add_subdiv_holidays = getattr(
571
- self, f"_add_subdiv_{subdiv}_holidays", None
572
- )
548
+ subdiv = self.subdiv.replace("-", "_").replace(" ", "_").lower()
549
+ add_subdiv_holidays = getattr(self, f"_add_subdiv_{subdiv}_holidays", None)
573
550
  if add_subdiv_holidays and callable(add_subdiv_holidays):
574
551
  add_subdiv_holidays()
575
552
 
@@ -617,8 +594,7 @@ class HolidayBase(Dict[date, str]):
617
594
  name, dt = args
618
595
  if not isinstance(dt, date):
619
596
  raise TypeError(
620
- "Invalid argument type: expected <class 'date'> "
621
- f"got '{type(dt)}'."
597
+ "Invalid argument type: expected <class 'date'> " f"got '{type(dt)}'."
622
598
  )
623
599
  elif len(args) == 3:
624
600
  name, month, day = args
@@ -649,7 +625,7 @@ class HolidayBase(Dict[date, str]):
649
625
  dates = set()
650
626
 
651
627
  # Populate items from the special holidays list.
652
- for month, day, name in self.special_holidays.get(year, ()):
628
+ for month, day, name in _normalize_tuple(self.special_holidays.get(year, ())):
653
629
  dates.add(self._add_holiday(name, date(year, month, day)))
654
630
 
655
631
  # Populate subdivision holidays.
@@ -657,9 +633,7 @@ class HolidayBase(Dict[date, str]):
657
633
 
658
634
  return dates
659
635
 
660
- def append(
661
- self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]
662
- ) -> None:
636
+ def append(self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]) -> None:
663
637
  """Alias for :meth:`update` to mimic list type."""
664
638
  return self.update(*args)
665
639
 
@@ -710,13 +684,14 @@ class HolidayBase(Dict[date, str]):
710
684
  * or a :class:`float` or :class:`int` representing a POSIX
711
685
  timestamp.
712
686
  """
713
- return [
714
- name
715
- for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER)
716
- if name
717
- ]
687
+ return [name for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER) if name]
718
688
 
719
- def get_named(self, holiday_name: str, lookup="icontains") -> List[date]:
689
+ def get_named(
690
+ self,
691
+ holiday_name: str,
692
+ lookup="icontains",
693
+ split_multiple_names=True,
694
+ ) -> List[date]:
720
695
  """Return a list of all holiday dates matching the provided holiday
721
696
  name. The match will be made case insensitively and partial matches
722
697
  will be included by default.
@@ -731,12 +706,15 @@ class HolidayBase(Dict[date, str]):
731
706
  icontains - case insensitive contains match;
732
707
  iexact - case insensitive exact match;
733
708
  istartswith - case insensitive starts with match;
709
+ :param split_multiple_names:
710
+ Either use the exact name for each date or split it by holiday
711
+ name delimiter.
734
712
 
735
713
  :return:
736
714
  A list of all holiday dates matching the provided holiday name.
737
715
  """
738
716
  holiday_date_names_mapping: Dict[date, List[str]] = {
739
- key: value.split(HOLIDAY_NAME_DELIMITER)
717
+ key: value.split(HOLIDAY_NAME_DELIMITER) if split_multiple_names else [value]
740
718
  for key, value in self.items()
741
719
  }
742
720
 
@@ -763,12 +741,7 @@ class HolidayBase(Dict[date, str]):
763
741
  return [
764
742
  dt
765
743
  for dt, names in holiday_date_names_mapping.items()
766
- if any(
767
- (
768
- holiday_name == name[: len(holiday_name)]
769
- for name in names
770
- )
771
- )
744
+ if any((holiday_name == name[: len(holiday_name)] for name in names))
772
745
  ]
773
746
  elif lookup == "iexact":
774
747
  holiday_name_lower = holiday_name.lower()
@@ -782,12 +755,7 @@ class HolidayBase(Dict[date, str]):
782
755
  return [
783
756
  dt
784
757
  for dt, names in holiday_date_names_mapping.items()
785
- if any(
786
- (
787
- holiday_name_lower == name[: len(holiday_name)].lower()
788
- for name in names
789
- )
790
- )
758
+ if any((holiday_name_lower == name[: len(holiday_name)].lower() for name in names))
791
759
  ]
792
760
 
793
761
  raise AttributeError(f"Unknown lookup type: {lookup}")
@@ -841,14 +809,24 @@ class HolidayBase(Dict[date, str]):
841
809
  :raise:
842
810
  KeyError if date is not a holiday and default is not given.
843
811
  """
844
- dates = self.get_named(name)
845
- if not dates:
812
+ use_exact_name = HOLIDAY_NAME_DELIMITER in name
813
+ dts = self.get_named(name, split_multiple_names=not use_exact_name)
814
+ if len(dts) == 0:
846
815
  raise KeyError(name)
847
816
 
848
- for dt in dates:
817
+ popped = []
818
+ for dt in dts:
819
+ holiday_names = self[dt].split(HOLIDAY_NAME_DELIMITER)
849
820
  self.pop(dt)
821
+ popped.append(dt)
850
822
 
851
- return dates
823
+ # Keep the rest of holidays falling on the same date.
824
+ if not use_exact_name:
825
+ holiday_names.remove(name)
826
+ if len(holiday_names) > 0:
827
+ self[dt] = HOLIDAY_NAME_DELIMITER.join(holiday_names)
828
+
829
+ return popped
852
830
 
853
831
  def update( # type: ignore[override]
854
832
  self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]