Repository: vacanza/holidays (python)

Issue:
Add Cocos Islands holidays
URLs:
 - https://en.wikipedia.org/wiki/Public_holidays_in_the_Cocos_(Keeling)_Islands
 - https://www.infrastructure.gov.au/territories-regions-cities/territories/indian-ocean-territories/community-bulletins/2022/A07-2022

Pull request:
Add Cocos Islands holidays
<!--
  Thanks for contributing to holidays!
-->

## Proposed change

<!--
  Describe the big picture of your changes.
  Don't forget to link your PR to an existing issue if any.
-->

Add Cocos Islands holidays.
Resolves #2426.

## Type of change

<!--
  Type of change you want to introduce. Please, check one (1) box only!
  If your PR requires multiple boxes to be checked, most likely it needs to
  be split into multiple PRs.
-->

- [x] New country/market holidays support (thank you!)
- [ ] Supported country/market holidays update (calendar discrepancy fix, localization)
- [ ] Existing code/documentation/test/process quality improvement (best practice, cleanup, refactoring, optimization)
- [ ] Dependency update (version deprecation/pin/upgrade)
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] Breaking change (a code change causing existing functionality to break)
- [ ] New feature (new `holidays` functionality in general)

## Checklist

<!--
  Put an `x` in the boxes that apply. You can change them after PR is created.
-->

- [x] I've followed the [contributing guidelines][contributing-guidelines]
- [x] I've successfully run `make check`, all checks and tests are green

<!--
  Thanks again for your contribution!
-->

[contributing-guidelines]: https://github.com/vacanza/holidays/blob/dev/CONTRIBUTING.md
[docs]: https://github.com/vacanza/holidays/tree/dev/docs/source


Patch:
diff --git a/README.md b/README.md
index 88b84229..277f5466 100644
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ and detailed information.
 
 ## Available Countries
 
