Repository: vacanza/python-holidays

Issue:
Add Papua New Guinea holidays
Links:
  - https://en.wikipedia.org/wiki/Public_holidays_in_Papua_New_Guinea
  - https://www.timeanddate.com/holidays/papua-new-guinea/


Discussion:
I'm working on this at the moment based on [the actual law itself as of 1953](http://www.paclii.org/pg/legis/consol_act/pha1953163.pdf) and [wayback machine copy for actual holiday dates between 2021-2024](https://web.archive.org/web/20201218104840/https://www.businessadvantagepng.com/papua-new-guinea-public-for-holidays/)

Resolving patch:
diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py
--- a/holidays/countries/__init__.py
+++ b/holidays/countries/__init__.py
@@ -111,6 +111,7 @@
 from .norway import Norway, NO, NOR
 from .pakistan import Pakistan, PK, PAK
 from .panama import Panama, PA, PAN
+from .papua_new_guinea import PapuaNewGuinea, PG, PNG
 from .paraguay import Paraguay, PY, PRY
 from .peru import Peru, PE, PER
 from .philippines import Philippines, PH, PHL
diff --git a/holidays/countries/papua_new_guinea.py b/holidays/countries/papua_new_guinea.py
new file mode 100644
--- /dev/null
+++ b/holidays/countries/papua_new_guinea.py
@@ -0,0 +1,175 @@
+#  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.calendars.gregorian import JAN, FEB, MAR, APR, JUN, SEP, NOV
+from holidays.groups import ChristianHolidays, InternationalHolidays, StaticHolidays
+from holidays.observed_holiday_base import ObservedHolidayBase, SUN_TO_NEXT_MON, SUN_TO_NEXT_TUE
+
+
+class PapuaNewGuinea(
+    ObservedHolidayBase, ChristianHolidays, InternationalHolidays, StaticHolidays
+):
+    """
+    References:
+      - http://www.paclii.org/pg/legis/consol_act/pha1953163.pdf # Public Holidays Act 1953
+      - https://en.wikipedia.org/wiki/Public_holidays_in_Papua_New_Guinea
+      - https://pnghausbung.com/kings-birthday-holiday-to-be-observed-on-16th-june/
+    Checked With:
+      - https://www.ipa.gov.pg/public/Holidays.aspx
+      - https://www.businessadvantagepng.com/papua-new-guinea-public-for-holidays/
+      - https://www.scribd.com/document/465334129/PNG-2019-Gazetted-Public-Holidays-pdf # 2019
+      - https://publicholidays.asia/wp-content/uploads/2020/01/PNG_PublicHolidays_2020.png # 2020
+      - https://publicholidays.asia/wp-content/uploads/2020/12/PNG_PublicHolidays_2021.pdf # 2021
+      - https://publicholidays.asia/wp-content/uploads/2022/01/PNG_PublicHolidays_2022.pdf # 2022
+      - https://publicholidays.asia/wp-content/uploads/2022/12/PNG_PublicHolidays_2023.pdf # 2023
+
+    Should a holiday listed, other than the Christmas Day, fall on a Sunday the next Monday
+    shall, unless the Head of State, acting on advice, declares otherwise, be observed as a
+    public holiday throughout the country.
+
+    When Christmas Day falls on a Sunday, the following Tuesday shall also be observed as a
+    public holiday.
+    """
+
+    country = "PG"
+    observed_label = "%s (Observed)"
+
+    def __init__(self, *args, **kwargs):
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        StaticHolidays.__init__(self, PapuaNewGuineaStaticHolidays)
+        kwargs.setdefault("observed_rule", SUN_TO_NEXT_MON)
+        super().__init__(*args, **kwargs)
+
+    def _populate_public_holidays(self):
+        # Public Holidays Law 1953 (No. 38 of 1953).
+        if self._year <= 1952:
+            return None
+
+        # Section 1: Public Holidays.
+        # - Easter Saturday is currently not gazetted as a Public Holiday in 2024.
+        # - While Easter Sunday itself is not listed, this is de facto always a day-off.
+
+        # New Year's Day.
+        self._add_observed(self._add_new_years_day("New Year's Day"))
+
+        # Good Friday.
+        self._add_good_friday("Good Friday")
+
+        if self._year <= 2023:
+            # Easter Saturday.
+            self._add_holy_saturday("Easter Saturday")
+
+        # Easter Sunday.
+        self._add_easter_sunday("Easter Sunday")
+
+        # Easter Monday.
+        self._add_easter_monday("Easter Monday")
+
+        # Papua New Guinea Remembrance Day.
+        self._add_observed(self._add_holiday_jul_23("Papua New Guinea Remembrance Day"))
+
+        # Christmas Day.
+        self._add_observed(self._add_christmas_day("Christmas Day"), rule=SUN_TO_NEXT_TUE)
+
+        # Boxing Day.
+        self._add_observed(self._add_christmas_day_two("Boxing Day"))
+
+        # Section 2: Independence Day or Days.
+
+        # Independence Day
+        # Commemorates the attainment of Independent Sovereign Statehood on Sep 16, 1975.
+
+        if self._year >= 1975:
+            # Independence Day.
+            self._add_observed(self._add_holiday_sep_16("Independence Day"))
+
+        # Section 3: Anniversary of Birthday of the Queen/King.
+        # In Papua New Guinea, it is usually celebrated on the second Monday of June every year.
+        # From 2023, the date changed to Jun 17 (Special Observed for 2023 on Jun 16).
+
+        if self._year <= 2022:
+            # Queen's Birthday.
+            self._add_holiday_2nd_mon_of_jun("Queen's Birthday")
+        else:
+            # King's Birthday.
+            self._add_holiday_jun_17("King's Birthday")
+
+        # Section 5: Additional Public Holidays.
+
+        # Grand Chief Sir Michael Somare Remembrance Day.
+        # First observed on Feb 26, 2022.
+        # As of 2024, all previous observances so far are done on an ad hoc basis.
+
+        if self._year >= 2022:
+            # Grand Chief Sir Michael Somare Remembrance Day.
+            self._add_holiday_feb_26("Grand Chief Sir Michael Somare Remembrance Day")
+
+        # National Repentance Day.
+        # Enacted Aug 15, 2011, celebrated by "prayer ceremonies" across the country.
+        # First observed on Aug 26, 2011, held annually since then on that date.
+
+        if self._year >= 2011:
+            # The National Repentance Day.
+            self._add_observed(self._add_holiday_aug_26("National Repentance Day"))
+
+
+class PG(PapuaNewGuinea):
+    pass
+
+
+class PNG(PapuaNewGuinea):
+    pass
+
+
+class PapuaNewGuineaStaticHolidays:
+    """
+    Starting from 2021 afterwards all state funerals are given special public holidays, though only some are day-off nationwide.
+
+    References:
+      - 2018 APEC Public Holiday*: https://www.rnz.co.nz/international/pacific-news/369989/papua-new-guinea-declares-apec-holiday  # noqa: E501
+      - 2021 Sir Mekere Morauta's Funeral: https://pnghausbung.com/friday-8th-declared-a-nation-wide-public-holiday-to-honour-late-sir-mekere/  # noqa: E501
+      - 2021 Sir Michael Somare's Day of Mourning: https://pnghausbung.com/2-weeks-mourning-period-for-late-sir-micheal-to-start-with-public-holiday-on-monday-pm/  # noqa: E501
+      - 2022 QE2's Funeral: https://www.thenational.com.pg/column-1-553/
+      - 2023 Sir Rabbie Namaliu's Funeral: https://pnghausbung.com/breaking-public-holiday-tomorrow-in-respect-of-late-sir-rabbies-state-funeral/  # noqa: E501
+
+    * Nov 15, 2018 is an APEC Holiday too, but for Port Moresby-only: https://www.businessadvantagepng.com/public-holidays-declared-in-port-moresby-due-to-apec-summit-says-ceo/  # noqa: E501
+    """
+
+    # National Day of Mourning for Sir Michael Somare.
+    sir_michael_somare_mourning_day = "National Day of Mourning for Sir Michael Somare"
+
+    # Grand Chief Sir Michael Somare Remembrance Day
+    sir_michael_somare_remembrance_day = "Grand Chief Sir Michael Somare Remembrance Day"
+
+    special_public_holidays = {
+        # APEC Leaders' Summit Public Holiday.
+        2018: (NOV, 16, "APEC Leaders' Summit Public Holiday"),
+        2021: (
+            # State Funeral of Sir Mekere Morauta.
+            (JAN, 8, "State Funeral of Sir Mekere Morauta"),
+            (MAR, 1, sir_michael_somare_mourning_day),
+            (MAR, 12, sir_michael_somare_mourning_day),
+        ),
+        # State Funeral of Queen Elizabeth II.
+        2022: (SEP, 19, "State Funeral of Queen Elizabeth II"),
+        # State Funeral of Sir Rabbie Namaliu.
+        2023: (APR, 18, "State Funeral of Sir Rabbie Namaliu"),
+    }
+
+    special_public_holidays_observed = {
+        2022: (FEB, 28, sir_michael_somare_remembrance_day),
+        2023: (
+            (FEB, 24, sir_michael_somare_remembrance_day),
+            (JUN, 16, "King's Birthday"),
+            (SEP, 15, "Independence Day"),
+        ),
+    }
diff --git a/holidays/registry.py b/holidays/registry.py
--- a/holidays/registry.py
+++ b/holidays/registry.py
@@ -117,6 +117,7 @@
     "norway": ("Norway", "NO", "NOR"),
     "pakistan": ("Pakistan", "PK", "PAK"),
     "panama": ("Panama", "PA", "PAN"),
