Repository: vacanza/holidays
Pull request #2730 (2025-07-16 16:30:04)

Update Peru holidays: add 2023+ 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.
-->

I added two National Holidays for Peru which were introduced in 2023 and 2025 that are listed in the source, but were not yet implemented.
https://es.wikipedia.org/wiki/Anexo:D%C3%ADas_festivos_en_Per%C3%BA

* Battle of Arica and National Flag Day (June 7th)
* Peruvian Air Force Day (July 23th)

My repo: https://github.com/kplrm/python-holidays

## 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.
-->

- [ ] New country/market holidays support (thank you!)
- [x] 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


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)


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=2730) **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=2730&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=2730&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=2730&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=2730&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=2730&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=vacanza_python-holidays&pullRequest=2730)



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/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/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/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 "День незалежності"


Test patch:
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"),