-We currently support 171 country codes. The standard way to refer to a country is by using its [ISO
+We currently support 172 country codes. The standard way to refer to a country is by using its [ISO
 3166-1 alpha-2 code](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes), the same used
 for domain names, and for a subdivision its [ISO 3166-2
 code](https://en.wikipedia.org/wiki/ISO_3166-2). Some countries have common or foreign names or
@@ -385,6 +385,13 @@ any) in brackets, available languages and additional holiday categories. All cou
 <td>HALF_DAY</td>
 </tr>
 <tr>
+<td>Cocos Islands</td>
+<td>CC</td>
+<td></td>
+<td>coa_CC, <strong>en_CC</strong>,  en_US</td>
+<td></td>
+</tr>
+<tr>
 <td>Colombia</td>
 <td>CO</td>
 <td></td>
diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py
index 26e9bee1..a8d665ea 100644
--- a/holidays/countries/__init__.py
+++ b/holidays/countries/__init__.py
@@ -46,6 +46,7 @@ from .canada import Canada, CA, CAN
 from .chad import Chad, TD, TCD
 from .chile import Chile, CL, CHL
 from .china import China, CN, CHN
+from .cocos_islands import CocosIslands, CC, CCK
 from .colombia import Colombia, CO, COL
 from .congo import Congo, CG, COG
 from .costa_rica import CostaRica, CR, CRI
diff --git a/holidays/countries/cocos_islands.py b/holidays/countries/cocos_islands.py
new file mode 100644
index 00000000..dee17fa0
--- /dev/null
+++ b/holidays/countries/cocos_islands.py
@@ -0,0 +1,259 @@
+#  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: Vacanza Team and individual contributors (see CONTRIBUTORS file)
+#           dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/vacanza/holidays
+#  License: MIT (see LICENSE file)
+
+from gettext import gettext as tr
+
+from holidays.calendars import _CustomIslamicHolidays
+from holidays.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
+from holidays.groups import (
+    ChristianHolidays,
+    InternationalHolidays,
+    IslamicHolidays,
+    StaticHolidays,
+)
+from holidays.observed_holiday_base import (
+    ObservedHolidayBase,
+    MON_TO_NEXT_TUE,
+    SAT_SUN_TO_NEXT_MON,
+    SAT_SUN_TO_NEXT_MON_TUE,
+)
+
+
+class CocosIslands(
+    ObservedHolidayBase, ChristianHolidays, InternationalHolidays, IslamicHolidays, StaticHolidays
+):
+    """Cocos (Keeling) Islands holidays.
+
+    References:
+        * <https://en.wikipedia.org/wiki/Public_holidays_in_the_Cocos_(Keeling)_Islands>
+        * <https://www.infrastructure.gov.au/territories-regions-cities/territories/indian-ocean-territories/community-bulletins>
+        * <https://www.infrastructure.gov.au/territories-regions-cities/territories/indian-ocean-territories/gazettes-bulletins>
+
+        * [2007](https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2006/02_2006_Public_Holidays_2007_CKI.doc)
+        * [2008](https://web.archive.org/web/20240718120923/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2007/06-2007_Public_Holidays_CKI.pdf)
+        * [2008 Eid al-Fitr](https://web.archive.org/web/20240331104649/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2008/03_2008_Observance_of_Hari_Raya_Puasa_2008.pdf)
+        * [2009](https://web.archive.org/web/20231208153529/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2008/01-2008-2009-public-holiday-CKI-gazette.pdf)
+        * [2010](https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2009/2009-Gazette_6-2009-CKI-Proclamation_of_2010_Special_Public_Bank_Holidays.pdf)
+        * [2013](https://web.archive.org/web/20240805055409/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2012/2012-Gazette_8-2012-CKI-Proclamation_of_2013_Public_Holidays_for_Cocos_(Keeling)_Islands.pdf)
+        * [2014](https://web.archive.org/web/20240718123844/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2013/2013-Gazette_3-2013-Cocos_K_Islands_2014_Public_Holidays.pdf)
+        * [2016](https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2015/2015-Gazette_4-2015-CKI-Proclamation_of_2016_Special_Public_Bank_Holidays.pdf)
+        * [2016 Eid al-Fitr](https://web.archive.org/web/20231208203746/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2016/2016-Gazette_3-2016-CKI-Proclamation_Special_Public_and_Bank_Holidays_2016.pdf)
+        * [2017](https://web.archive.org/web/20240303203132/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_gazette/files/2016/2016-Gazette_2-2016-CKI-Proclamation_Special_Public_and_Bank_Holidays_2017.pdf)
+        * [2019](https://web.archive.org/web/20241123131420/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_bulletins/2018/files/A38-2018.pdf)
+        * [2019 Act of Self Determination Day](https://web.archive.org/web/20220518200522/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_bulletins/2019/files/A10-2019-bank-holidays.pdf)
+        * [2020](https://web.archive.org/web/20240521203357/https://www.infrastructure.gov.au/sites/default/files/migrated/territories/indian_ocean/iot_bulletins/2019/files/A53-2019.pdf)
+        * [2021](https://web.archive.org/web/20250502204052/https://www.infrastructure.gov.au/territories-regions-cities/territories/indian_ocean/iot_bulletins/2020/A041-2020-cki-public-holidays)
+        * [2022](https://web.archive.org/web/20250429071240/https://www.infrastructure.gov.au/sites/default/files/documents/a33-2021-2022-public-holidays-cocos-keeling-islands.pdf)
+        * [2022 Eid al-Fitr](https://web.archive.org/web/20220810061351/https://www.infrastructure.gov.au/sites/default/files/documents/Gazette-Change-to-CKI-Hari-Raya-Puasa-2022.pdf)
+        * [2023](https://web.archive.org/web/20240711221156/https://www.infrastructure.gov.au/sites/default/files/documents/a19-2022-community-bulletin-2023-kings-birthday-cocos-keeling-islands.pdf)
+        * [2023 Eid al-Adha](https://web.archive.org/web/20240804112114/https://www.infrastructure.gov.au/sites/default/files/documents/a06-2023_community_bulletin_-_change_of_public_holiday_date_for_hari_raya_haji_2023.pdf)
+        * [2024](https://web.archive.org/web/20250207203100/https://www.infrastructure.gov.au/sites/default/files/documents/a12-2023-2024-public-holidays-cocos-k-islands.pdf)
+        * [2025](https://web.archive.org/web/20250413083314/https://www.infrastructure.gov.au/sites/default/files/documents/a21-2024-administrator-community-bulletin-cki-public-holidays-2025.pdf)
+    """
+
+    country = "CC"
+    default_language = "en_CC"
+    # %s (observed).
+    observed_label = tr("%s (observed)")
+    # %s (estimated).
+    estimated_label = tr("%s (estimated)")
+    # %s (observed, estimated).
+    observed_estimated_label = tr("%s (observed, estimated)")
+    supported_languages = ("coa_CC", "en_CC", "en_US")
+    # Act of Self Determination 1984.
+    start_year = 1985
+
+    def __init__(self, islamic_show_estimated: bool = True, *args, **kwargs):
+        """
+        Args:
+            islamic_show_estimated:
+                Whether to add "estimated" label to Islamic holidays name
+                if holiday date is estimated.
+        """
+        ChristianHolidays.__init__(self)
+        InternationalHolidays.__init__(self)
+        IslamicHolidays.__init__(
+            self, cls=CocosIslandsIslamicHolidays, show_estimated=islamic_show_estimated
+        )
+        StaticHolidays.__init__(self, CocosIslandsStaticHolidays)
+        kwargs.setdefault("observed_rule", SAT_SUN_TO_NEXT_MON)
+        super().__init__(*args, **kwargs)
+
+    def _populate_public_holidays(self):
+        # New Year's Day.
+        self._add_observed(self._add_new_years_day(tr("New Year's Day")))
+
+        # Australia Day.
+        self._add_observed(self._add_holiday_jan_26(tr("Australia Day")))
+
+        act_of_self_determination_dates = {
+            2007: (APR, 5),
+        }
+        # Act of Self Determination Day.
+        name = tr("Act of Self Determination Day")
+        if self._year in act_of_self_determination_dates:
+            self._add_holiday(name, act_of_self_determination_dates[self._year])
+        else:
+            dt = self._add_holiday_apr_6(name)
+            if self._year != 2019:
+                self._add_observed(dt)
+
+        # Good Friday.
+        self._add_good_friday(tr("Good Friday"))
+
+        # Easter Monday.
+        self._add_easter_monday(tr("Easter Monday"))
+
+        # ANZAC Day.
+        self._add_observed(self._add_holiday_apr_25(tr("ANZAC Day")))
+
+        queens_kings_birthday_dates = {
+            2021: (JUN, 7),
+            2022: (JUN, 6),
+            2023: (JUN, 6),
+            2024: (JUN, 6),
+        }
+        name = (
+            # King's Birthday.
+            tr("King's Birthday")
+            if self._year >= 2023
+            # Queen's Birthday.
+            else tr("Queen's Birthday")
+        )
+        if self._year in queens_kings_birthday_dates:
+            self._add_holiday(name, queens_kings_birthday_dates[self._year])
+        else:
+            self._add_holiday_2nd_mon_of_jun(name)
+
+        # Placed before Christmas Day for proper observed calculation.
+        self._add_observed(
+            # Boxing Day.
+            self._add_christmas_day_two(tr("Boxing Day")),
+            rule=SAT_SUN_TO_NEXT_MON_TUE + MON_TO_NEXT_TUE,
+        )
+
+        # Christmas Day.
+        self._add_observed(self._add_christmas_day(tr("Christmas Day")))
+
+        # Islamic holidays.
+
+        if self._year <= 2019:
+            # Islamic New Year.
+            for dt in self._add_islamic_new_year_day(tr("Islamic New Year")):
+                self._add_observed(dt)
+
+        # Prophet's Birthday.
+        for dt in self._add_mawlid_day(tr("Prophet's Birthday")):
+            self._add_observed(dt)
+
+        # Eid al-Fitr.
+        for dt in self._add_eid_al_fitr_day(tr("Eid al-Fitr")):
+            self._add_observed(dt)
+
+        # Eid al-Adha.
+        for dt in self._add_eid_al_adha_day(tr("Eid al-Adha")):
+            if self._year != 2025:
+                self._add_observed(dt)
+
+
+class CocosIslandsIslamicHolidays(_CustomIslamicHolidays):
+    EID_AL_ADHA_DATES = {
+        2007: (DEC, 20),
+        2008: (DEC, 8),
+        2009: (NOV, 30),
+        2010: (NOV, 16),
+        2013: (OCT, 15),
+        2014: (OCT, 4),
+        2016: (SEP, 13),
+        2017: (SEP, 1),
+        2019: (AUG, 11),
+        2020: (JUL, 31),
+        2021: (JUL, 20),
+        2022: (JUL, 9),
+        2023: (JUN, 28),
+        2024: (JUN, 17),
+        2025: (JUN, 7),
+    }
+
+    EID_AL_FITR_DATES = {
+        2007: (OCT, 15),
+        2008: (OCT, 1),
+        2009: (SEP, 21),
+        2010: (SEP, 10),
+        2013: (AUG, 8),
+        2014: (JUL, 28),
+        2016: (JUL, 6),
+        2017: (JUN, 24),
+        2019: (JUN, 5),
+        2020: (MAY, 24),
+        2021: (MAY, 13),
+        2022: (MAY, 3),
+        2023: (APR, 22),
+        2024: (APR, 10),
+        2025: (MAR, 31),
+    }
+
+    HIJRI_NEW_YEAR_DATES = {
+        2007: (JAN, 22),
+        2008: (JAN, 10),
+        2009: (DEC, 18),
+        2010: (DEC, 7),
+        2013: (NOV, 4),
+        2014: (OCT, 25),
+        2016: (OCT, 3),
+        2017: (SEP, 22),
+        2019: (SEP, 1),
+    }
+
+    MAWLID_DATES = {
+        2007: (APR, 2),
+        2008: (MAR, 20),
+        2009: (MAR, 9),
+        2010: (FEB, 26),
+        2013: (JAN, 24),
+        2014: (JAN, 13),
+        2016: (DEC, 12),
+        2017: (DEC, 1),
+        2019: (NOV, 9),
+        2020: (OCT, 29),
+        2021: (OCT, 19),
+        2022: (OCT, 8),
+        2023: (SEP, 27),
+        2024: (SEP, 16),
+        2025: (SEP, 5),
+    }
+
+
+class CC(CocosIslands):
+    pass
+
+
+class CCK(CocosIslands):
+    pass
+
+
+class CocosIslandsStaticHolidays:
+    """Cocos (Keeling) Islands special holidays.
+
+    References:
+        * [National Day of Mourning 2022](https://web.archive.org/web/20240712213751/https://www.infrastructure.gov.au/sites/default/files/documents/04-2022-proclamation-cki-day-of-mourning.pdf)
+    """
+
+    special_public_holidays = {
+        # National Day of Mourning for Queen Elizabeth II.
+        2022: (SEP, 22, tr("National Day of Mourning for Queen Elizabeth II")),
+    }
+
+    special_public_holidays_observed = {
+        2019: (APR, 10, tr("Act of Self Determination Day")),
+        2025: (JUN, 6, tr("Eid al-Adha")),
+    }
diff --git a/holidays/locale/coa_CC/LC_MESSAGES/CC.po b/holidays/locale/coa_CC/LC_MESSAGES/CC.po
new file mode 100644
index 00000000..b00af9e3
--- /dev/null
+++ b/holidays/locale/coa_CC/LC_MESSAGES/CC.po
@@ -0,0 +1,103 @@
+#  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: Vacanza Team and individual contributors (see CONTRIBUTORS file)
+#           dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/vacanza/holidays
+#  License: MIT (see LICENSE file)
+#
+# Cocos (Keeling) Islands holidays coa_CC localization.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Holidays 0.73\n"
+"POT-Creation-Date: 2025-05-07 12:18+0530\n"
+"PO-Revision-Date: 2025-05-07 12:22+0530\n"
+"Last-Translator: Devaraj K <devarajkaliyaamoorthy@gmail.com>\n"
+"Language-Team: Holidays Localization Team\n"
+"Language: coa_CC\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Lingva 5.0.6\n"
+"X-Generator: Poedit 3.5\n"
+"X-Source-Language: en_CC\n"
+
+#. %s (observed).
+#, c-format
+msgid "%s (observed)"
+msgstr "%s (disambut)"
+
+#. King's Birthday.
+msgid "King's Birthday"
+msgstr "Hari Ulang Tahun Raja"
+
+#. Queen's Birthday.
+msgid "Queen's Birthday"
+msgstr "Hari Ulang Tahun Ratu"
+
+#. New Year's Day.
+msgid "New Year's Day"
+msgstr "Hari Tahun Baru"
+
+#. Australia Day.
+msgid "Australia Day"
+msgstr "Hari Australia"
+
+#. Islamic New Year.
+msgid "Islamic New Year"
+msgstr "Tahun Baru Hijriah"
+
+#. Eid al-Fitr.
+msgid "Eid al-Fitr"
+msgstr "Hari Raya Puasa"
+
+#. Good Friday.
+msgid "Good Friday"
+msgstr "Jumat Agung"
+
+#. Easter Monday.
+msgid "Easter Monday"
+msgstr "Isnin Paskah"
+
+#. Act of Self Determination Day.
+msgid "Act of Self Determination Day"
+msgstr "Hari Penentuan Diri"
+
+#. ANZAC Day.
+msgid "ANZAC Day"
+msgstr "Hari ANZAC"
+
+#. Eid al-Adha.
+msgid "Eid al-Adha"
+msgstr "Hari Raya Haji"
+
+#. Prophet's Birthday.
+msgid "Prophet's Birthday"
+msgstr "Hari Maulaud Nabi"
+
+#. Christmas Day.
+msgid "Christmas Day"
+msgstr "Hari Natal"
+
+#. Boxing Day.
+msgid "Boxing Day"
+msgstr "Hari Boxing"
+
+#. National Day of Mourning for Queen Elizabeth II.
+msgid "National Day of Mourning for Queen Elizabeth II"
+msgstr "Hari Berkabung Negara untuk Ratu Elizabeth II"
+
+#. %s (estimated).
+#, c-format
+msgid "%s (estimated)"
+msgstr "%s (dianggarkan)"
+
+#. %s (observed, estimated).
+#, c-format
+msgid "%s (observed, estimated)"
+msgstr "%s (disambut, dianggarkan)"
diff --git a/holidays/locale/en_CC/LC_MESSAGES/CC.po b/holidays/locale/en_CC/LC_MESSAGES/CC.po
new file mode 100644
index 00000000..a10b9686
--- /dev/null
+++ b/holidays/locale/en_CC/LC_MESSAGES/CC.po
@@ -0,0 +1,103 @@
+#  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: Vacanza Team and individual contributors (see CONTRIBUTORS file)
+#           dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/vacanza/holidays
+#  License: MIT (see LICENSE file)
+#
+# Cocos (Keeling) Islands holidays.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Holidays 0.73\n"
+"POT-Creation-Date: 2025-05-09 22:15+0530\n"
+"PO-Revision-Date: 2025-05-12 01:27+0530\n"
+"Last-Translator: Devaraj K <devarajkaliyaamoorthy@gmail.com>\n"
+"Language-Team: Holidays Localization Team\n"
+"Language: en_CC\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Lingva 5.0.6\n"
+"X-Generator: Poedit 3.5\n"
+"X-Source-Language: en_CC\n"
+
+#. %s (observed).
+#, c-format
+msgid "%s (observed)"
+msgstr ""
+
+#. King's Birthday.
+msgid "King's Birthday"
+msgstr ""
+
+#. Queen's Birthday.
+msgid "Queen's Birthday"
+msgstr ""
+
+#. New Year's Day.
+msgid "New Year's Day"
+msgstr ""
+
+#. Australia Day.
+msgid "Australia Day"
+msgstr ""
+
+#. Islamic New Year.
+msgid "Islamic New Year"
+msgstr ""
+
+#. Eid al-Fitr.
+msgid "Eid al-Fitr"
+msgstr ""
+
+#. Good Friday.
+msgid "Good Friday"
+msgstr ""
+
+#. Easter Monday.
+msgid "Easter Monday"
+msgstr ""
+
+#. Act of Self Determination Day.
+msgid "Act of Self Determination Day"
+msgstr ""
+
+#. ANZAC Day.
+msgid "ANZAC Day"
+msgstr ""
+
+#. Eid al-Adha.
+msgid "Eid al-Adha"
+msgstr ""
+
+#. Prophet's Birthday.
+msgid "Prophet's Birthday"
+msgstr ""
+
+#. Christmas Day.
+msgid "Christmas Day"
+msgstr ""
+
+#. Boxing Day.
+msgid "Boxing Day"
+msgstr ""
+
+#. National Day of Mourning for Queen Elizabeth II.
+msgid "National Day of Mourning for Queen Elizabeth II"
+msgstr ""
+
+#. %s (estimated).
+#, c-format
+msgid "%s (estimated)"
+msgstr ""
+
+#. %s (observed, estimated).
+#, c-format
+msgid "%s (observed, estimated)"
+msgstr ""
diff --git a/holidays/locale/en_US/LC_MESSAGES/CC.po b/holidays/locale/en_US/LC_MESSAGES/CC.po
new file mode 100644
index 00000000..9099a99b
--- /dev/null
+++ b/holidays/locale/en_US/LC_MESSAGES/CC.po
@@ -0,0 +1,103 @@
+#  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: Vacanza Team and individual contributors (see CONTRIBUTORS file)
+#           dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/vacanza/holidays
+#  License: MIT (see LICENSE file)
+#
+# Cocos (Keeling) Islands holidays en_US localization.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Holidays 0.73\n"
+"POT-Creation-Date: 2025-05-07 12:18+0530\n"
+"PO-Revision-Date: 2025-05-07 12:22+0530\n"
+"Last-Translator: Devaraj K <devarajkaliyaamoorthy@gmail.com>\n"
+"Language-Team: Holidays Localization Team\n"
+"Language: en_US\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Lingva 5.0.6\n"
+"X-Generator: Poedit 3.5\n"
+"X-Source-Language: en_CC\n"
+
+#. %s (observed).
+#, c-format
+msgid "%s (observed)"
+msgstr "%s (observed)"
+
+#. King's Birthday.
+msgid "King's Birthday"
+msgstr "King's Birthday"
+
+#. Queen's Birthday.
+msgid "Queen's Birthday"
+msgstr "Queen's Birthday"
+
+#. New Year's Day.
+msgid "New Year's Day"
+msgstr "New Year's Day"
+
+#. Australia Day.
+msgid "Australia Day"
+msgstr "Australia Day"
+
+#. Islamic New Year.
+msgid "Islamic New Year"
+msgstr "Islamic New Year"
+
+#. Eid al-Fitr.
+msgid "Eid al-Fitr"
+msgstr "Eid al-Fitr"
+
+#. Good Friday.
+msgid "Good Friday"
+msgstr "Good Friday"
+
+#. Easter Monday.
+msgid "Easter Monday"
+msgstr "Easter Monday"
+
+#. Act of Self Determination Day.
+msgid "Act of Self Determination Day"
+msgstr "Act of Self Determination Day"
+
+#. ANZAC Day.
+msgid "ANZAC Day"
+msgstr "ANZAC Day"
+
+#. Eid al-Adha.
+msgid "Eid al-Adha"
+msgstr "Eid al-Adha"
+
+#. Prophet's Birthday.
+msgid "Prophet's Birthday"
+msgstr "Prophet's Birthday"
+
+#. Christmas Day.
+msgid "Christmas Day"
+msgstr "Christmas Day"
+
+#. Boxing Day.
+msgid "Boxing Day"
+msgstr "Boxing Day"
+
+#. National Day of Mourning for Queen Elizabeth II.
+msgid "National Day of Mourning for Queen Elizabeth II"
+msgstr "National Day of Mourning for Queen Elizabeth II"
+
+#. %s (estimated).
+#, c-format
+msgid "%s (estimated)"
+msgstr "%s (estimated)"
+
+#. %s (observed, estimated).
+#, c-format
+msgid "%s (observed, estimated)"
+msgstr "%s (observed, estimated)"
diff --git a/holidays/registry.py b/holidays/registry.py
index b2f9511b..81b7d264 100644
--- a/holidays/registry.py
+++ b/holidays/registry.py
@@ -54,6 +54,7 @@ COUNTRIES: RegistryDict = {
     "chad": ("Chad", "TD", "TCD"),
     "chile": ("Chile", "CL", "CHL"),
     "china": ("China", "CN", "CHN"),
+    "cocos_islands": ("CocosIslands", "CC", "CCK"),
     "colombia": ("Colombia", "CO", "COL"),
     "congo": ("Congo", "CG", "COG"),
     "costa_rica": ("CostaRica", "CR", "CRI"),
diff --git a/requirements/dev.txt b/requirements/dev.txt
index 1c9384c4..b8a26162 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -7,7 +7,7 @@ hijridate==2.5.0
 lingva==5.0.6
 pre-commit==4.2.0
 pygithub==2.6.1
-ruff==0.11.8
-tox==4.25.0
+ruff==0.11.9
+tox==4.26.0
 urllib3>=2.2.2 # not directly required, pinned by Snyk to avoid a vulnerability
 zipp>=3.19.1 # not directly required, pinned by Snyk to avoid a vulnerability


Test patch:
diff --git a/tests/countries/test_cocos_islands.py b/tests/countries/test_cocos_islands.py
new file mode 100644
index 00000000..6553d373
--- /dev/null
+++ b/tests/countries/test_cocos_islands.py
@@ -0,0 +1,318 @@
+#  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: Vacanza Team and individual contributors (see CONTRIBUTORS file)
+#           dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
+#           ryanss <ryanssdev@icloud.com> (c) 2014-2017
+#  Website: https://github.com/vacanza/holidays
+#  License: MIT (see LICENSE file)
+
+from unittest import TestCase
+
+from holidays.countries.cocos_islands import CocosIslands, CC, CCK
+from tests.common import CommonCountryTests
+
+
+class TestCocosIslands(CommonCountryTests, TestCase):
+    @classmethod
+    def setUpClass(cls):
+        years = range(1985, 2050)
+        super().setUpClass(CocosIslands, years=years, years_non_observed=years)
+        cls.no_estimated_holidays = CocosIslands(years=years, islamic_show_estimated=False)
+
+    def test_country_aliases(self):
+        self.assertAliases(CocosIslands, CC, CCK)
+
+    def test_no_holidays(self):
+        self.assertNoHolidays(CocosIslands(years=1984))
+
+    def test_special_holidays(self):
+        self.assertHoliday(
+            "2022-09-22",
+        )
+
+    def test_new_years_day(self):
+        name = "New Year's Day"
+        self.assertHolidayName(name, (f"{year}-01-01" for year in range(1985, 2050)))
+        obs_dt = (
+            "2011-01-03",
+            "2012-01-02",
+            "2017-01-02",
+            "2022-01-03",
+            "2023-01-02",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_australia_day(self):
+        name = "Australia Day"
+        self.assertHolidayName(name, (f"{year}-01-26" for year in range(1985, 2050)))
+        obs_dt = (
+            "2013-01-28",
+            "2014-01-27",
+            "2019-01-28",
+            "2020-01-27",
+            "2025-01-27",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_act_of_self_determination_day(self):
+        name = "Act of Self Determination Day"
+        self.assertHolidayName(
+            name,
+            "2007-04-05",
+            (f"{year}-04-06" for year in (*range(1985, 2007), *range(2008, 2050))),
+        )
+        obs_dt = (
+            "2013-04-08",
+            "2014-04-07",
+            "2019-04-10",
+            "2024-04-08",
+            "2025-04-07",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_good_friday(self):
+        name = "Good Friday"
+        self.assertHolidayName(
+            name,
+            "2020-04-10",
+            "2021-04-02",
+            "2022-04-15",
+            "2023-04-07",
+            "2024-03-29",
+            "2025-04-18",
+        )
+        self.assertHolidayName(name, range(1985, 2050))
+
+    def test_easter_monday(self):
+        name = "Easter Monday"
+        self.assertHolidayName(
+            name,
+            "2020-04-13",
+            "2021-04-05",
+            "2022-04-18",
+            "2023-04-10",
+            "2024-04-01",
+            "2025-04-21",
+        )
+        self.assertHolidayName(name, range(1985, 2050))
+
+    def test_anzac_day(self):
+        name = "ANZAC Day"
+        self.assertHolidayName(name, (f"{year}-04-25" for year in range(1985, 2050)))
+        obs_dt = (
+            "2009-04-27",
+            "2010-04-26",
+            "2015-04-27",
+            "2020-04-27",
+            "2021-04-26",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_sovereigns_birthday(self):
+        name_1 = "Queen's Birthday"
+        name_2 = "King's Birthday"
+        self.assertHolidayName(
+            name_1,
+            "2018-06-11",
+            "2019-06-10",
+            "2020-06-08",
+            "2021-06-07",
+            "2022-06-06",
+        )
+        self.assertHolidayName(
+            name_2,
+            "2023-06-06",
+            "2024-06-06",
+            "2025-06-09",
+        )
+        self.assertHolidayName(name_1, range(1985, 2023))
+        self.assertHolidayName(name_2, range(2023, 2050))
+        self.assertNoHolidayName(name_1, range(2023, 2050))
+        self.assertNoHolidayName(name_2, range(1985, 2023))
+
+    def test_boxing_day(self):
+        name = "Boxing Day"
+        self.assertHolidayName(name, (f"{year}-12-26" for year in range(1985, 2050)))
+        obs_dt = (
+            "2015-12-28",
+            "2016-12-27",
+            "2020-12-28",
+            "2021-12-28",
+            "2022-12-27",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_christmas_day(self):
+        name = "Christmas Day"
+        self.assertHolidayName(name, (f"{year}-12-25" for year in range(1985, 2050)))
+        obs_dt = (
+            "2010-12-27",
+            "2011-12-26",
+            "2016-12-26",
+            "2021-12-27",
+            "2022-12-26",
+        )
+        self.assertHolidayName(f"{name} (observed)", obs_dt)
+
+    def test_islamic_new_year(self):
+        name = "Islamic New Year"
+        self.assertHolidayName(
+            name,
+            self.no_estimated_holidays,
+            "2015-10-14",
+            "2016-10-03",
+            "2017-09-22",
+            "2018-09-11",
+            "2019-09-01",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1985, 2020))
+        self.assertNoHolidayName(name, self.no_estimated_holidays, range(2020, 2050))
+        obs_dt = (
+            "1999-04-19",
+            "2004-02-23",
+            "2011-11-28",
+            "2014-10-27",
+            "2019-09-02",
+        )
+        self.assertHolidayName(f"{name} (observed)", self.no_estimated_holidays, obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_prophets_birthday(self):
+        name = "Prophet's Birthday"
+        self.assertHolidayName(
+            name,
+            "2020-10-29",
+            "2021-10-19",
+            "2022-10-08",
+            "2023-09-27",
+            "2024-09-16",
+            "2025-09-05",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1985, 2050))
+        obs_dt = (
+            "2004-05-03",
+            "2012-02-06",
+            "2015-01-05",
+            "2019-11-11",
+            "2022-10-10",
+        )
+        self.assertHolidayName(f"{name} (observed)", self.no_estimated_holidays, obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_eid_al_fitr(self):
+        name = "Eid al-Fitr"
+        self.assertHolidayName(
+            name,
+            "2020-05-24",
+            "2021-05-13",
+            "2022-05-03",
+            "2023-04-22",
+            "2024-04-10",
+            "2025-03-31",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1985, 2050))
+        obs_dt = (
+            "2004-11-15",
+            "2012-08-20",
+            "2017-06-26",
+            "2020-05-25",
+            "2023-04-24",
+        )
+        self.assertHolidayName(f"{name} (observed)", self.no_estimated_holidays, obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_eid_al_adha(self):
+        name = "Eid al-Adha"
+        self.assertHolidayName(
+            name,
+            "2020-07-31",
+            "2021-07-20",
+            "2022-07-09",
+            "2023-06-28",
+            "2024-06-17",
+            "2025-06-07",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1985, 2050))
+        obs_dt = (
+            "2011-11-07",
+            "2014-10-06",
+            "2019-08-12",
+            "2022-07-11",
+            "2025-06-06",
+        )
+        self.assertHolidayName(f"{name} (observed)", self.no_estimated_holidays, obs_dt)
+        self.assertNoNonObservedHoliday(obs_dt)
+
+    def test_l10n_default(self):
+        self.assertLocalizedHolidays(
+            ("2022-01-01", "New Year's Day"),
+            ("2022-01-03", "New Year's Day (observed)"),
+            ("2022-01-26", "Australia Day"),
+            ("2022-04-06", "Act of Self Determination Day"),
+            ("2022-04-15", "Good Friday"),
+            ("2022-04-18", "Easter Monday"),
+            ("2022-04-25", "ANZAC Day"),
+            ("2022-05-03", "Eid al-Fitr"),
+            ("2022-06-06", "Queen's Birthday"),
+            ("2022-07-09", "Eid al-Adha"),
+            ("2022-07-11", "Eid al-Adha (observed)"),
+            ("2022-09-22", "National Day of Mourning for Queen Elizabeth II"),
+            ("2022-10-08", "Prophet's Birthday"),
+            ("2022-10-10", "Prophet's Birthday (observed)"),
+            ("2022-12-25", "Christmas Day"),
+            ("2022-12-26", "Boxing Day; Christmas Day (observed)"),
+            ("2022-12-27", "Boxing Day (observed)"),
+        )
+
+    def test_l10n_coa_cc(self):
+        self.assertLocalizedHolidays(
+            "coa_CC",
+            ("2022-01-01", "Hari Tahun Baru"),
+            ("2022-01-03", "Hari Tahun Baru (disambut)"),
+            ("2022-01-26", "Hari Australia"),
+            ("2022-04-06", "Hari Penentuan Diri"),
+            ("2022-04-15", "Jumat Agung"),
+            ("2022-04-18", "Isnin Paskah"),
+            ("2022-04-25", "Hari ANZAC"),
+            ("2022-05-03", "Hari Raya Puasa"),
+            ("2022-06-06", "Hari Ulang Tahun Ratu"),
+            ("2022-07-09", "Hari Raya Haji"),
+            ("2022-07-11", "Hari Raya Haji (disambut)"),
+            ("2022-09-22", "Hari Berkabung Negara untuk Ratu Elizabeth II"),
+            ("2022-10-08", "Hari Maulaud Nabi"),
+            ("2022-10-10", "Hari Maulaud Nabi (disambut)"),
+            ("2022-12-25", "Hari Natal"),
+            ("2022-12-26", "Hari Boxing; Hari Natal (disambut)"),
+            ("2022-12-27", "Hari Boxing (disambut)"),
+        )
+
+    def test_l10n_en_us(self):
+        self.assertLocalizedHolidays(
+            "en_US",
+            ("2022-01-01", "New Year's Day"),
+            ("2022-01-03", "New Year's Day (observed)"),
+            ("2022-01-26", "Australia Day"),
+            ("2022-04-06", "Act of Self Determination Day"),
+            ("2022-04-15", "Good Friday"),
+            ("2022-04-18", "Easter Monday"),
+            ("2022-04-25", "ANZAC Day"),
+            ("2022-05-03", "Eid al-Fitr"),
+            ("2022-06-06", "Queen's Birthday"),
+            ("2022-07-09", "Eid al-Adha"),
+            ("2022-07-11", "Eid al-Adha (observed)"),
+            ("2022-09-22", "National Day of Mourning for Queen Elizabeth II"),
+            ("2022-10-08", "Prophet's Birthday"),
+            ("2022-10-10", "Prophet's Birthday (observed)"),
+            ("2022-12-25", "Christmas Day"),
+            ("2022-12-26", "Boxing Day; Christmas Day (observed)"),
+            ("2022-12-27", "Boxing Day (observed)"),
+        )