+    "papua_new_guinea": ("PapuaNewGuinea", "PG", "PNG"),
     "paraguay": ("Paraguay", "PY", "PRY"),
     "peru": ("Peru", "PE", "PER"),
     "philippines": ("Philippines", "PH", "PHL"),


Test patch:
diff --git a/tests/countries/test_papua_new_guinea.py b/tests/countries/test_papua_new_guinea.py
new file mode 100644
--- /dev/null
+++ b/tests/countries/test_papua_new_guinea.py
@@ -0,0 +1,183 @@
+#  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.papua_new_guinea import PapuaNewGuinea, PG, PNG
+from tests.common import TestCase
+
+
+class TestPapuaNewGuinea(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass(
+            PapuaNewGuinea, years=range(1953, 2050), years_non_observed=range(1953, 2050)
+        )
+
+    def test_country_aliases(self):
+        self.assertCountryAliases(PapuaNewGuinea, PG, PNG)
+
+    def test_no_holidays(self):
+        self.assertNoHolidays(PapuaNewGuinea(years=1952))
+
+    def test_special_holidays(self):
+        dt = (
+            "2018-11-16",
+            "2021-01-08",
+            "2021-03-01",
+            "2021-03-12",
+            "2022-09-19",
+            "2023-04-18",
+        )
+        dt_observed = (
+            "2022-02-28",
+            "2023-02-24",
+            "2023-06-16",
+            "2023-09-15",
+        )
+        self.assertHoliday(dt, dt_observed)
+        self.assertNoNonObservedHoliday(dt_observed)
+
+    def test_1953(self):
+        # http://www.paclii.org/pg/legis/consol_act/pha1953163.pdf
+        self.assertHolidays(
+            PapuaNewGuinea(years=1953),
+            ("1953-01-01", "New Year's Day"),
+            ("1953-04-03", "Good Friday"),
+            ("1953-04-04", "Easter Saturday"),
+            ("1953-04-05", "Easter Sunday"),
+            ("1953-04-06", "Easter Monday"),
+            ("1953-06-08", "Queen's Birthday"),
+            ("1953-07-23", "Papua New Guinea Remembrance Day"),
+            ("1953-12-25", "Christmas Day"),
+            ("1953-12-26", "Boxing Day"),
+        )
+
+    def test_2019(self):
+        # https://www.scribd.com/document/465334129/PNG-2019-Gazetted-Public-Holidays-pdf
+        # https://pngiportal.org/directory/national-gazette-g560-602-2018
+        self.assertHolidays(
+            PapuaNewGuinea(years=2019),
+            ("2019-01-01", "New Year's Day"),
+            ("2019-04-19", "Good Friday"),
+            ("2019-04-20", "Easter Saturday"),
+            ("2019-04-21", "Easter Sunday"),
+            ("2019-04-22", "Easter Monday"),
+            ("2019-06-10", "Queen's Birthday"),
+            ("2019-07-23", "Papua New Guinea Remembrance Day"),
+            ("2019-08-26", "National Repentance Day"),
+            ("2019-09-16", "Independence Day"),
+            ("2019-12-25", "Christmas Day"),
+            ("2019-12-26", "Boxing Day"),
+        )
+
+    def test_2020(self):
+        # https://publicholidays.asia/wp-content/uploads/2020/01/PNG_PublicHolidays_2020.png
+        self.assertHolidays(
+            PapuaNewGuinea(years=2020),
+            ("2020-01-01", "New Year's Day"),
+            ("2020-04-10", "Good Friday"),
+            ("2020-04-11", "Easter Saturday"),
+            ("2020-04-12", "Easter Sunday"),
+            ("2020-04-13", "Easter Monday"),
+            ("2020-06-08", "Queen's Birthday"),
+            ("2020-07-23", "Papua New Guinea Remembrance Day"),
+            ("2020-08-26", "National Repentance Day"),
+            ("2020-09-16", "Independence Day"),
+            ("2020-12-25", "Christmas Day"),
+            ("2020-12-26", "Boxing Day"),
+        )
+
+    def test_2021(self):
+        # https://publicholidays.asia/wp-content/uploads/2020/12/PNG_PublicHolidays_2021.pdf
+        # https://www.efpng.org.pg/wp-content/uploads/2021/05/CIRCULAR-No.17-2021-AMENDMENTS-TO-2021-PUBLIC-HOLIDAY.pdf  # noqa: E501
+        # Easter dates were later corrected as of https://web.archive.org/web/20210411125811/https://www.businessadvantagepng.com/papua-new-guinea-public-for-holidays/  # noqa: E501
+        self.assertHolidays(
+            PapuaNewGuinea(years=2021),
+            ("2021-01-01", "New Year's Day"),
+            ("2021-01-08", "State Funeral of Sir Mekere Morauta"),
+            ("2021-03-01", "National Day of Mourning for Sir Michael Somare"),
+            ("2021-03-12", "National Day of Mourning for Sir Michael Somare"),
+            ("2021-04-02", "Good Friday"),
+            ("2021-04-03", "Easter Saturday"),
+            ("2021-04-04", "Easter Sunday"),
+            ("2021-04-05", "Easter Monday"),
+            ("2021-06-14", "Queen's Birthday"),
+            ("2021-07-23", "Papua New Guinea Remembrance Day"),
+            ("2021-08-26", "National Repentance Day"),
+            ("2021-09-16", "Independence Day"),
+            ("2021-12-25", "Christmas Day"),
+            ("2021-12-26", "Boxing Day"),
+            ("2021-12-27", "Boxing Day (Observed)"),
+        )
+
+    def test_2022(self):
+        # https://publicholidays.asia/wp-content/uploads/2022/01/PNG_PublicHolidays_2022.pdf
+        # Somare Day public holiday was observed on Feb 28 instead as of
+        # https://web.archive.org/web/20220703204538/https://www.businessadvantagepng.com/papua-new-guinea-public-for-holidays/  # noqa: E501
+        self.assertHolidays(
+            PapuaNewGuinea(years=2022),
+            ("2022-01-01", "New Year's Day"),
+            ("2022-02-26", "Grand Chief Sir Michael Somare Remembrance Day"),
+            ("2022-02-28", "Grand Chief Sir Michael Somare Remembrance Day (Observed)"),
+            ("2022-04-15", "Good Friday"),
+            ("2022-04-16", "Easter Saturday"),
+            ("2022-04-17", "Easter Sunday"),
+            ("2022-04-18", "Easter Monday"),
+            ("2022-06-13", "Queen's Birthday"),
+            ("2022-07-23", "Papua New Guinea Remembrance Day"),
+            ("2022-08-26", "National Repentance Day"),
+            ("2022-09-16", "Independence Day"),
+            ("2022-09-19", "State Funeral of Queen Elizabeth II"),
+            ("2022-12-25", "Christmas Day"),
+            ("2022-12-26", "Boxing Day"),
+            ("2022-12-27", "Christmas Day (Observed)"),
+        )
+
+    def test_2023(self):
+        # https://publicholidays.asia/wp-content/uploads/2022/12/PNG_PublicHolidays_2023.pdf
+        # https://pnghausbung.com/kings-birthday-holiday-to-be-observed-on-16th-june/
+        self.assertHolidays(
+            PapuaNewGuinea(years=2023),
+            ("2023-01-01", "New Year's Day"),
+            ("2023-01-02", "New Year's Day (Observed)"),
+            ("2023-02-24", "Grand Chief Sir Michael Somare Remembrance Day (Observed)"),
+            ("2023-02-26", "Grand Chief Sir Michael Somare Remembrance Day"),
+            ("2023-04-07", "Good Friday"),
+            ("2023-04-08", "Easter Saturday"),
+            ("2023-04-09", "Easter Sunday"),
+            ("2023-04-10", "Easter Monday"),
+            ("2023-04-18", "State Funeral of Sir Rabbie Namaliu"),
+            ("2023-06-16", "King's Birthday (Observed)"),
+            ("2023-06-17", "King's Birthday"),
+            ("2023-07-23", "Papua New Guinea Remembrance Day"),
+            ("2023-07-24", "Papua New Guinea Remembrance Day (Observed)"),
+            ("2023-08-26", "National Repentance Day"),
+            ("2023-09-15", "Independence Day (Observed)"),
+            ("2023-09-16", "Independence Day"),
+            ("2023-12-25", "Christmas Day"),
+            ("2023-12-26", "Boxing Day"),
+        )
+
+    def test_2024(self):
+        # https://web.archive.org/web/20231221053513/https://www.businessadvantagepng.com/papua-new-guinea-public-for-holidays/  # noqa: E501
+        self.assertHolidays(
+            PapuaNewGuinea(years=2024),
+            ("2024-01-01", "New Year's Day"),
+            ("2024-02-26", "Grand Chief Sir Michael Somare Remembrance Day"),
+            ("2024-03-29", "Good Friday"),
+            ("2024-03-31", "Easter Sunday"),
+            ("2024-04-01", "Easter Monday"),
+            ("2024-06-17", "King's Birthday"),
+            ("2024-07-23", "Papua New Guinea Remembrance Day"),
+            ("2024-08-26", "National Repentance Day"),
+            ("2024-09-16", "Independence Day"),
+            ("2024-12-25", "Christmas Day"),
+            ("2024-12-26", "Boxing Day"),
+        )