holidays 0.77__py3-none-any.whl → 0.79__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 (121) hide show
  1. holidays/calendars/__init__.py +1 -0
  2. holidays/calendars/chinese.py +14 -4
  3. holidays/calendars/ethiopian.py +31 -0
  4. holidays/calendars/islamic.py +48 -5
  5. holidays/calendars/julian.py +14 -0
  6. holidays/calendars/mandaean.py +59 -0
  7. holidays/calendars/tibetan.py +1466 -0
  8. holidays/constants.py +2 -0
  9. holidays/countries/__init__.py +14 -0
  10. holidays/countries/afghanistan.py +6 -39
  11. holidays/countries/albania.py +3 -22
  12. holidays/countries/argentina.py +3 -18
  13. holidays/countries/azerbaijan.py +6 -39
  14. holidays/countries/bahrain.py +29 -38
  15. holidays/countries/bhutan.py +194 -0
  16. holidays/countries/bosnia_and_herzegovina.py +2 -27
  17. holidays/countries/brunei.py +7 -117
  18. holidays/countries/burkina_faso.py +4 -15
  19. holidays/countries/cameroon.py +3 -34
  20. holidays/countries/canada.py +2 -1
  21. holidays/countries/central_african_republic.py +3 -16
  22. holidays/countries/chad.py +4 -17
  23. holidays/countries/chile.py +20 -4
  24. holidays/countries/christmas_island.py +4 -15
  25. holidays/countries/cocos_islands.py +5 -24
  26. holidays/countries/egypt.py +175 -51
  27. holidays/countries/ethiopia.py +18 -47
  28. holidays/countries/fiji.py +1 -2
  29. holidays/countries/gabon.py +3 -23
  30. holidays/countries/gambia.py +168 -0
  31. holidays/countries/germany.py +41 -0
  32. holidays/countries/guinea.py +5 -27
  33. holidays/countries/guinea_bissau.py +100 -0
  34. holidays/countries/guyana.py +2 -17
  35. holidays/countries/india.py +12 -25
  36. holidays/countries/indonesia.py +11 -160
  37. holidays/countries/iran.py +16 -126
  38. holidays/countries/iraq.py +276 -0
  39. holidays/countries/kazakhstan.py +2 -18
  40. holidays/countries/kenya.py +2 -8
  41. holidays/countries/kiribati.py +124 -0
  42. holidays/countries/lebanon.py +5 -87
  43. holidays/countries/liberia.py +80 -0
  44. holidays/countries/libya.py +5 -37
  45. holidays/countries/luxembourg.py +13 -0
  46. holidays/countries/malaysia.py +9 -130
  47. holidays/countries/mali.py +4 -9
  48. holidays/countries/mauritius.py +1 -2
  49. holidays/countries/montenegro.py +3 -18
  50. holidays/countries/nepal.py +42 -44
  51. holidays/countries/niger.py +14 -74
  52. holidays/countries/north_macedonia.py +3 -39
  53. holidays/countries/oman.py +6 -28
  54. holidays/countries/pakistan.py +12 -35
  55. holidays/countries/palestine.py +2 -5
  56. holidays/countries/philippines.py +3 -33
  57. holidays/countries/pitcairn_islands.py +85 -0
  58. holidays/countries/qatar.py +3 -45
  59. holidays/countries/saudi_arabia.py +46 -35
  60. holidays/countries/senegal.py +6 -16
  61. holidays/countries/sierra_leone.py +4 -20
  62. holidays/countries/singapore.py +3 -59
  63. holidays/countries/south_georgia_and_the_south_sandwich_islands.py +160 -0
  64. holidays/countries/spain.py +3 -10
  65. holidays/countries/sri_lanka.py +3 -14
  66. holidays/countries/suriname.py +11 -19
  67. holidays/countries/syrian_arab_republic.py +134 -0
  68. holidays/countries/tanzania.py +3 -9
  69. holidays/countries/timor_leste.py +2 -17
  70. holidays/countries/togo.py +4 -29
  71. holidays/countries/trinidad_and_tobago.py +2 -9
  72. holidays/countries/turkey.py +2 -116
  73. holidays/countries/turkmenistan.py +158 -0
  74. holidays/countries/united_arab_emirates.py +5 -29
  75. holidays/countries/uzbekistan.py +3 -31
  76. holidays/countries/yemen.py +8 -52
  77. holidays/groups/__init__.py +2 -0
  78. holidays/groups/christian.py +48 -12
  79. holidays/groups/international.py +17 -1
  80. holidays/groups/islamic.py +1 -11
  81. holidays/groups/mandaean.py +107 -0
  82. holidays/groups/tibetan.py +153 -0
  83. holidays/holiday_base.py +86 -91
  84. holidays/locale/ar/LC_MESSAGES/BH.mo +0 -0
  85. holidays/locale/ar/LC_MESSAGES/IQ.mo +0 -0
  86. holidays/locale/ar/LC_MESSAGES/SY.mo +0 -0
  87. holidays/locale/{ar → ar_EG}/LC_MESSAGES/EG.mo +0 -0
  88. holidays/locale/de/LC_MESSAGES/DE.mo +0 -0
  89. holidays/locale/de/LC_MESSAGES/LU.mo +0 -0
  90. holidays/locale/en_GM/LC_MESSAGES/GM.mo +0 -0
  91. holidays/locale/en_GS/LC_MESSAGES/GS.mo +0 -0
  92. holidays/locale/en_US/LC_MESSAGES/BH.mo +0 -0
  93. holidays/locale/en_US/LC_MESSAGES/CL.mo +0 -0
  94. holidays/locale/en_US/LC_MESSAGES/DE.mo +0 -0
  95. holidays/locale/en_US/LC_MESSAGES/EG.mo +0 -0
  96. holidays/locale/en_US/LC_MESSAGES/GM.mo +0 -0
  97. holidays/locale/en_US/LC_MESSAGES/GS.mo +0 -0
  98. holidays/locale/en_US/LC_MESSAGES/GW.mo +0 -0
  99. holidays/locale/en_US/LC_MESSAGES/IQ.mo +0 -0
  100. holidays/locale/en_US/LC_MESSAGES/LU.mo +0 -0
  101. holidays/locale/en_US/LC_MESSAGES/SY.mo +0 -0
  102. holidays/locale/en_US/LC_MESSAGES/TM.mo +0 -0
  103. holidays/locale/fr/LC_MESSAGES/EG.mo +0 -0
  104. holidays/locale/fr/LC_MESSAGES/LU.mo +0 -0
  105. holidays/locale/lb/LC_MESSAGES/LU.mo +0 -0
  106. holidays/locale/pt_GW/LC_MESSAGES/GW.mo +0 -0
  107. holidays/locale/ru/LC_MESSAGES/TM.mo +0 -0
  108. holidays/locale/th/LC_MESSAGES/DE.mo +0 -0
  109. holidays/locale/tk/LC_MESSAGES/TM.mo +0 -0
  110. holidays/locale/uk/LC_MESSAGES/CL.mo +0 -0
  111. holidays/locale/uk/LC_MESSAGES/DE.mo +0 -0
  112. holidays/locale/uk/LC_MESSAGES/LU.mo +0 -0
  113. holidays/registry.py +14 -0
  114. holidays/utils.py +18 -18
  115. holidays/version.py +1 -1
  116. {holidays-0.77.dist-info → holidays-0.79.dist-info}/METADATA +79 -9
  117. {holidays-0.77.dist-info → holidays-0.79.dist-info}/RECORD +121 -92
  118. {holidays-0.77.dist-info → holidays-0.79.dist-info}/licenses/CONTRIBUTORS +3 -0
  119. {holidays-0.77.dist-info → holidays-0.79.dist-info}/WHEEL +0 -0
  120. {holidays-0.77.dist-info → holidays-0.79.dist-info}/licenses/LICENSE +0 -0
  121. {holidays-0.77.dist-info → holidays-0.79.dist-info}/top_level.txt +0 -0
