Repository: vacanza/holidays
Pull request #2725 (2025-07-15 07:26:16)

Add Mali 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 Mali holidays.
Resolves #1224.

## 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


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/vacanza/holidays/pull/2725?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vacanza) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 100.00%. Comparing base [(`76d2171`)](https://app.codecov.io/gh/vacanza/holidays/commit/76d2171470c4bd61a0ce6dad07f1f05388ab3a79?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vacanza) to head [(`cdc01de`)](https://app.codecov.io/gh/vacanza/holidays/commit/cdc01deddd655ac21e2ace8e01a6ce3a2ed1e76d?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vacanza).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff            @@
##               dev     #2725   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          264       265    +1     
  Lines        15783     15824   +41     
  Branches      2133      2137    +4     
=========================================
+ Hits         15783     15824   +41     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/vacanza/holidays/pull/2725?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vacanza).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vacanza).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=vacanza_python-holidays&pullRequest=2725&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=vacanza_python-holidays&pullRequest=2725&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2725)



Patch:
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 60a2c9e7..e7037eb1 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -35,6 +35,7 @@ Daniel Musketa
 Daniël Niemeijer
 David Hotham
 Devaraj K
+Diego Rosaperez
 Diogo Rosa
 Dorian Monnier
 Douglas Franklin
diff --git a/README.md b/README.md
index f46e34aa..382102f9 100644
--- a/README.md
+++ b/README.md
@@ -105,7 +105,7 @@ and detailed information.
 
 ## Available Countries
 
-We currently support 222 country codes. The standard way to refer to a country is by using its [ISO
+We currently support 223 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
@@ -1001,6 +1001,13 @@ any) in brackets, available languages and additional holiday categories. All cou
 <td></td>
 </tr>
 <tr>
+<td>Mali</td>
+<td>ML</td>
+<td></td>
+<td>en_US, <strong>fr</strong></td>
+<td></td>
+</tr>
+<tr>
 <td>Malta</td>
 <td>MT</td>
 <td></td>
diff --git a/holidays/countries/__init__.py b/holidays/countries/__init__.py
index bdd7485d..5ff66a62 100644
--- a/holidays/countries/__init__.py
+++ b/holidays/countries/__init__.py
@@ -139,6 +139,7 @@ from holidays.countries.madagascar import Madagascar, MG, MDG
 from holidays.countries.malawi import Malawi, MW, MWI
 from holidays.countries.malaysia import Malaysia, MY, MYS
 from holidays.countries.maldives import Maldives, MV, MDV
+from holidays.countries.mali import Mali, ML, MLI
 from holidays.countries.malta import Malta, MT, MLT
 from holidays.countries.marshall_islands import MarshallIslands, MH, MHL, HolidaysMH
 from holidays.countries.martinique import Martinique, MQ, MTQ, HolidaysMQ
