Repository: vacanza/python-holidays

Issue:
Add Bahrain holidays
To track BH holidays adding process (requested by @taljishi in #813).

Some sources:
  * https://www.cbb.gov.bh/official-bank-holidays/
  * https://www.officeholidays.com/countries/bahrain/2022
  * https://en.wikipedia.org/wiki/Public_holidays_in_Bahrain




Discussion:

Resolving patch:
diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py
--- a/holidays/countries/__init__.py
+++ b/holidays/countries/__init__.py
@@ -16,6 +16,7 @@
 from .australia import AU, AUS, Australia
 from .austria import AT, AUT, Austria
 from .azerbaijan import AZ, AZE, Azerbaijan
+from .bahrain import BH, BAH, Bahrain
 from .bangladesh import BD, BGD, Bangladesh
 from .belarus import BY, BLR, Belarus
 from .belgium import BE, BEL, Belgium
diff --git a/holidays/countries/bahrain.py b/holidays/countries/bahrain.py
new file mode 100644
--- /dev/null
+++ b/holidays/countries/bahrain.py
@@ -0,0 +1,136 @@
+#  python-holidays
+#  ---------------
+#  A fast, efficient Python library for generating country, province and state
+#  specific sets of holidays on the fly. It aims to make determining whether a
+#  specific date is a holiday as fast and flexible as possible.
+#
+#  Authors: dr-prodigy <maurizio.montel@gmail.com> (c) 2017-2022
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/dr-prodigy/python-holidays
+#  License: MIT (see LICENSE file)
+
+from datetime import date
+
+from dateutil.relativedelta import relativedelta as rd
+
+from holidays.constants import FRI, SAT, JAN, MAY, JUL, AUG, OCT, DEC
+from holidays.holiday_base import HolidayBase
+from holidays.utils import _islamic_to_gre
+
+
+class Bahrain(HolidayBase):
+    """
+    Bahrain holidays.
+
+    References:
+      - https://www.cbb.gov.bh/official-bank-holidays/
+      - https://www.officeholidays.com/countries/bahrain/
+    """
+
+    country = "BH"
+    weekend = {FRI, SAT}
+
+    def _populate(self, year):
+        super()._populate(year)
+
+        # New Year's Day.
+        self[date(year, JAN, 1)] = "New Year's Day"
+
+        # Labour day.
+        self[date(year, MAY, 1)] = "Labour Day"
+
+        # Eid Al Fitr.
+        eid_al_fitr = "Eid Al Fitr"
+        eid_al_fitr_mapping = {
+            2022: ((MAY, 2),),
+        }
+        if year in eid_al_fitr_mapping:
+            for dt in eid_al_fitr_mapping[year]:
+                eid_al_fitr_day = date(year, *dt)
+                self[eid_al_fitr_day] = eid_al_fitr
+                self[eid_al_fitr_day + rd(days=+1)] = f"{eid_al_fitr} Holiday"
+                self[eid_al_fitr_day + rd(days=+2)] = f"{eid_al_fitr} Holiday"
+        else:
+            for eid_al_fitr_day in _islamic_to_gre(year, 10, 1):
+                self[eid_al_fitr_day] = f"{eid_al_fitr}* (*estimated)"
+                self[
+                    eid_al_fitr_day + rd(days=+1)
+                ] = f"{eid_al_fitr} Holiday* (*estimated)"
+                self[
+                    eid_al_fitr_day + rd(days=+2)
+                ] = f"{eid_al_fitr} Holiday* (*estimated)"
+
+        # Eid Al Adha.
+        eid_al_adha = "Eid Al Adha"
+        eid_al_adha_mapping = {
+            2022: ((JUL, 9),),
+        }
+        if year in eid_al_adha_mapping:
+            for dt in eid_al_adha_mapping[year]:
+                eid_al_adha_day = date(year, *dt)
+                self[eid_al_adha_day] = eid_al_adha
+                self[eid_al_adha_day + rd(days=+1)] = f"{eid_al_adha} Holiday"
+                self[eid_al_adha_day + rd(days=+2)] = f"{eid_al_adha} Holiday"
+        else:
+            for eid_al_adha_day in _islamic_to_gre(year, 12, 9):
+                self[
+                    eid_al_adha_day + rd(days=+1)
+                ] = f"{eid_al_adha}* (*estimated)"
+                self[
+                    eid_al_adha_day + rd(days=+2)
+                ] = f"{eid_al_adha}* (*estimated)"
+                self[
+                    eid_al_adha_day + rd(days=+3)
+                ] = f"{eid_al_adha}* (*estimated)"
+
+        # Al Hijra New Year.
+        hijri_new_year = "Al Hijra New Year"
+        hijri_new_year_mapping = {
+            2022: ((JUL, 30),),
+        }
+        if year in hijri_new_year_mapping:
+            for dt in hijri_new_year_mapping[year]:
+                self[date(year, *dt)] = hijri_new_year
+        else:
+            for dt in _islamic_to_gre(year, 1, 1):
+                self[dt] = f"{hijri_new_year}* (*estimated)"
+
+        # Ashura.
+        ashura = "Ashura"
+        ashura_mapping = {
+            2022: ((AUG, 7),),
+        }
+        if year in ashura_mapping:
+            for dt in ashura_mapping[year]:
+                ashura_day = date(year, *dt)
+                self[ashura_day] = ashura
+                self[ashura_day + rd(days=+1)] = f"{ashura} Holiday"
+        else:
+            for ashura_day in _islamic_to_gre(year, 1, 9):
+                self[ashura_day] = f"{ashura}* (*estimated)"
+                self[
+                    ashura_day + rd(days=+1)
+                ] = f"{ashura}* Holiday* (*estimated)"
+
+        # Prophets Birthday.
+        mawlud = "Prophets Birthday"
+        mawlud_mapping = {2022: ((OCT, 8),)}
+        if year in mawlud_mapping:
+            for dt in mawlud_mapping[year]:
+                self[date(year, *dt)] = mawlud
+        else:
+            for dt in _islamic_to_gre(year, 3, 12):
+                self[dt] = f"{mawlud}* (*estimated)"
+
+        # National Day.
+        national_day = "National Day"
+        self[date(year, DEC, 16)] = national_day
+        self[date(year, DEC, 17)] = national_day
+
+
+class BH(Bahrain):
+    pass
+
+
+class BAH(Bahrain):
+    pass


Test patch:
diff --git a/test/countries/test_bahrain.py b/test/countries/test_bahrain.py
new file mode 100644
--- /dev/null
+++ b/test/countries/test_bahrain.py
@@ -0,0 +1,82 @@
+#  python-holidays
+#  ---------------
+#  A fast, efficient Python library for generating country, province and state
+#  specific sets of holidays on the fly. It aims to make determining whether a
+#  specific date is a holiday as fast and flexible as possible.
+#
+#  Authors: dr-prodigy <maurizio.montel@gmail.com> (c) 2017-2022
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/dr-prodigy/python-holidays
+#  License: MIT (see LICENSE file)
+
+import importlib.util
+
+from holidays.countries.bahrain import BH, BAH, Bahrain
+from test.common import TestCase
+
+
+class TestBahrain(TestCase):
+    def setUp(self):
+        self.holidays = Bahrain()
+
+    def test_country_aliases(self):
+        self.assertCountryAliases(Bahrain, BH, BAH)
+
+    def test_2022(self):
+        self.assertHoliday(
+            "2022-01-01",
+            "2022-05-01",
+            "2022-05-02",
+            "2022-05-03",
+            "2022-05-04",
+            "2022-07-09",
+            "2022-07-10",
+            "2022-07-11",
+            "2022-07-30",
+            "2022-08-07",
+            "2022-08-08",
+            "2022-10-08",
+            "2022-12-16",
+            "2022-12-17",
+        )
+
+    def test_2023(self):
+        self.assertHoliday(
+            "2023-01-01",
+            "2023-04-21",
+            "2023-04-22",
+            "2023-04-23",
+            "2023-05-01",
+            "2023-06-28",
+            "2023-06-29",
+            "2023-06-30",
+            "2023-07-19",
+            "2023-07-27",
+            "2023-07-28",
+            "2023-09-27",
+            "2023-12-16",
+            "2023-12-17",
+        )
+
+    def test_hijri_based(self):
+        if not importlib.util.find_spec("hijri_converter"):
+            return
+
+        # Eid Al-Fitr.
+        self.assertHoliday(
+            "2020-05-24",
+            "2020-05-25",
+            "2020-05-26",
+        )
+
+        # Eid Al-Adha.
+        self.assertHoliday(
+            "2020-07-31",
+            "2020-08-01",
+            "2020-08-02",
+        )
+
+        # Islamic New Year.
+        self.assertHoliday(
+            "2020-08-20",
+        )