Repository: vacanza/python-holidays

Issue:
Add El Salvador holidays
Links:
  - https://www.timeanddate.com/holidays/el-salvador/
  - https://www.officeholidays.com/countries/el-salvador/2022


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
@@ -45,6 +45,7 @@
 from .dominican_republic import DominicanRepublic, DO, DOM
 from .ecuador import Ecuador, EC, ECU
 from .egypt import Egypt, EG, EGY
+from .el_salvador import ElSalvador, SV, SLV
 from .estonia import Estonia, EE, EST
 from .eswatini import Eswatini, SZ, SZW, Swaziland
 from .ethiopia import Ethiopia, ET, ETH
diff --git a/holidays/countries/el_salvador.py b/holidays/countries/el_salvador.py
new file mode 100644
--- /dev/null
+++ b/holidays/countries/el_salvador.py
@@ -0,0 +1,101 @@
+#  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 <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/dr-prodigy/python-holidays
+#  License: MIT (see LICENSE file)
+
+from holidays.constants import MAY, JUN, AUG, SEP
+from holidays.holiday_base import HolidayBase
+from holidays.holiday_groups import ChristianHolidays, InternationalHolidays
+
+
+class ElSalvador(HolidayBase, ChristianHolidays, InternationalHolidays):
+    """
+    References:
+    - https://www.transparencia.gob.sv/institutions/gd-usulutan/documents/192280/download   # noqa: E501
+    - https://www.timeanddate.com/holidays/el-salvador
+    - https://www.officeholidays.com/countries/el-salvador
+    """
+
+    country = "SV"
+    subdivisions = (
+        "AH",  # Ahuachapán
+        "CA",  # Cabañas
+        "CH",  # Chalatenango
+        "CU",  # Cuscatlán
+        "LI",  # La Libertad
+        "MO",  # Morazán
+        "PA",  # La Paz
+        "SA",  # Santa Ana
+        "SM",  # San Miguel
+        "SO",  # Sonsonate
+        "SS",  # San Salvador
+        "SV",  # San Vicente
+        "UN",  # La Unión
+        "US",  # Usulután
+    )
+
+    def __init__(self, *args, **kwargs):
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
+
+    def _populate(self, year):
+        super()._populate(year)
+
+        # New Year's Day.
+        self._add_new_years_day("New Year's Day")
+
+        # Maundy Thursday.
+        self._add_holy_thursday("Maundy Thursday")
+
+        # Good Friday.
+        self._add_good_friday("Good Friday")
+
+        # Holy Saturday.
+        self._add_holy_saturday("Holy Saturday")
+
+        # Labor Day.
+        self._add_labor_day("Labor Day")
+
+        if year >= 2016:
+            # Legislative Decree #399 from Apr 14, 2016
+            # Mothers' Day.
+            self._add_holiday("Mothers' Day", MAY, 10)
+
+        if year >= 2013:
+            # Legislative Decree #208 from Jun 17, 2012
+            # Fathers' Day.
+            self._add_holiday("Fathers' Day", JUN, 17)
+
+        # Feast of San Salvador.
+        self._add_holiday("Feast of San Salvador", AUG, 6)
+
+        # Independence Day.
+        self._add_holiday("Independence Day", SEP, 15)
+
+        # All Souls' Day.
+        self._add_all_souls_day("All Souls' Day")
+
+        # Christmas Day.
+        self._add_christmas_day("Christmas Day")
+
+    def _add_subdiv_ss_holidays(self):
+        # San Salvador Day 1.
+        self._add_holiday("San Salvador Day 1", AUG, 3)
+
+        # San Salvador Day 2.
+        self._add_holiday("San Salvador Day 2", AUG, 5)
+
+
+class SV(ElSalvador):
+    pass
+
+
+class SLV(ElSalvador):
+    pass
diff --git a/holidays/registry.py b/holidays/registry.py
--- a/holidays/registry.py
+++ b/holidays/registry.py
@@ -53,6 +53,7 @@
     "dominican_republic": ("DominicanRepublic", "DO", "DOM"),
     "ecuador": ("Ecuador", "EC", "ECU"),
     "egypt": ("Egypt", "EG", "EGY"),
