holidays 0.26__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 (256) hide show
  1. holidays/__init__.py +1 -1
  2. holidays/calendars/__init__.py +5 -7
  3. holidays/calendars/buddhist.py +1 -3
  4. holidays/calendars/chinese.py +1 -3
  5. holidays/calendars/custom.py +1 -3
  6. holidays/calendars/hindu.py +1 -3
  7. holidays/calendars/islamic.py +1341 -1345
  8. holidays/calendars/thai.py +217 -26
  9. holidays/countries/__init__.py +4 -0
  10. holidays/countries/albania.py +6 -17
  11. holidays/countries/andorra.py +2 -6
  12. holidays/countries/angola.py +53 -39
  13. holidays/countries/argentina.py +13 -24
  14. holidays/countries/aruba.py +109 -48
  15. holidays/countries/australia.py +31 -69
  16. holidays/countries/azerbaijan.py +30 -38
  17. holidays/countries/bahrain.py +5 -5
  18. holidays/countries/bangladesh.py +1 -3
  19. holidays/countries/belarus.py +1 -3
  20. holidays/countries/belize.py +4 -16
  21. holidays/countries/bolivia.py +2 -6
  22. holidays/countries/bosnia_and_herzegovina.py +5 -17
  23. holidays/countries/botswana.py +9 -18
  24. holidays/countries/brazil.py +2 -5
  25. holidays/countries/brunei.py +427 -0
  26. holidays/countries/bulgaria.py +2 -6
  27. holidays/countries/burkina_faso.py +141 -0
  28. holidays/countries/burundi.py +2 -5
  29. holidays/countries/cambodia.py +323 -0
  30. holidays/countries/cameroon.py +71 -77
  31. holidays/countries/canada.py +19 -28
  32. holidays/countries/chad.py +133 -0
  33. holidays/countries/chile.py +4 -11
  34. holidays/countries/china.py +1 -2
  35. holidays/countries/colombia.py +17 -15
  36. holidays/countries/costa_rica.py +2 -6
  37. holidays/countries/curacao.py +100 -46
  38. holidays/countries/cyprus.py +2 -6
  39. holidays/countries/czechia.py +4 -12
  40. holidays/countries/denmark.py +1 -3
  41. holidays/countries/dominican_republic.py +1 -3
  42. holidays/countries/ecuador.py +54 -54
  43. holidays/countries/egypt.py +2 -5
  44. holidays/countries/eswatini.py +34 -44
  45. holidays/countries/ethiopia.py +5 -14
  46. holidays/countries/finland.py +1 -3
  47. holidays/countries/gabon.py +49 -53
  48. holidays/countries/greece.py +1 -2
  49. holidays/countries/honduras.py +16 -13
  50. holidays/countries/hongkong.py +7 -8
  51. holidays/countries/hungary.py +93 -92
  52. holidays/countries/india.py +4 -11
  53. holidays/countries/indonesia.py +120 -114
  54. holidays/countries/ireland.py +5 -15
  55. holidays/countries/isle_of_man.py +9 -4
  56. holidays/countries/israel.py +6 -18
  57. holidays/countries/italy.py +1 -2
  58. holidays/countries/jamaica.py +10 -18
  59. holidays/countries/japan.py +10 -16
  60. holidays/countries/kazakhstan.py +7 -22
  61. holidays/countries/kenya.py +1 -3
  62. holidays/countries/kyrgyzstan.py +2 -5
  63. holidays/countries/latvia.py +2 -6
  64. holidays/countries/lesotho.py +52 -32
  65. holidays/countries/lithuania.py +4 -12
  66. holidays/countries/madagascar.py +3 -9
  67. holidays/countries/malawi.py +34 -26
  68. holidays/countries/malaysia.py +223 -248
  69. holidays/countries/marshall_islands.py +4 -9
  70. holidays/countries/mexico.py +1 -3
  71. holidays/countries/moldova.py +3 -6
  72. holidays/countries/monaco.py +16 -26
  73. holidays/countries/montenegro.py +23 -19
  74. holidays/countries/morocco.py +2 -5
  75. holidays/countries/mozambique.py +35 -31
  76. holidays/countries/namibia.py +54 -35
  77. holidays/countries/new_zealand.py +11 -21
  78. holidays/countries/nicaragua.py +26 -22
  79. holidays/countries/nigeria.py +6 -17
  80. holidays/countries/north_macedonia.py +3 -8
  81. holidays/countries/norway.py +1 -3
  82. holidays/countries/pakistan.py +71 -72
  83. holidays/countries/panama.py +25 -24
  84. holidays/countries/paraguay.py +54 -47
  85. holidays/countries/philippines.py +6 -2
  86. holidays/countries/poland.py +3 -9
  87. holidays/countries/portugal.py +3 -11
  88. holidays/countries/romania.py +3 -5
  89. holidays/countries/saudi_arabia.py +8 -22
  90. holidays/countries/serbia.py +19 -29
  91. holidays/countries/singapore.py +70 -74
  92. holidays/countries/slovakia.py +1 -4
  93. holidays/countries/south_africa.py +60 -62
  94. holidays/countries/south_korea.py +14 -23
  95. holidays/countries/spain.py +2 -5
  96. holidays/countries/sweden.py +1 -3
  97. holidays/countries/taiwan.py +2 -5
  98. holidays/countries/thailand.py +34 -81
  99. holidays/countries/turkey.py +1 -3
  100. holidays/countries/ukraine.py +6 -18
  101. holidays/countries/united_arab_emirates.py +21 -29
  102. holidays/countries/united_kingdom.py +47 -67
  103. holidays/countries/united_states.py +42 -72
  104. holidays/countries/vatican_city.py +1 -3
  105. holidays/countries/venezuela.py +8 -6
  106. holidays/countries/vietnam.py +6 -18
  107. holidays/countries/zambia.py +63 -33
  108. holidays/countries/zimbabwe.py +56 -37
  109. holidays/financial/european_central_bank.py +1 -3
  110. holidays/financial/ny_stock_exchange.py +31 -48
  111. holidays/groups/__init__.py +18 -0
  112. holidays/groups/buddhist.py +71 -0
  113. holidays/groups/chinese.py +235 -0
  114. holidays/groups/christian.py +483 -0
  115. holidays/groups/hindu.py +71 -0
  116. holidays/groups/international.py +157 -0
  117. holidays/groups/islamic.py +288 -0
  118. holidays/groups/thai.py +157 -0
  119. holidays/helpers.py +20 -0
  120. holidays/holiday_base.py +49 -75
  121. holidays/holiday_groups.py +11 -1190
  122. holidays/locale/am/LC_MESSAGES/ET.po +18 -15
  123. holidays/locale/ar/LC_MESSAGES/CA.po +43 -43
  124. holidays/locale/ar/LC_MESSAGES/ET.po +18 -15
  125. holidays/locale/ar/LC_MESSAGES/UA.po +16 -14
  126. holidays/locale/be/LC_MESSAGES/BY.po +9 -8
  127. holidays/locale/bg/LC_MESSAGES/BG.po +14 -12
  128. holidays/locale/da/LC_MESSAGES/DK.po +7 -6
  129. holidays/locale/el/LC_MESSAGES/CY.po +5 -3
  130. holidays/locale/el/LC_MESSAGES/GR.po +13 -13
  131. holidays/locale/en/LC_MESSAGES/CA.po +43 -43
  132. holidays/locale/en_US/LC_MESSAGES/AR.po +26 -25
  133. holidays/locale/en_US/LC_MESSAGES/AW.mo +0 -0
  134. holidays/locale/en_US/LC_MESSAGES/AW.po +87 -0
  135. holidays/locale/en_US/LC_MESSAGES/BG.po +14 -12
  136. holidays/locale/en_US/LC_MESSAGES/BN.mo +0 -0
  137. holidays/locale/en_US/LC_MESSAGES/BN.po +96 -0
  138. holidays/locale/en_US/LC_MESSAGES/BY.po +9 -8
  139. holidays/locale/en_US/LC_MESSAGES/CA.po +43 -43
  140. holidays/locale/en_US/LC_MESSAGES/CL.po +18 -18
  141. holidays/locale/en_US/LC_MESSAGES/CO.po +19 -19
  142. holidays/locale/en_US/LC_MESSAGES/CR.po +6 -5
  143. holidays/locale/en_US/LC_MESSAGES/CW.mo +0 -0
  144. holidays/locale/en_US/LC_MESSAGES/CW.po +82 -0
  145. holidays/locale/en_US/LC_MESSAGES/CY.po +5 -3
  146. holidays/locale/en_US/LC_MESSAGES/DK.po +7 -6
  147. holidays/locale/en_US/LC_MESSAGES/DO.po +12 -12
  148. holidays/locale/en_US/LC_MESSAGES/EC.po +11 -12
  149. holidays/locale/en_US/LC_MESSAGES/ET.po +18 -15
  150. holidays/locale/en_US/LC_MESSAGES/FI.po +13 -13
  151. holidays/locale/en_US/LC_MESSAGES/GR.po +13 -13
  152. holidays/locale/en_US/LC_MESSAGES/HN.mo +0 -0
  153. holidays/locale/en_US/LC_MESSAGES/HN.po +13 -13
  154. holidays/locale/en_US/LC_MESSAGES/HU.mo +0 -0
  155. holidays/locale/en_US/LC_MESSAGES/HU.po +109 -0
  156. holidays/locale/en_US/LC_MESSAGES/JP.po +19 -17
  157. holidays/locale/en_US/LC_MESSAGES/KH.mo +0 -0
  158. holidays/locale/en_US/LC_MESSAGES/KH.po +139 -0
  159. holidays/locale/en_US/LC_MESSAGES/MC.mo +0 -0
  160. holidays/locale/en_US/LC_MESSAGES/MC.po +16 -15
  161. holidays/locale/en_US/LC_MESSAGES/MD.po +5 -5
  162. holidays/locale/en_US/LC_MESSAGES/MX.po +3 -2
  163. holidays/locale/en_US/LC_MESSAGES/NI.mo +0 -0
  164. holidays/locale/en_US/LC_MESSAGES/NI.po +13 -13
  165. holidays/locale/en_US/LC_MESSAGES/NO.po +1 -1
  166. holidays/locale/en_US/LC_MESSAGES/PL.po +23 -21
  167. holidays/locale/en_US/LC_MESSAGES/PT.po +31 -31
  168. holidays/locale/en_US/LC_MESSAGES/PY.po +13 -11
  169. holidays/locale/en_US/LC_MESSAGES/RO.po +4 -3
  170. holidays/locale/en_US/LC_MESSAGES/RS.po +10 -10
  171. holidays/locale/en_US/LC_MESSAGES/SE.po +1 -1
  172. holidays/locale/en_US/LC_MESSAGES/SK.po +14 -14
  173. holidays/locale/en_US/LC_MESSAGES/TH.po +41 -41
  174. holidays/locale/en_US/LC_MESSAGES/UA.po +16 -14
  175. holidays/locale/en_US/LC_MESSAGES/VE.po +6 -6
  176. holidays/locale/es/LC_MESSAGES/AR.po +26 -25
  177. holidays/locale/es/LC_MESSAGES/CL.po +18 -18
  178. holidays/locale/es/LC_MESSAGES/CO.po +19 -19
  179. holidays/locale/es/LC_MESSAGES/CR.po +6 -5
  180. holidays/locale/es/LC_MESSAGES/DO.po +12 -12
  181. holidays/locale/es/LC_MESSAGES/EC.po +11 -12
  182. holidays/locale/es/LC_MESSAGES/HN.po +12 -12
  183. holidays/locale/es/LC_MESSAGES/MX.po +3 -2
  184. holidays/locale/es/LC_MESSAGES/NI.po +10 -10
  185. holidays/locale/es/LC_MESSAGES/PY.po +13 -11
  186. holidays/locale/es/LC_MESSAGES/VE.po +6 -6
  187. holidays/locale/fi/LC_MESSAGES/FI.po +13 -13
  188. holidays/locale/fr/LC_MESSAGES/CA.po +43 -43
  189. holidays/locale/fr/LC_MESSAGES/MC.po +15 -14
  190. holidays/locale/hu/LC_MESSAGES/HU.mo +0 -0
  191. holidays/locale/hu/LC_MESSAGES/HU.po +109 -0
  192. holidays/locale/ja/LC_MESSAGES/JP.po +19 -17
  193. holidays/locale/km/LC_MESSAGES/KH.mo +0 -0
  194. holidays/locale/km/LC_MESSAGES/KH.po +139 -0
  195. holidays/locale/ms/LC_MESSAGES/BN.mo +0 -0
  196. holidays/locale/ms/LC_MESSAGES/BN.po +96 -0
  197. holidays/locale/nl/LC_MESSAGES/AW.mo +0 -0
  198. holidays/locale/nl/LC_MESSAGES/AW.po +87 -0
  199. holidays/locale/nl/LC_MESSAGES/CW.mo +0 -0
  200. holidays/locale/nl/LC_MESSAGES/CW.po +82 -0
  201. holidays/locale/no/LC_MESSAGES/NO.po +1 -1
  202. holidays/locale/pap/LC_MESSAGES/AW.mo +0 -0
  203. holidays/locale/pap/LC_MESSAGES/AW.po +87 -0
  204. holidays/locale/pap/LC_MESSAGES/CW.mo +0 -0
  205. holidays/locale/pap/LC_MESSAGES/CW.po +82 -0
  206. holidays/locale/pl/LC_MESSAGES/PL.po +23 -21
  207. holidays/locale/pt_PT/LC_MESSAGES/PT.po +31 -31
  208. holidays/locale/ro/LC_MESSAGES/MD.po +5 -5
  209. holidays/locale/ro/LC_MESSAGES/RO.po +4 -3
  210. holidays/locale/sk/LC_MESSAGES/SK.po +14 -14
  211. holidays/locale/sr/LC_MESSAGES/RS.po +10 -10
  212. holidays/locale/sv/LC_MESSAGES/FI.po +13 -13
  213. holidays/locale/sv/LC_MESSAGES/SE.po +1 -1
  214. holidays/locale/th/LC_MESSAGES/BN.mo +0 -0
  215. holidays/locale/th/LC_MESSAGES/BN.po +96 -0
  216. holidays/locale/th/LC_MESSAGES/CA.po +43 -43
  217. holidays/locale/th/LC_MESSAGES/KH.mo +0 -0
  218. holidays/locale/th/LC_MESSAGES/KH.po +145 -0
  219. holidays/locale/th/LC_MESSAGES/TH.po +41 -41
  220. holidays/locale/uk/LC_MESSAGES/AR.po +26 -25
  221. holidays/locale/uk/LC_MESSAGES/AW.mo +0 -0
  222. holidays/locale/uk/LC_MESSAGES/AW.po +87 -0
  223. holidays/locale/uk/LC_MESSAGES/CL.po +18 -18
  224. holidays/locale/uk/LC_MESSAGES/CO.po +19 -19
  225. holidays/locale/uk/LC_MESSAGES/CR.po +6 -5
  226. holidays/locale/uk/LC_MESSAGES/CW.mo +0 -0
  227. holidays/locale/uk/LC_MESSAGES/CW.po +82 -0
  228. holidays/locale/uk/LC_MESSAGES/DK.po +7 -6
  229. holidays/locale/uk/LC_MESSAGES/DO.po +12 -12
  230. holidays/locale/uk/LC_MESSAGES/EC.po +11 -12
  231. holidays/locale/uk/LC_MESSAGES/FI.po +13 -13
  232. holidays/locale/uk/LC_MESSAGES/HN.mo +0 -0
  233. holidays/locale/uk/LC_MESSAGES/HN.po +13 -13
  234. holidays/locale/uk/LC_MESSAGES/HU.mo +0 -0
  235. holidays/locale/uk/LC_MESSAGES/HU.po +109 -0
  236. holidays/locale/uk/LC_MESSAGES/MC.po +15 -14
  237. holidays/locale/uk/LC_MESSAGES/MD.po +5 -5
  238. holidays/locale/uk/LC_MESSAGES/MX.po +3 -2
  239. holidays/locale/uk/LC_MESSAGES/NI.mo +0 -0
  240. holidays/locale/uk/LC_MESSAGES/NI.po +13 -13
  241. holidays/locale/uk/LC_MESSAGES/NO.po +1 -1
  242. holidays/locale/uk/LC_MESSAGES/PL.po +23 -21
  243. holidays/locale/uk/LC_MESSAGES/PY.po +13 -11
  244. holidays/locale/uk/LC_MESSAGES/RO.po +4 -3
  245. holidays/locale/uk/LC_MESSAGES/SE.po +1 -1
  246. holidays/locale/uk/LC_MESSAGES/SK.po +14 -14
  247. holidays/locale/uk/LC_MESSAGES/UA.po +16 -14
  248. holidays/locale/uk/LC_MESSAGES/VE.po +6 -6
  249. holidays/registry.py +7 -11
  250. holidays/utils.py +5 -15
  251. {holidays-0.26.dist-info → holidays-0.27.dist-info}/METADATA +25 -7
  252. holidays-0.27.dist-info/RECORD +449 -0
  253. holidays-0.26.dist-info/RECORD +0 -402
  254. {holidays-0.26.dist-info → holidays-0.27.dist-info}/LICENSE +0 -0
  255. {holidays-0.26.dist-info → holidays-0.27.dist-info}/WHEEL +0 -0
  256. {holidays-0.26.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, ...] = ()
