Repository: vacanza/python-holidays

Issue:
Add Seychelles holidays
Links:
  - https://en.wikipedia.org/wiki/Public_holidays_in_Seychelles
  - https://www.timeanddate.com/holidays/seychelles/
  - https://www.cbs.sc/PublicHolidays.html


Discussion:
I'm working on this one, here's the actual [Public Holidays Act](https://seylii.org/akn/sc/act/1976/19/eng@2012-06-30).
Thanks a lot, @PPsyrius!

Resolving patch:
diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py
--- a/holidays/countries/__init__.py
+++ b/holidays/countries/__init__.py
@@ -126,6 +126,7 @@
 from .san_marino import SanMarino, SM, SMR
 from .saudi_arabia import SaudiArabia, SA, SAU
 from .serbia import Serbia, RS, SRB
+from .seychelles import Seychelles, SC, SYC
 from .singapore import Singapore, SG, SGP
 from .slovakia import Slovakia, SK, SVK
 from .slovenia import Slovenia, SI, SVN
diff --git a/holidays/countries/seychelles.py b/holidays/countries/seychelles.py
new file mode 100644
--- /dev/null
+++ b/holidays/countries/seychelles.py
@@ -0,0 +1,174 @@
+#  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 gettext import gettext as tr
+
+from holidays.calendars.gregorian import JAN, MAR, MAY, SEP, OCT, DEC
+from holidays.groups import ChristianHolidays, InternationalHolidays, StaticHolidays
+from holidays.observed_holiday_base import ObservedHolidayBase, SUN_TO_NEXT_MON
+
+
+class Seychelles(ObservedHolidayBase, ChristianHolidays, InternationalHolidays):
+    """
+    https://www.psb.gov.sc/public-holidays
+    https://www.cbs.sc/PublicHolidays.html
+
+    [Act 19 of 1976, 1994 Amendment]
+        Oldest Seychelles Holidays Law available online in full.
+        https://seylii.org/akn/sc/act/1976/19/eng@2012-06-30
+    [Act 11 of 2014]
+        Holidays names changed.
+        https://seylii.org/akn/sc/act/2014/11/eng@2014-08-04
+    [Act 3 of 2017]
+        Added Easter Monday, repealing Liberation Day.
+        https://seylii.org/akn/sc/act/2017/3/eng@2017-04-12
+
+    Where any public holiday, except Sunday, falls on a Sunday the next following day,
+    not being itself a public holiday, shall be a public holiday.
+    """
+
+    country = "SC"
+    default_language = "en_SC"
+    # %s (observed).
+    observed_label = tr("%s (observed)")
+    supported_languages = ("en_SC", "en_US")
+
+    def __init__(self, *args, **kwargs):
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        StaticHolidays.__init__(self, SeychellesStaticHolidays)
+        kwargs.setdefault("observed_rule", SUN_TO_NEXT_MON)
+        super().__init__(*args, **kwargs)
+
+    def _populate_public_holidays(self):
+        # Earliest source is the 1994 amendment of Seychelles Public Holidays Act.
+        if self._year <= 1993:
+            return None
+
+        # New Year's Day.
+        self._add_new_years_day(tr("New Year's Day"))
+
+        # New Year Holiday.
+        self._add_observed(self._add_new_years_day_two(tr("New Year Holiday")))
+
+        # Good Friday.
+        self._add_good_friday(tr("Good Friday"))
+
+        # Easter Saturday.
+        self._add_holy_saturday(tr("Easter Saturday"))
+
+        if self._year >= 2017:
+            # Easter Monday.
+            self._add_easter_monday(tr("Easter Monday"))
+
+        # Labour Day.
+        self._add_observed(self._add_labor_day(tr("Labour Day")))
+
+        # The Fete Dieu.
+        self._add_corpus_christi_day(tr("The Fete Dieu"))
+
+        if self._year <= 2016:
+            # Liberation Day.
+            self._add_observed(self._add_holiday_jun_5(tr("Liberation Day")))
+
+        self._add_observed(
+            self._add_holiday_jun_18(
+                # National Day.
+                tr("National Day")
+                if self._year <= 2014
+                # Constitution Day.
+                else tr("Constitution Day")
+            )
+        )
+
+        self._add_observed(
+            self._add_holiday_jun_29(
+                # Independence Day.
+                tr("Independence Day")
+                if self._year <= 2014
+                # Independence (National) Day.
+                else tr("Independence (National) Day")
+            )
+        )
+
+        # Assumption Day.
+        self._add_observed(self._add_assumption_of_mary_day(tr("Assumption Day")))
+
+        # All Saints Day.
+        self._add_observed(self._add_all_saints_day(tr("All Saints Day")))
+
+        self._add_observed(
+            # The Feast of the Immaculate Conception.
+            self._add_immaculate_conception_day(tr("The Feast of the Immaculate Conception"))
+        )
+
+        # Christmas Day.
+        self._add_observed(self._add_christmas_day(tr("Christmas Day")))
+
+
+class SC(Seychelles):
+    pass
+
+
+class SYC(Seychelles):
+    pass
+
+
+class SeychellesStaticHolidays:
+    """
+    Sources:
+     - https://seylii.org/akn/sc/act/si/2015/58/eng@2015-12-01
+     - https://seylii.org/akn/sc/act/si/2015/59/eng@2015-12-11
+     - https://seylii.org/akn/sc/act/si/2016/58/eng@2016-09-06
+     - https://seylii.org/akn/sc/act/si/2019/10/eng@2019-03-05
+     - https://seylii.org/akn/sc/act/si/2019/61/eng@2019-10-18
+     - https://seylii.org/akn/sc/act/si/2020/134/eng@2020-09-17
+     - https://seylii.org/akn/sc/act/si/2020/154/eng@2020-10-26
+     - https://www.statehouse.gov.sc/news/1765/public-holiday-october-1
+     - https://www.egov.sc/PressRoom/DisplayPressRelease.aspx?PRLID=196
+     - https://www.nation.sc/archive/216478/saturday-may-12-2007-public-holiday
+
+    All Election Dates usually proceed from the Outer Islands first, then the Inner Islands, and
+    the main capital, Mahé, on the last day. The current implementation only uses the last day,
+    as officially decreed in 2007, 2011, 2015, and 2020.
+    """
+
+    # Bridge Public Holiday.
+    bridge_public_holiday = tr("Bridge Public Holiday")
+
+    # Presidential Election Day.
+    presidential_election_day = tr("Presidential Election Day")
+
+    # Parliamentary Election Day.
+    parliamentary_election_day = tr("Parliamentary Election Day")
+
+    # General Election Day.
+    general_election_day = tr("General Election Day")
+
+    special_public_holidays = {
+        2007: (MAY, 12, presidential_election_day),
+        2011: (
+            (MAY, 21, presidential_election_day),
+            (OCT, 1, parliamentary_election_day),
+        ),
+        2015: (
+            (DEC, 5, presidential_election_day),
+            (DEC, 18, presidential_election_day),
+        ),
+        2016: (SEP, 10, parliamentary_election_day),
+        # Funeral of the Former President France Albert René.
+        2019: (MAR, 7, tr("Funeral of the Former President France Albert René")),
+        2020: (
+            (JAN, 3, bridge_public_holiday),
+            (OCT, 24, general_election_day),
+            (OCT, 26, bridge_public_holiday),
+        ),
+    }
diff --git a/holidays/registry.py b/holidays/registry.py
--- a/holidays/registry.py
+++ b/holidays/registry.py
@@ -132,6 +132,7 @@
     "san_marino": ("SanMarino", "SM", "SMR"),
     "saudi_arabia": ("SaudiArabia", "SA", "SAU"),
     "serbia": ("Serbia", "RS", "SRB"),
+    "seychelles": ("Seychelles", "SC", "SYC"),
     "singapore": ("Singapore", "SG", "SGP"),
     "slovakia": ("Slovakia", "SK", "SVK"),
     "slovenia": ("Slovenia", "SI", "SVN"),


Test patch:
diff --git a/tests/countries/test_seychelles.py b/tests/countries/test_seychelles.py
new file mode 100644
--- /dev/null
+++ b/tests/countries/test_seychelles.py
@@ -0,0 +1,180 @@
+#  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 unittest import TestCase
+
+from holidays.countries.seychelles import Seychelles, SC, SYC
+from tests.common import CommonCountryTests
+
+
+class TestSeychelles(CommonCountryTests, TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass(Seychelles)
+
+    def test_country_aliases(self):
+        self.assertAliases(Seychelles, SC, SYC)
+
+    def test_no_holidays(self):
+        self.assertNoHolidays(Seychelles(years=1993))
+
+    def test_special_holidays(self):
+        # Election Dates have its own separate checklists.
+        self.assertHoliday(
+            "2007-05-12",
+            "2011-05-21",
+            "2011-10-01",
+            "2015-12-05",
+            "2015-12-18",
+            "2016-09-10",
+            "2019-03-07",
+            "2020-01-03",
+            "2020-10-24",
+            "2020-10-26",
+        )
+
+    def test_2009(self):
+        # https://web.archive.org/web/20091208104016/https://www.cbs.sc/PublicHolidays.html
+        self.assertHolidays(
+            Seychelles(years=2009),
+            ("2009-01-01", "New Year's Day"),
+            ("2009-01-02", "New Year Holiday"),
+            ("2009-04-10", "Good Friday"),
+            ("2009-04-11", "Easter Saturday"),
+            ("2009-05-01", "Labour Day"),
+            ("2009-06-05", "Liberation Day"),
+            ("2009-06-11", "The Fete Dieu"),
+            ("2009-06-18", "National Day"),
+            ("2009-06-29", "Independence Day"),
+            ("2009-08-15", "Assumption Day"),
+            ("2009-11-01", "All Saints Day"),
+            ("2009-11-02", "All Saints Day (observed)"),
+            ("2009-12-08", "The Feast of the Immaculate Conception"),
+            ("2009-12-25", "Christmas Day"),
+        )
+
+    def test_2012(self):
+        # https://web.archive.org/web/20121023221205/https://www.cbs.sc/PublicHolidays.html
+        self.assertHolidays(
+            Seychelles(years=2012),
+            ("2012-01-01", "New Year's Day"),
+            ("2012-01-02", "New Year Holiday"),
+            ("2012-04-06", "Good Friday"),
+            ("2012-04-07", "Easter Saturday"),
+            ("2012-05-01", "Labour Day"),
+            ("2012-06-05", "Liberation Day"),
+            ("2012-06-07", "The Fete Dieu"),
+            ("2012-06-18", "National Day"),
+            ("2012-06-29", "Independence Day"),
+            ("2012-08-15", "Assumption Day"),
+            ("2012-11-01", "All Saints Day"),
+            ("2012-12-08", "The Feast of the Immaculate Conception"),
+            ("2012-12-25", "Christmas Day"),
+        )
+
+    def test_2019(self):
+        # https://web.archive.org/web/20191029202210/http://cbs.sc/PublicHolidays.html
+        self.assertHolidays(
+            Seychelles(years=2019),
+            ("2019-01-01", "New Year's Day"),
+            ("2019-01-02", "New Year Holiday"),
+            ("2019-03-07", "Funeral of the Former President France Albert René"),
+            ("2019-04-19", "Good Friday"),
+            ("2019-04-20", "Easter Saturday"),
+            ("2019-04-22", "Easter Monday"),
+            ("2019-05-01", "Labour Day"),
+            ("2019-06-20", "The Fete Dieu"),
+            ("2019-06-18", "Constitution Day"),
+            ("2019-06-29", "Independence (National) Day"),
+            ("2019-08-15", "Assumption Day"),
+            ("2019-11-01", "All Saints Day"),
+            ("2019-12-08", "The Feast of the Immaculate Conception"),
+            ("2019-12-09", "The Feast of the Immaculate Conception (observed)"),
+            ("2019-12-25", "Christmas Day"),
+        )
+
+    def test_2021(self):
+        # https://web.archive.org/web/20211206090711/https://www.cbs.sc/PublicHolidays.html
+        self.assertHolidays(
+            Seychelles(years=2021),
+            ("2021-01-01", "New Year's Day"),
+            ("2021-01-02", "New Year Holiday"),
+            ("2021-04-02", "Good Friday"),
+            ("2021-04-03", "Easter Saturday"),
+            ("2021-04-05", "Easter Monday"),
+            ("2021-05-01", "Labour Day"),
+            ("2021-06-03", "The Fete Dieu"),
+            ("2021-06-18", "Constitution Day"),
+            ("2021-06-29", "Independence (National) Day"),
+            ("2021-08-15", "Assumption Day"),
+            ("2021-08-16", "Assumption Day (observed)"),
+            ("2021-11-01", "All Saints Day"),
+            ("2021-12-08", "The Feast of the Immaculate Conception"),
+            ("2021-12-25", "Christmas Day"),
+        )
+
+    def test_2023(self):
+        # https://web.archive.org/web/20230318041823/https://www.cbs.sc/PublicHolidays.html
+        self.assertHolidays(
+            Seychelles(years=2023),
+            ("2023-01-01", "New Year's Day"),
+            ("2023-01-02", "New Year Holiday"),
+            ("2023-04-07", "Good Friday"),
+            ("2023-04-08", "Easter Saturday"),
+            ("2023-04-10", "Easter Monday"),
+            ("2023-05-01", "Labour Day"),
+            ("2023-06-08", "The Fete Dieu"),
+            ("2023-06-18", "Constitution Day"),
+            ("2023-06-19", "Constitution Day (observed)"),
+            ("2023-06-29", "Independence (National) Day"),
+            ("2023-08-15", "Assumption Day"),
+            ("2023-11-01", "All Saints Day"),
+            ("2023-12-08", "The Feast of the Immaculate Conception"),
+            ("2023-12-25", "Christmas Day"),
+        )
+
+    def test_l10n_default(self):
+        # https://www.psb.gov.sc/public-holidays
+        self.assertLocalizedHolidays(
+            ("2024-01-01", "New Year's Day"),
+            ("2024-01-02", "New Year Holiday"),
+            ("2024-03-29", "Good Friday"),
+            ("2024-03-30", "Easter Saturday"),
+            ("2024-04-01", "Easter Monday"),
+            ("2024-05-01", "Labour Day"),
+            ("2024-05-30", "The Fete Dieu"),
+            ("2024-06-18", "Constitution Day"),
+            ("2024-06-29", "Independence (National) Day"),
+            ("2024-08-15", "Assumption Day"),
+            ("2024-11-01", "All Saints Day"),
+            ("2024-12-08", "The Feast of the Immaculate Conception"),
+            ("2024-12-09", "The Feast of the Immaculate Conception (observed)"),
+            ("2024-12-25", "Christmas Day"),
+        )
+
+    def test_l10n_en_us(self):
+        self.assertLocalizedHolidays(
+            "en_US",
+            ("2024-01-01", "New Year's Day"),
+            ("2024-01-02", "New Year Holiday"),
+            ("2024-03-29", "Good Friday"),
+            ("2024-03-30", "Easter Saturday"),
+            ("2024-04-01", "Easter Monday"),
+            ("2024-05-01", "Labor Day"),
+            ("2024-05-30", "Corpus Christi"),
+            ("2024-06-18", "Constitution Day"),
+            ("2024-06-29", "Independence (National) Day"),
+            ("2024-08-15", "Assumption Day"),
+            ("2024-11-01", "All Saints Day"),
+            ("2024-12-08", "Immaculate Conception"),
+            ("2024-12-09", "Immaculate Conception (observed)"),
+            ("2024-12-25", "Christmas Day"),
+        )