@@ -26,3 +26,4 @@ from holidays.calendars.mongolian import _CustomMongolianHolidays, _MongolianLun
26
26
  from holidays.calendars.persian import _Persian
27
27
  from holidays.calendars.sinhala import _SinhalaLunar, _CustomSinhalaHolidays
28
28
  from holidays.calendars.thai import _ThaiLunisolar, KHMER_CALENDAR, THAI_CALENDAR
29
+ from holidays.calendars.tibetan import _TibetanLunisolar, _CustomTibetanHolidays
@@ -1325,11 +1325,21 @@ class _ChineseLunisolar:
1325
1325
  def _get_holiday(self, holiday: str, year: int, calendar=None) -> tuple[Optional[date], bool]:
1326
1326
  calendar = calendar or self.__calendar
1327
1327
  self.__verify_calendar(calendar)
1328
- custom_calendar_dates = getattr(self, f"{calendar}_{holiday}_DATES", {})
1328
+ confirmed_dates = getattr(
1329
+ self, f"{holiday}_DATES_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", {}
1330
+ )
1331
+ confirmed_years = getattr(
1332
+ self, f"{holiday}_DATES_CONFIRMED_YEARS_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", (0, 0)
1333
+ )
1329
1334
  estimated_dates = getattr(self, f"{holiday}_DATES", {})