@@ -273,19 +273,11 @@ class HolidayBase(Dict[date, str]):
273
273
  )
274
274
 
275
275
  if not isinstance(self, HolidaySum):
276
- if subdiv and subdiv not in set(
277
- self.subdivisions + self._deprecated_subdivisions
278
- ):
276
+ if subdiv and subdiv not in set(self.subdivisions + self._deprecated_subdivisions):
279
277
  if hasattr(self, "market"):
280
- error = (
281
- f"Market '{self.market}' does not have subdivision "
282
- f"'{subdiv}'"
283
- )
278
+ error = f"Market '{self.market}' does not have subdivision " f"'{subdiv}'"
284
279
  else:
285
- error = (
286
- f"Country '{self.country}' does not have subdivision "
287
- f"'{subdiv}'"
288
- )
280
+ error = f"Country '{self.country}' does not have subdivision " f"'{subdiv}'"
289
281
  raise NotImplementedError(error)
290
282
 
291
283
  if subdiv and subdiv in self._deprecated_subdivisions:
@@ -330,9 +322,7 @@ class HolidayBase(Dict[date, str]):
330
322
  for year in self.years:
331
323
  self._populate(year)
332
324
 
333
- def __add__(
334
- self, other: Union[int, "HolidayBase", "HolidaySum"]
335
- ) -> "HolidayBase":
325
+ def __add__(self, other: Union[int, "HolidayBase", "HolidaySum"]) -> "HolidayBase":
336
326
  """Add another dictionary of public holidays creating a
337
327
  :class:`HolidaySum` object.
338
328
 
@@ -349,9 +339,7 @@ class HolidayBase(Dict[date, str]):
349
339
  return self
350
340
 
351
341
  if not isinstance(other, (HolidayBase, HolidaySum)):
352
- raise TypeError(
353
- "Holiday objects can only be added with other Holiday objects"
354
- )
342
+ raise TypeError("Holiday objects can only be added with other Holiday objects")
355
343
 
356
344
  return HolidaySum(self, other)
357
345
 
@@ -372,18 +360,14 @@ class HolidayBase(Dict[date, str]):
372
360
  if not isinstance(key, (date, datetime, float, int, str)):
373
361
  raise TypeError(f"Cannot convert type '{type(key)}' to date.")
374
362
 
375
- return dict.__contains__(
376
- cast("Mapping[Any, Any]", self), self.__keytransform__(key)
377
- )
363
+ return dict.__contains__(cast("Mapping[Any, Any]", self), self.__keytransform__(key))
378
364
 
379
365
  def __eq__(self, other: object) -> bool:
380
366
  if not isinstance(other, HolidayBase):
381
367
  return False
382
368
 
383
369
  for attribute_name in self.__attribute_names:
384
- if getattr(self, attribute_name, None) != getattr(
385
- other, attribute_name, None
386
- ):
370
+ if getattr(self, attribute_name, None) != getattr(other, attribute_name, None):
387
371
  return False
388
372
 
389
373
  return dict.__eq__(self, other)
@@ -403,9 +387,7 @@ class HolidayBase(Dict[date, str]):
403
387
  elif isinstance(key.step, int):
404
388
  step = key.step
405
389
  else:
406
- raise TypeError(
407
- f"Cannot convert type '{type(key.step)}' to int."
408
- )
390
+ raise TypeError(f"Cannot convert type '{type(key.step)}' to int.")
409
391
 
410
392
  if step == 0:
411
393
  raise ValueError("Step value must not be zero.")
@@ -454,10 +436,8 @@ class HolidayBase(Dict[date, str]):
454
436
  elif isinstance(key, date): # Key type is derived from `date`.
455
437
  dt = key
456
438
 
457
- elif isinstance(
458
- key, (float, int)
459
- ): # Key type is derived from `float` or `int`.
460
- 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()
461
441
 
462
442
  else: # Key type is not supported.
463
443
  raise TypeError(f"Cannot convert type '{type(key)}' to date.")
@@ -474,9 +454,7 @@ class HolidayBase(Dict[date, str]):
474
454
  return True
475
455
 
476
456
  for attribute_name in self.__attribute_names:
477
- if getattr(self, attribute_name, None) != getattr(
478
- other, attribute_name, None
479
- ):
457
+ if getattr(self, attribute_name, None) != getattr(other, attribute_name, None):
480
458
  return True
481
459
 
482
460
  return dict.__ne__(self, other)
@@ -528,10 +506,7 @@ class HolidayBase(Dict[date, str]):
528
506
 
529
507
  parts = []
530
508
  for attribute_name in self.__attribute_names:
531
- parts.append(
532
- "'%s': %s"
533
- % (attribute_name, getattr(self, attribute_name, None))
534
- )
509
+ parts.append("'%s': %s" % (attribute_name, getattr(self, attribute_name, None)))
535
510
 
536
511
  return f"{{{', '.join(parts)}}}"
537
512
 
@@ -571,9 +546,7 @@ class HolidayBase(Dict[date, str]):
571
546
  """Populate subdivision holidays."""
572
547
  if self.subdiv is not None:
573
548
  subdiv = self.subdiv.replace("-", "_").replace(" ", "_").lower()
574
- add_subdiv_holidays = getattr(
575
- self, f"_add_subdiv_{subdiv}_holidays", None
576
- )
549
+ add_subdiv_holidays = getattr(self, f"_add_subdiv_{subdiv}_holidays", None)
577
550
  if add_subdiv_holidays and callable(add_subdiv_holidays):
578
551
  add_subdiv_holidays()
579
552
 
@@ -621,8 +594,7 @@ class HolidayBase(Dict[date, str]):
621
594
  name, dt = args
622
595
  if not isinstance(dt, date):
623
596
  raise TypeError(
624
- "Invalid argument type: expected <class 'date'> "
625
- f"got '{type(dt)}'."
597
+ "Invalid argument type: expected <class 'date'> " f"got '{type(dt)}'."
626
598
  )
627
599
  elif len(args) == 3:
628
600
  name, month, day = args
@@ -653,7 +625,7 @@ class HolidayBase(Dict[date, str]):
653
625
  dates = set()
654
626
 
655
627
  # Populate items from the special holidays list.
656
- for month, day, name in self.special_holidays.get(year, ()):
628
+ for month, day, name in _normalize_tuple(self.special_holidays.get(year, ())):
657
629
  dates.add(self._add_holiday(name, date(year, month, day)))
658
630
 
659
631
  # Populate subdivision holidays.
@@ -661,9 +633,7 @@ class HolidayBase(Dict[date, str]):
661
633
 
662
634
  return dates
663
635
 
664
- def append(
665
- self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]
666
- ) -> None:
636
+ def append(self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]) -> None:
667
637
  """Alias for :meth:`update` to mimic list type."""
668
638
  return self.update(*args)
669
639
 
@@ -714,13 +684,14 @@ class HolidayBase(Dict[date, str]):
714
684
  * or a :class:`float` or :class:`int` representing a POSIX
715
685
  timestamp.
716
686
  """