+    "el_salvador": ("ElSalvador", "SV", "SLV"),
     "estonia": ("Estonia", "EE", "EST"),
     "eswatini": ("Eswatini", "SZ", "SZW", "Swaziland"),
     "ethiopia": ("Ethiopia", "ET", "ETH"),


Test patch:
diff --git a/tests/countries/test_el_salvador.py b/tests/countries/test_el_salvador.py
new file mode 100644
--- /dev/null
+++ b/tests/countries/test_el_salvador.py
@@ -0,0 +1,83 @@
+#  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 <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/dr-prodigy/python-holidays
+#  License: MIT (see LICENSE file)
+
+from holidays.countries.el_salvador import ElSalvador, SV, SLV
+from tests.common import TestCase
+
+
+class TestElSalvador(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass(ElSalvador, years=range(2000, 2050))
+
+    def test_country_aliases(self):
+        self.assertCountryAliases(ElSalvador, SV, SLV)
+
+    def test_mothers_day(self):
+        name = "Mothers' Day"
+        self.assertHolidaysName(
+            name, (f"{year}-05-10" for year in range(2016, 2050))
+        )
+        self.assertNoHoliday(f"{year}-05-10" for year in range(2000, 2016))
+        self.assertNoHolidayNameInYears(name, range(2000, 2016))
+
+    def test_fathers_day(self):
+        name = "Fathers' Day"
+        self.assertHolidaysName(
+            name, (f"{year}-06-17" for year in range(2013, 2050))
+        )
+        self.assertNoHoliday(f"{year}-06-17" for year in range(2000, 2013))
+        self.assertNoHolidayNameInYears(name, range(2000, 2013))
+
+    def test_ss_holidays(self):
+        name1 = "San Salvador Day 1"
+        name2 = "San Salvador Day 2"
+        self.assertNoHolidayNameInYears(name1, range(2000, 2050))
+        self.assertNoHolidayNameInYears(name2, range(2000, 2050))
+        ss_holidays = ElSalvador(subdiv="SS", years=range(2000, 2050))
+        self.assertHolidaysName(
+            name1, ss_holidays, (f"{year}-08-03" for year in range(2016, 2050))
+        )
+        self.assertHolidaysName(
+            name2, ss_holidays, (f"{year}-08-05" for year in range(2016, 2050))
+        )
+
+    def test_2021(self):
+        self.assertHolidays(
+            ElSalvador(years=2021),
+            ("2021-01-01", "New Year's Day"),
+            ("2021-04-01", "Maundy Thursday"),
+            ("2021-04-02", "Good Friday"),
+            ("2021-04-03", "Holy Saturday"),
+            ("2021-05-01", "Labor Day"),
+            ("2021-05-10", "Mothers' Day"),
+            ("2021-06-17", "Fathers' Day"),
+            ("2021-08-06", "Feast of San Salvador"),
+            ("2021-09-15", "Independence Day"),
+            ("2021-11-02", "All Souls' Day"),
+            ("2021-12-25", "Christmas Day"),
+        )
+
+    def test_2022(self):
+        self.assertHolidays(
+            ElSalvador(years=2022),
+            ("2022-01-01", "New Year's Day"),
+            ("2022-04-14", "Maundy Thursday"),
+            ("2022-04-15", "Good Friday"),
+            ("2022-04-16", "Holy Saturday"),
+            ("2022-05-01", "Labor Day"),
+            ("2022-05-10", "Mothers' Day"),
+            ("2022-06-17", "Fathers' Day"),
+            ("2022-08-06", "Feast of San Salvador"),
+            ("2022-09-15", "Independence Day"),
+            ("2022-11-02", "All Souls' Day"),
+            ("2022-12-25", "Christmas Day"),
+        )