diff --git a/holidays/countries/mali.py b/holidays/countries/mali.py
new file mode 100644
index 00000000..f281a9a4
--- /dev/null
+++ b/holidays/countries/mali.py
@@ -0,0 +1,151 @@
+#  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, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
+from holidays.groups import ChristianHolidays, InternationalHolidays, IslamicHolidays
+from holidays.holiday_base import HolidayBase
+
+
+class Mali(HolidayBase, ChristianHolidays, InternationalHolidays, IslamicHolidays):
+    """Mali holidays.
+
+    References:
+        * [Ordinance no. 54 of 1960](https://web.archive.org/web/20250619193041/https://sgg-mali.ml/JO/1960/mali-jo-1960-71.pdf)
+        * [Law No. 28 of 1964](https://web.archive.org/web/20250619190638/https://sgg-mali.ml/JO/1964/mali-jo-1964-183.pdf)
+        * [Ordinance no. 16 of 1992](https://web.archive.org/web/20250611221453/https://sgg-mali.ml/JO/1992/mali-jo-1992-08.pdf)
+        * [Law No. 40 of 2005](https://web.archive.org/web/20250603120027/https://sgg-mali.ml/JO/2005/mali-jo-2005-25.pdf)
+    """
+
+    country = "ML"
+    default_language = "fr"
+    # %s (estimated).
+    estimated_label = tr("%s (estimé)")
+    start_year = 1961
+    supported_languages = ("en_US", "fr")
+
+    def __init__(self, *args, islamic_show_estimated: bool = True, **kwargs):
+        """
+        Args:
+            islamic_show_estimated:
+                Whether to add "estimated" label to Islamic holidays name
+                if holiday date is estimated.
+        """
+        ChristianHolidays.__init__(self)
+        IslamicHolidays.__init__(
+            self, cls=MaliIslamicHolidays, show_estimated=islamic_show_estimated
+        )
+        InternationalHolidays.__init__(self)
+        super().__init__(*args, **kwargs)
+
+    def _populate_public_holidays(self):
+        # New Year's Day.
+        self._add_new_years_day(tr("Jour de l'An"))
+
+        if self._year >= 1965:
+            # Armed Forces Day.
+            self._add_holiday_jan_20(tr("Journée de l'Armée"))
+
+        if self._year >= 1992:
+            # Martyrs' Day.
+            self._add_holiday_mar_26(tr("Journée du 26 mars"))
+
+        if self._year >= 2006:
+            # Easter Monday.
+            self._add_easter_monday(tr("Lundi de Pâques"))
+
+        # Labor Day.
+        self._add_labor_day(tr("Fête du Travail"))
+
+        if self._year >= 1965:
+            # Africa Day.
+            self._add_africa_day(tr("Journée de l'Afrique"))
+
+        # National Day of the Republic of Mali.
+        self._add_holiday_sep_22(tr("Fête Nationale de la République du Mali"))
+
+        # Christmas Day.
+        self._add_christmas_day(tr("Fête de Noël"))
+
+        self._add_mawlid_day(
+            # Prophet's Birthday.
+            tr("Journée du Maouloud (Naissance du Prophète)")
+            if self._year >= 2006
+            # Prophet's Birthday.
+            else tr("Journée du Mawloud")
+        )
+
+        if self._year >= 2006:
+            # Prophet's Baptism.
+            self._add_prophet_baptism_day(tr("Journée du Maouloud (Baptême du Prophète)"))
+
+        # Eid al-Fitr.
+        self._add_eid_al_fitr_day(tr("Journée de la Fête du Ramadan"))
+
+        # Eid al-Adha.
+        self._add_eid_al_adha_day(tr("Journée de la Tabaski"))
+
+
+class ML(Mali):
+    pass
+
+
+class MLI(Mali):
+    pass
+
+
+class MaliIslamicHolidays(_CustomIslamicHolidays):
+    # https://web.archive.org/web/20250619042440/https://www.timeanddate.com/holidays/mali/eid-al-adha
+    EID_AL_ADHA_DATES = {
+        2015: (SEP, 24),
+        2016: (SEP, 13),
+        2017: (SEP, 2),
+        2018: (AUG, 22),
+        2019: (AUG, 11),
+        2020: (JUL, 31),
+        2021: (JUL, 21),
+        2022: (JUL, 9),
+        2023: (JUN, 28),
+        2024: (JUN, 17),
+        2025: (JUN, 7),
+    }
+
+    # https://web.archive.org/web/20250318001443/https://www.timeanddate.com/holidays/mali/eid-al-fitr
+    EID_AL_FITR_DATES = {
+        2015: (JUL, 18),
+        2016: (JUL, 7),
+        2017: (JUN, 26),
+        2018: (JUN, 15),
+        2019: (JUN, 3),
+        2020: (MAY, 23),
+        2021: (MAY, 12),
+        2022: (MAY, 1),
+        2023: (APR, 21),
+        2024: (APR, 9),
+        2025: (MAR, 30),
+    }
+
+    # https://web.archive.org/web/20240424165412/https://www.timeanddate.com/holidays/mali/prophet-birthday
+    MAWLID_DATES = {
+        2015: ((JAN, 3), (DEC, 24)),
+        2016: (DEC, 12),
+        2017: (DEC, 1),
+        2018: (NOV, 21),
+        2019: (NOV, 10),
+        2020: (OCT, 29),
+        2021: (OCT, 19),
+        2022: (OCT, 9),
+        2023: (SEP, 28),
+        2024: (SEP, 16),
+    }
diff --git a/holidays/countries/peru.py b/holidays/countries/peru.py
index 5f22d20e..9cf0d832 100644
--- a/holidays/countries/peru.py
+++ b/holidays/countries/peru.py
@@ -22,6 +22,8 @@ class Peru(HolidayBase, ChristianHolidays, InternationalHolidays):
     References:
         * <https://web.archive.org/web/20250414165243/https://www.gob.pe/feriados/>
         * <https://es.wikipedia.org/wiki/Anexo:Días_feriados_en_el_Perú>