1330
- exact_dates = getattr(self, f"{holiday}_DATES_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", {})
1331
- dt = exact_dates.get(year, custom_calendar_dates.get(year, estimated_dates.get(year, ())))
1332
- return date(year, *dt) if dt else None, year not in exact_dates
1335
+ custom_calendar_dates = getattr(self, f"{calendar}_{holiday}_DATES", {})
1336
+ dt = confirmed_dates.get(
1337
+ year, custom_calendar_dates.get(year, estimated_dates.get(year, ()))
1338
+ )
1339
+ is_confirmed = year in confirmed_dates or (
1340
+ confirmed_years[0] <= year <= confirmed_years[1]
1341
+ )
1342
+ return date(year, *dt) if dt else None, not is_confirmed
1333
1343
 
1334
1344
  def buddha_birthday_date(self, year: int, calendar=None) -> tuple[Optional[date], bool]:
1335
1345
  return self._get_holiday(BUDDHA_BIRTHDAY, year, calendar)
@@ -0,0 +1,31 @@
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
+ ETHIOPIAN_CALENDAR = "ETHIOPIAN_CALENDAR"
14
+
15
+
16
+ def is_ethiopian_leap_year(year: int) -> bool:
17
+ """Determine if the Ethiopian year that starts in the given Gregorian year is a leap year.
18
+
19
+ Ethiopian leap years follow the Coptic/Julian rule:
20
+ * Every 4 years without exception (no century rule).
21
+ * The Ethiopian year starts on September 11 (or 12 in an Ethiopian leap year).
22
+
23
+ Args:
24
+ year:
25
+ Gregorian year to evaluate.
26
+
27
+ Returns:
28
+ `True` if an Ethiopian leap year starts in the given Gregorian year, `False` otherwise.
29
+ """
30
+
31
+ return (year + 1) % 4 == 0
@@ -14,7 +14,21 @@ from collections.abc import Iterable
14
14
  from datetime import date
15
15
 
16
16
  from holidays.calendars.custom import _CustomCalendar
17
- from holidays.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
17
+ from holidays.calendars.gregorian import (
18
+ JAN,
19
+ FEB,
20
+ MAR,
21
+ APR,
22
+ MAY,
23
+ JUN,
24
+ JUL,
25
+ AUG,
26
+ SEP,
27
+ OCT,
28
+ NOV,
29
+ DEC,
30
+ _timedelta,
31
+ )
18
32
  from holidays.helpers import _normalize_tuple
19
33
 
20
34
  ALI_AL_RIDA_DEATH = "ALI_AL_RIDA_DEATH"
@@ -3957,11 +3971,40 @@ class _IslamicLunar:
3957
3971
  }
3958
3972
 
3959
3973
  def _get_holiday(self, holiday: str, year: int) -> Iterable[tuple[date, bool]]:
3974
+ confirmed_dates = getattr(
3975
+ self, f"{holiday}_DATES_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", {}
3976
+ )
3977
+ confirmed_years = getattr(
3978
+ self, f"{holiday}_DATES_CONFIRMED_YEARS_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", ()
3979
+ )
3960
3980
  estimated_dates = getattr(self, f"{holiday}_DATES", {})