717
- return [
718
- name
719
- for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER)
720
- if name
721
- ]
687
+ return [name for name in self.get(key, "").split(HOLIDAY_NAME_DELIMITER) if name]
722
688
 
723
- 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]:
724
695
  """Return a list of all holiday dates matching the provided holiday
725
696
  name. The match will be made case insensitively and partial matches
726
697
  will be included by default.
@@ -735,12 +706,15 @@ class HolidayBase(Dict[date, str]):
735
706
  icontains - case insensitive contains match;
736
707
  iexact - case insensitive exact match;
737
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.
738
712
 
739
713
  :return:
740
714
  A list of all holiday dates matching the provided holiday name.
741
715
  """
742
716
  holiday_date_names_mapping: Dict[date, List[str]] = {
743
- key: value.split(HOLIDAY_NAME_DELIMITER)
717
+ key: value.split(HOLIDAY_NAME_DELIMITER) if split_multiple_names else [value]
744
718
  for key, value in self.items()
745
719
  }
746
720
 
@@ -767,12 +741,7 @@ class HolidayBase(Dict[date, str]):
767
741
  return [
768
742
  dt
769
743
  for dt, names in holiday_date_names_mapping.items()
770
- if any(
771
- (
772
- holiday_name == name[: len(holiday_name)]
773
- for name in names
774
- )
775
- )
744
+ if any((holiday_name == name[: len(holiday_name)] for name in names))
776
745
  ]