+        * [Ley N° 31788](https://web.archive.org/web/20250716164223/https://img.lpderecho.pe/wp-content/uploads/2023/06/Ley-31788-LPDerecho.pdf)
+        * [Ley N° 31822](https://web.archive.org/web/20250716164455/https://img.lpderecho.pe/wp-content/uploads/2023/07/Ley-31822-LPDerecho.pdf)
     """
 
     country = "PE"
@@ -49,9 +51,19 @@ class Peru(HolidayBase, ChristianHolidays, InternationalHolidays):
         # Labor Day.
         self._add_labor_day(tr("Día del Trabajo"))
 
+        # Added via Ley N° 31788 on June 15th, 2023.
+        if self._year >= 2024:
+            # Battle of Arica and Flag Day.
+            self._add_holiday_jun_7(tr("Batalla de Arica y Día de la Bandera"))
+
         # Saint Peter and Saint Paul's Day.
         self._add_saints_peter_and_paul_day(tr("San Pedro y San Pablo"))
 
+        # Added via Ley N° 31822 on July 8th, 2023.
+        if self._year >= 2023:
+            # Peruvian Air Force Day.
+            self._add_holiday_jul_23(tr("Día de la Fuerza Aérea del Perú"))
+
         # Independence Day.
         self._add_holiday_jul_28(tr("Día de la Independencia"))
 
diff --git a/holidays/groups/islamic.py b/holidays/groups/islamic.py
index 6f788a9e..db965f43 100644
--- a/holidays/groups/islamic.py
+++ b/holidays/groups/islamic.py
@@ -373,6 +373,23 @@ class IslamicHolidays(EasternCalendarHolidays):
             name, self._islamic_calendar.nuzul_al_quran_dates(self._year)
         )
 
+    def _add_prophet_baptism_day(self, name) -> set[date]:
+        """
+        Add Prophet's Baptism.
+
+        Celebrated one week after the Prophet Mohammed's Birthday, this
+        marks the traditional Islamic birth rites that take place seven
+        days after birth. While it is not recognized in mainstream Islam,
+        Mali celebrates it as a cultural-religious public holiday that
+        reflects the local interpretation and honor of the Prophet Muhammad.
+        The term "baptism" is symbolic and not literal - there's no Islamic
+        ritual akin to Christian baptism.
+        https://www.officeholidays.com/holidays/mali/prophets-baptism
+        """
+        return self._add_islamic_calendar_holiday(
+            name, self._islamic_calendar.mawlid_dates(self._year), days_delta=+7
+        )
+
     def _add_prophet_death_day(self, name) -> set[date]:
         """
         Add death of Prophet Muhammad and Hasan ibn Ali day (28th day of 2nd month).
diff --git a/holidays/locale/en_US/LC_MESSAGES/ML.po b/holidays/locale/en_US/LC_MESSAGES/ML.po
new file mode 100644
index 00000000..9f593b63
--- /dev/null
+++ b/holidays/locale/en_US/LC_MESSAGES/ML.po
@@ -0,0 +1,84 @@
+#  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)
+#
+# Mali holidays en_US localization.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Holidays 0.77\n"
+"POT-Creation-Date: 2025-07-13 16:01+0530\n"
+"PO-Revision-Date: 2025-07-13 16:01+0530\n"
+"Last-Translator: Kriti Birda <workwithkritibirda@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-Source-Language: fr\n"
+
+#. %s (estimated).
+#, c-format
+msgid "%s (estimé)"
+msgstr "%s (estimated)"
+
+#. New Year's Day.
+msgid "Jour de l'An"
+msgstr "New Year's Day"
+
+#. Armed Forces Day.
+msgid "Journée de l'Armée"
+msgstr "Armed Forces Day"
+
+#. Martyrs' Day.
+msgid "Journée du 26 mars"
+msgstr "Martyrs' Day"
+
+#. Easter Monday.
+msgid "Lundi de Pâques"
+msgstr "Easter Monday"
+
+#. Labor Day.
+msgid "Fête du Travail"
+msgstr "Labor Day"
+
+#. Africa Day.
+msgid "Journée de l'Afrique"
+msgstr "Africa Day"
+
+#. National Day of the Republic of Mali.
+msgid "Fête Nationale de la République du Mali"
+msgstr "National Day of the Republic of Mali"
+
+#. Christmas Day.
+msgid "Fête de Noël"
+msgstr "Christmas Day"
+
+#. Prophet's Birthday.
+msgid "Journée du Maouloud (Naissance du Prophète)"
+msgstr "Prophet's Birthday"
+
+#. Prophet's Birthday.
+msgid "Journée du Mawloud"
+msgstr "Prophet's Birthday"
+
+#. Prophet's Baptism.
+msgid "Journée du Maouloud (Baptême du Prophète)"
+msgstr "Prophet's Baptism"
+
+#. Eid al-Fitr.
+msgid "Journée de la Fête du Ramadan"
+msgstr "Eid al-Fitr"
+
+#. Eid al-Adha.
+msgid "Journée de la Tabaski"
+msgstr "Eid al-Adha"
diff --git a/holidays/locale/en_US/LC_MESSAGES/PE.po b/holidays/locale/en_US/LC_MESSAGES/PE.po
index b7628237..3450b75e 100644
--- a/holidays/locale/en_US/LC_MESSAGES/PE.po
+++ b/holidays/locale/en_US/LC_MESSAGES/PE.po
@@ -47,10 +47,18 @@ msgstr "Easter Sunday"
 msgid "Día del Trabajo"
 msgstr "Labor Day"
 
+#. Battle of Arica and Flag Day.
+msgid "Batalla de Arica y Día de la Bandera"
+msgstr "Battle of Arica and Flag Day"
+
 #. Saint Peter and Saint Paul's Day.
 msgid "San Pedro y San Pablo"
 msgstr "Saint Peter and Saint Paul's Day"
 
+#. Peruvian Air Force Day.
+msgid "Día de la Fuerza Aérea del Perú"
+msgstr "Peruvian Air Force Day"
+
 #. Independence Day.
 msgid "Día de la Independencia"
 msgstr "Independence Day"
diff --git a/holidays/locale/es/LC_MESSAGES/PE.po b/holidays/locale/es/LC_MESSAGES/PE.po
index b398891b..9820dbd3 100644
--- a/holidays/locale/es/LC_MESSAGES/PE.po
+++ b/holidays/locale/es/LC_MESSAGES/PE.po
@@ -47,10 +47,18 @@ msgstr ""
 msgid "Día del Trabajo"
 msgstr ""
 
+#. Battle of Arica and Flag Day.
+msgid "Batalla de Arica y Día de la Bandera"
+msgstr ""
+
 #. Saint Peter and Saint Paul's Day.
 msgid "San Pedro y San Pablo"
 msgstr ""
 
+#. Peruvian Air Force Day.
+msgid "Día de la Fuerza Aérea del Perú"
+msgstr ""
+
 #. Independence Day.
 msgid "Día de la Independencia"
 msgstr ""
diff --git a/holidays/locale/fr/LC_MESSAGES/ML.po b/holidays/locale/fr/LC_MESSAGES/ML.po
new file mode 100644
index 00000000..5247f724
--- /dev/null
+++ b/holidays/locale/fr/LC_MESSAGES/ML.po
@@ -0,0 +1,84 @@
+#  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)
+#
+# Mali holidays.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Holidays 0.77\n"
+"POT-Creation-Date: 2025-07-13 16:01+0530\n"
+"PO-Revision-Date: 2025-07-13 16:01+0530\n"
+"Last-Translator: Kriti Birda <workwithkritibirda@gmail.com>\n"
+"Language-Team: Holidays Localization Team\n"
+"Language: fr\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-Source-Language: fr\n"
+
+#. %s (estimated).
+#, c-format
+msgid "%s (estimé)"
+msgstr ""
+
+#. New Year's Day.
+msgid "Jour de l'An"
+msgstr ""
+
+#. Armed Forces Day.
+msgid "Journée de l'Armée"
+msgstr ""
+
+#. Martyrs' Day.
+msgid "Journée du 26 mars"
+msgstr ""
+
+#. Easter Monday.
+msgid "Lundi de Pâques"
+msgstr ""
+
+#. Labor Day.
+msgid "Fête du Travail"
+msgstr ""
+
+#. Africa Day.
+msgid "Journée de l'Afrique"
+msgstr ""
+
+#. National Day of the Republic of Mali.
+msgid "Fête Nationale de la République du Mali"
+msgstr ""
+
+#. Christmas Day.
+msgid "Fête de Noël"
+msgstr ""
+
+#. Prophet's Birthday.
+msgid "Journée du Maouloud (Naissance du Prophète)"
+msgstr ""
+
+#. Prophet's Birthday.
+msgid "Journée du Mawloud"
+msgstr ""
+
+#. Prophet's Baptism.
+msgid "Journée du Maouloud (Baptême du Prophète)"
+msgstr ""
+
+#. Eid al-Fitr.
+msgid "Journée de la Fête du Ramadan"
+msgstr ""
+
+#. Eid al-Adha.
+msgid "Journée de la Tabaski"
+msgstr ""
diff --git a/holidays/locale/uk/LC_MESSAGES/PE.po b/holidays/locale/uk/LC_MESSAGES/PE.po
index acda155e..11d5d4c9 100644
--- a/holidays/locale/uk/LC_MESSAGES/PE.po
+++ b/holidays/locale/uk/LC_MESSAGES/PE.po
@@ -47,10 +47,18 @@ msgstr "Великдень"
 msgid "Día del Trabajo"
 msgstr "День праці"
 
+#. Battle of Arica and Flag Day.
+msgid "Batalla de Arica y Día de la Bandera"
+msgstr "День битви за Аріку та День прапора"
+
 #. Saint Peter and Saint Paul's Day.
 msgid "San Pedro y San Pablo"
 msgstr "День Святих Петра і Павла"
 
+#. Peruvian Air Force Day.
+msgid "Día de la Fuerza Aérea del Perú"
+msgstr "День Повітряних сил Перу"
+
 #. Independence Day.
 msgid "Día de la Independencia"
 msgstr "День незалежності"
diff --git a/holidays/registry.py b/holidays/registry.py
index a5cc0128..53c361b3 100644
--- a/holidays/registry.py
+++ b/holidays/registry.py
@@ -142,6 +142,7 @@ COUNTRIES: RegistryDict = {
     "malawi": ("Malawi", "MW", "MWI"),
     "malaysia": ("Malaysia", "MY", "MYS"),
     "maldives": ("Maldives", "MV", "MDV"),
+    "mali": ("Mali", "ML", "MLI"),
     "malta": ("Malta", "MT", "MLT"),
     "marshall_islands": ("MarshallIslands", "MH", "MHL", "HolidaysMH"),
     "martinique": ("Martinique", "MQ", "MTQ", "HolidaysMQ"),


Test patch:
diff --git a/tests/countries/test_mali.py b/tests/countries/test_mali.py
new file mode 100644
index 00000000..e6e77655
--- /dev/null
+++ b/tests/countries/test_mali.py
@@ -0,0 +1,186 @@
+#  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 import Mali, ML, MLI
+from tests.common import CommonCountryTests
+
+
+class TestMali(CommonCountryTests, TestCase):
+    @classmethod
+    def setUpClass(cls):
+        years = range(1961, 2050)
+        super().setUpClass(Mali, years=years)
+        cls.no_estimated_holidays = Mali(years=years, islamic_show_estimated=False)
+
+    def test_country_aliases(self):
+        self.assertAliases(Mali, ML, MLI)
+
+    def test_no_holidays(self):
+        self.assertNoHolidays(Mali(years=1960))
+
+    def test_new_years_day(self):
+        self.assertHolidayName("Jour de l'An", (f"{year}-01-01" for year in range(1961, 2050)))
+
+    def test_armed_forces_day(self):
+        name = "Journée de l'Armée"
+        self.assertHolidayName(name, (f"{year}-01-20" for year in range(1965, 2050)))
+        self.assertNoHolidayName(name, range(1961, 1965))
+
+    def test_march_26_day(self):
+        name = "Journée du 26 mars"
+        self.assertHolidayName(name, (f"{year}-03-26" for year in range(1992, 2050)))
+        self.assertNoHolidayName(name, range(1961, 1992))
+
+    def test_easter_monday(self):
+        name = "Lundi de Pâques"
+        self.assertHolidayName(
+            name,
+            "2021-04-05",
+            "2022-04-18",
+            "2023-04-10",
+            "2024-04-01",
+            "2025-04-21",
+        )
+        self.assertHolidayName(name, range(2006, 2050))
+        self.assertNoHolidayName(name, range(1961, 2006))
+
+    def test_labor_day(self):
+        self.assertHolidayName("Fête du Travail", (f"{year}-05-01" for year in range(1961, 2050)))
+
+    def test_africa_day(self):
+        name = "Journée de l'Afrique"
+        self.assertHolidayName(name, (f"{year}-05-25" for year in range(1965, 2050)))
+        self.assertNoHolidayName(name, range(1961, 1965))
+
+    def test_independence_day(self):
+        self.assertHolidayName(
+            "Fête Nationale de la République du Mali",
+            (f"{year}-09-22" for year in range(1961, 2050)),
+        )
+
+    def test_christmas_day(self):
+        self.assertHolidayName("Fête de Noël", (f"{year}-12-25" for year in range(1961, 2050)))
+
+    def test_prophets_birthday(self):
+        name_1 = "Journée du Mawloud"
+        self.assertHolidayName(
+            name_1,
+            self.no_estimated_holidays,
+            "2001-06-04",
+            "2002-05-24",
+            "2003-05-13",
+            "2004-05-01",
+            "2005-04-21",
+        )
+        self.assertHolidayName(name_1, self.no_estimated_holidays, range(1961, 2006))
+        self.assertNoHolidayName(name_1, self.no_estimated_holidays, range(2006, 2050))
+
+        name_2 = "Journée du Maouloud (Naissance du Prophète)"
+        self.assertHolidayName(
+            name_2,
+            "2020-10-29",
+            "2021-10-19",
+            "2022-10-09",
+            "2023-09-28",
+            "2024-09-16",
+        )
+        self.assertHolidayName(name_2, self.no_estimated_holidays, range(2006, 2050))
+        self.assertNoHolidayName(name_2, self.no_estimated_holidays, range(1961, 2006))
+
+    def test_prophet_baptism_day(self):
+        name = "Journée du Maouloud (Baptême du Prophète)"
+        self.assertHolidayName(
+            name,
+            "2020-11-05",
+            "2021-10-26",
+            "2022-10-16",
+            "2023-10-05",
+            "2024-09-23",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(2006, 2050))
+        self.assertNoHolidayName(name, self.no_estimated_holidays, range(1961, 2006))
+
+    def test_eid_al_fitr(self):
+        name = "Journée de la Fête du Ramadan"
+        self.assertHolidayName(
+            name,
+            "2021-05-12",
+            "2022-05-01",
+            "2023-04-21",
+            "2024-04-09",
+            "2025-03-30",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1961, 2050))
+
+    def test_eid_al_adha(self):
+        name = "Journée de la Tabaski"
+        self.assertHolidayName(
+            name,
+            "2021-07-21",
+            "2022-07-09",
+            "2023-06-28",
+            "2024-06-17",
+            "2025-06-07",
+        )
+        self.assertHolidayName(name, self.no_estimated_holidays, range(1961, 2050))
+
+    def test_2024(self):
+        self.assertHolidays(
+            Mali(years=2024),
+            ("2024-01-01", "Jour de l'An"),
+            ("2024-01-20", "Journée de l'Armée"),
+            ("2024-03-26", "Journée du 26 mars"),
+            ("2024-04-01", "Lundi de Pâques"),
+            ("2024-04-09", "Journée de la Fête du Ramadan"),
+            ("2024-05-01", "Fête du Travail"),
+            ("2024-05-25", "Journée de l'Afrique"),
+            ("2024-06-17", "Journée de la Tabaski"),
+            ("2024-09-16", "Journée du Maouloud (Naissance du Prophète)"),
+            ("2024-09-23", "Journée du Maouloud (Baptême du Prophète)"),
+            ("2024-09-22", "Fête Nationale de la République du Mali"),
+            ("2024-12-25", "Fête de Noël"),
+        )
+
+    def test_l10n_default(self):
+        self.assertLocalizedHolidays(
+            ("2025-01-01", "Jour de l'An"),
+            ("2025-01-20", "Journée de l'Armée"),
+            ("2025-03-26", "Journée du 26 mars"),
+            ("2025-03-30", "Journée de la Fête du Ramadan"),
+            ("2025-04-21", "Lundi de Pâques"),
+            ("2025-05-01", "Fête du Travail"),
+            ("2025-05-25", "Journée de l'Afrique"),
+            ("2025-06-07", "Journée de la Tabaski"),
+            ("2025-09-04", "Journée du Maouloud (Naissance du Prophète) (estimé)"),
+            ("2025-09-11", "Journée du Maouloud (Baptême du Prophète) (estimé)"),
+            ("2025-09-22", "Fête Nationale de la République du Mali"),
+            ("2025-12-25", "Fête de Noël"),
+        )
+
+    def test_l10n_en_us(self):
+        self.assertLocalizedHolidays(
+            "en_US",
+            ("2025-01-01", "New Year's Day"),
+            ("2025-01-20", "Armed Forces Day"),
+            ("2025-03-26", "Martyrs' Day"),
+            ("2025-03-30", "Eid al-Fitr"),
+            ("2025-04-21", "Easter Monday"),
+            ("2025-05-01", "Labor Day"),
+            ("2025-05-25", "Africa Day"),
+            ("2025-06-07", "Eid al-Adha"),
+            ("2025-09-04", "Prophet's Birthday (estimated)"),
+            ("2025-09-11", "Prophet's Baptism (estimated)"),
+            ("2025-09-22", "National Day of the Republic of Mali"),
+            ("2025-12-25", "Christmas Day"),
+        )
diff --git a/tests/countries/test_peru.py b/tests/countries/test_peru.py
index 8e00d155..03f74d84 100644
--- a/tests/countries/test_peru.py
+++ b/tests/countries/test_peru.py
@@ -19,13 +19,14 @@ from tests.common import CommonCountryTests
 class TestPeru(CommonCountryTests, TestCase):
     @classmethod
     def setUpClass(cls):
-        super().setUpClass(Peru)
+        super().setUpClass(Peru, years=range(1950, 2050))
 
     def test_country_aliases(self):
         self.assertAliases(Peru, PE, PER)
 
     def test_2019(self):
         self.assertHolidayDates(
+            Peru(years=2019),
             "2019-01-01",
             "2019-04-18",
             "2019-04-19",
@@ -43,6 +44,7 @@ class TestPeru(CommonCountryTests, TestCase):
 
     def test_2022(self):
         self.assertHolidayDates(
+            Peru(years=2022),
             "2022-01-01",
             "2022-04-14",
             "2022-04-15",
@@ -60,6 +62,16 @@ class TestPeru(CommonCountryTests, TestCase):
             "2022-12-25",
         )
 
+    def test_battle_of_arica_and_flag_day(self):
+        name = "Batalla de Arica y Día de la Bandera"
+        self.assertHolidayName(name, (f"{year}-06-07" for year in range(2024, 2050)))
+        self.assertNoHolidayName(name, range(1950, 2024))
+
+    def test_peruvian_air_force_day(self):
+        name = "Día de la Fuerza Aérea del Perú"
+        self.assertHolidayName(name, (f"{year}-07-23" for year in range(2023, 2050)))
+        self.assertNoHolidayName(name, range(1950, 2023))
+
     def test_l10n_default(self):
         self.assertLocalizedHolidays(
             ("2022-01-01", "Año Nuevo"),