3961
- exact_dates = getattr(self, f"{holiday}_DATES_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", {})
3962
- for year in (year - 1, year):
3963
- for dt in _normalize_tuple(exact_dates.get(year, estimated_dates.get(year, ()))):
3964
- yield date(year, *dt), year not in exact_dates
3981
+
3982
+ for check_year in (year - 1, year):
3983
+ for dt in _normalize_tuple(
3984
+ confirmed_dates.get(check_year, estimated_dates.get(check_year, ()))
3985
+ ):
3986
+ is_confirmed = check_year in confirmed_dates or any(
3987
+ year_from <= check_year <= year_to
3988
+ for year_from, year_to in _normalize_tuple(confirmed_years)
3989
+ )
3990
+ yield date(check_year, *dt), not is_confirmed
3991
+
3992
+ def _is_long_ramadan(self, eid_al_fitr: date) -> bool:
3993
+ """Check whether the Ramadan preceding the given Eid al-Fitr date lasted 30 days.
3994
+
3995
+ Args:
3996
+ eid_al_fitr:
3997
+ The date of Eid al-Fitr.
3998
+
3999
+ Returns:
4000
+ True if Ramadan lasted 30 days, False otherwise.
4001
+ """
4002
+ eid_al_fitr_year = eid_al_fitr.year
4003
+ return _timedelta(eid_al_fitr, -30) in {
4004
+ dt
4005
+ for year in (eid_al_fitr_year - 1, eid_al_fitr_year)
4006
+ for (dt, _) in self.ramadan_beginning_dates(year)
4007
+ }
3965
4008
 
3966
4009
  def ali_al_rida_death_dates(self, year: int) -> Iterable[tuple[date, bool]]:
3967
4010
  return self._get_holiday(ALI_AL_RIDA_DEATH, year)
@@ -11,3 +11,17 @@
11
11
  # License: MIT (see LICENSE file)
12
12
 
13
13
  JULIAN_CALENDAR = "JULIAN_CALENDAR"
14
+
15
+
16
+ def julian_calendar_drift(year: int) -> int:
17
+ """Return the Julian–Gregorian date drift relative to the 1899–2099 baseline.
18
+
19
+ Args:
20
+ year:
21
+ Gregorian year to check.
22
+
23
+ Returns:
24
+ Number of days to add/subtract relative to the 1899–2099 baseline.
25
+ """
26
+
27
+ return -13 if year <= 1582 else (year // 100) - (year // 400) - 15
@@ -0,0 +1,59 @@
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 typing import Optional
15
+
16
+ from holidays.calendars.gregorian import _timedelta
17
+
18
+
19
+ class _Mandaean:
20
+ """
21
+ Mandaean calendar for 1901-2100 years.
22
+ https://en.wikipedia.org/wiki/Mandaean_calendar
23
+ """
24
+
25
+ # Begin of 445271 Mandaean year.
26
+ START_DATE = date(1901, 8, 16)
27
+ START_YEAR = 1901
28
+ END_YEAR = 2100
29
+
30
+ def new_year_date(self, year: int) -> Optional[date]:
31
+ """
32
+ Return Gregorian date of Mandaean new year (1 Dowla) in a given Gregorian year.
33
+ """
34
+ if year < _Mandaean.START_YEAR or year > _Mandaean.END_YEAR:
35
+ return None
36
+
37
+ return _timedelta(_Mandaean.START_DATE, 365 * (year - _Mandaean.START_YEAR))
38
+
39
+ def mandaean_to_gregorian(self, year: int, month: int, day: int) -> Optional[date]:
40
+ """
41
+ Return Gregorian date of Mandaean day and month of the year that begins in a given
42
+ Gregorian year.
43
+ Extra 5 days inserted after 8th month are considered as 13th month.
44
+ """
45
+ start_date = self.new_year_date(year)
46
+ if not start_date:
47
+ return None
48
+
49
+ if not (1 <= month <= 13) or not (1 <= day <= 30) or (month == 13 and not (1 <= day <= 5)):
50
+ return None
51
+
52
+ if month < 9:
53
+ delta = 30 * (month - 1)
54
+ elif month == 13:
55
+ delta = 30 * 8
56
+ else:
57
+ delta = 30 * (month - 1) + 5
58
+
59
+ return _timedelta(start_date, delta + day - 1)