777
746
  elif lookup == "iexact":
778
747
  holiday_name_lower = holiday_name.lower()
@@ -786,12 +755,7 @@ class HolidayBase(Dict[date, str]):
786
755
  return [
787
756
  dt
788
757
  for dt, names in holiday_date_names_mapping.items()
789
- if any(
790
- (
791
- holiday_name_lower == name[: len(holiday_name)].lower()
792
- for name in names
793
- )
794
- )
758
+ if any((holiday_name_lower == name[: len(holiday_name)].lower() for name in names))
795
759
  ]
796
760
 
797
761
  raise AttributeError(f"Unknown lookup type: {lookup}")
@@ -845,14 +809,24 @@ class HolidayBase(Dict[date, str]):
845
809
  :raise:
846
810
  KeyError if date is not a holiday and default is not given.
847
811
  """
848
- dates = self.get_named(name)
849
- 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:
850
815
  raise KeyError(name)
851
816
 
852
- for dt in dates:
817
+ popped = []
818
+ for dt in dts:
819
+ holiday_names = self[dt].split(HOLIDAY_NAME_DELIMITER)
853
820
  self.pop(dt)
821
+ popped.append(dt)
854
822
 
855
- 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
856
830
 
857
831
  def update( # type: ignore[override]
858
832
  self, *args: Union[Dict[DateLike, str], List[DateLike], DateLike]