diff --git a/README.md b/README.md
index d4c72d34c9..c9c2347327 100644
--- a/README.md
+++ b/README.md
@@ -726,7 +726,7 @@ any) in brackets, available languages and additional holiday categories. All cou
DE |
States: BB (Brandenburg), BE (Berlin), BW (Baden-Württemberg), BY (Bayern), HB (Bremen), HE (Hessen), HH (Hamburg), MV (Mecklenburg-Vorpommern), NI (Niedersachsen), NW (Nordrhein-Westfalen), RP (Rheinland-Pfalz), SH (Schleswig-Holstein), SL (Saarland), SN (Sachsen), ST (Sachsen-Anhalt), TH (Thüringen); cities: Augsburg |
de, en_US, th, uk |
-CATHOLIC |
+CATHOLIC, SCHOOL |
| Ghana |
diff --git a/holidays/countries/germany.py b/holidays/countries/germany.py
index 5f9be24820..556d0b9492 100644
--- a/holidays/countries/germany.py
+++ b/holidays/countries/germany.py
@@ -10,10 +10,11 @@
# Website: https://github.com/vacanza/holidays
# License: MIT (see LICENSE file)
+from datetime import date, timedelta
from gettext import gettext as tr
from holidays.calendars.gregorian import MAY, JUN, OCT
-from holidays.constants import CATHOLIC, PUBLIC
+from holidays.constants import CATHOLIC, PUBLIC, SCHOOL
from holidays.groups import ChristianHolidays, InternationalHolidays, StaticHolidays
from holidays.holiday_base import HolidayBase
@@ -43,7 +44,23 @@ class Germany(HolidayBase, ChristianHolidays, InternationalHolidays, StaticHolid
* [Sachsen](https://web.archive.org/web/20250808020452/https://www.revosax.sachsen.de/vorschrift/3997-SaechsSFG)
* [Sachsen-Anhalt](https://web.archive.org/web/20250615214949/http://www.landesrecht.sachsen-anhalt.de/bsst/document/jlr-FeiertGSTpP2)
* [Thüringen](https://web.archive.org/web/20250712163548/http://landesrecht.thueringen.de/bsth/document/jlr-FeiertGTHV5P2)
-
+ School Holiday References:
+ * [Brandenburg](https://bravors.brandenburg.de/sixcms/media.php/66/VV-Schulbetrieb-Anlage-1-2025.pdf)
+ * [Berlin](https://www.berlin.de/sen/bjf/service/kalender/ferien/ferienordnung-des-landes-berlin-2024_2025-bis-2029_2030.pdf?ts=1752674587)
+ * [Baden-Württemberg](https://km.baden-wuerttemberg.de/de/service/ferien)
+ * [Bayern](https://www.verkuendung-bayern.de/baymbl/2022-747/)
+ * [Bremen](https://www.bildung.bremen.de/ferientermine-3404)
+ * [Hessen](https://kultus.hessen.de/Schulsystem/Ferien/Ferientermine)
+ * [Hamburg](https://www.hamburg.de/resource/blob/134372/5bc131bdd36a604f67b361d21f7df37e/ferienordnung-hamburg-2024-2030-data.pdf)
+ * [Mecklenburg-Vorpommern](https://www.landesrecht-mv.de/bsmv/document/jlr-AFer2024-2030VMVrahmen)
+ * [Niedersachsen](https://www.mk.niedersachsen.de/download/98089/Ferienuebersicht_fuer_Niedersachsen_Schuljahr_2024_25_-_2029_30.pdf)
+ * [Nordrhein-Westfalen(https://www.schulministerium.nrw/service/ferienordnung-fuer-nordrhein-westfalen-fuer-die-schuljahre-bis-202930)
+ * [Rheinland-Pfalz](https://bm.rlp.de/service/ferientermine)
+ * [Schleswig-Holstein](https://www.schleswig-holstein.de/DE/landesregierung/themen/bildung-hochschulen/ferientermine/ferientermine_node.html)
+ * [Saarland](https://www.saarland.de/SharedDocs/Downloads/DE/mbk/Bildungsserver/allgemeine-informationen/ferienordnung_ab_2024_amtsblatt.pdf?__blob=publicationFile&v=1)
+ * [Sachsen](https://www.schule.sachsen.de/schuljahrestermine-4793.html)
+ * [Sachsen-Anhalt](https://mb.sachsen-anhalt.de/fileadmin/Bibliothek/Landesjournal/Bildung_und_Wissenschaft/Erlasse/Ferienregelung_2024_bis_2030.pdf)
+ * [Thüringen](https://bildung.thueringen.de/schule/schulwesen/ferien)
!!! note "Note"
"Mariä Himmelfahrt" is only a holiday in Bavaria (BY) and "Fronleichnam"
in Saxony (SN) and Thuringia (TH) if municipality is mostly catholic which
@@ -93,7 +110,7 @@ class Germany(HolidayBase, ChristianHolidays, InternationalHolidays, StaticHolid
"Sachsen-Anhalt": "ST",
"Thüringen": "TH",
}
- supported_categories = (CATHOLIC, PUBLIC)
+ supported_categories = (CATHOLIC, PUBLIC, SCHOOL)
supported_languages = ("de", "en_US", "th", "uk")
_deprecated_subdivisions = ("BYP",)
@@ -102,6 +119,1200 @@ def __init__(self, *args, **kwargs) -> None:
InternationalHolidays.__init__(self)
StaticHolidays.__init__(self, GermanyStaticHolidays)
super().__init__(*args, **kwargs)
+ # Disable automatic expansion after initial population to avoid
+ # implicitly populating adjacent years when checking membership
+ # (keeps per-year population semantics for school holiday checks).
+ self.expand = False
+
+ def _add_school_holidays_hh(self, year):
+ # Helper to add a range of holidays
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ # Ensure holiday is added for the populated year by passing
+ # month and day to _add_holiday so it constructs the date
+ # using `self._year` (prevents cross-year leakage).
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ # Definition of holidays as (Name, Start Date, End Date)
+ # For single days, Start Date == End Date
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 17), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 2)),
+ (tr("Halbjahrespause"), date(2026, 1, 30), date(2026, 1, 30)),
+ (tr("Frühjahrsferien"), date(2026, 3, 2), date(2026, 3, 13)),
+ (tr("Himmelfahrt/Pfingsten"), date(2026, 5, 11), date(2026, 5, 15)),
+ (tr("Sommerferien"), date(2026, 7, 9), date(2026, 8, 19)),
+ (tr("Herbstferien"), date(2026, 10, 19), date(2026, 10, 30)),
+ (tr("Weihnachtsferien"), date(2026, 12, 21), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 1)),
+ (tr("Halbjahrespause"), date(2027, 1, 29), date(2027, 1, 29)),
+ (tr("Frühjahrsferien"), date(2027, 3, 1), date(2027, 3, 12)),
+ (tr("Himmelfahrt/Pfingsten"), date(2027, 5, 7), date(2027, 5, 14)),
+ (tr("Sommerferien"), date(2027, 7, 1), date(2027, 8, 11)),
+ (tr("Herbstferien"), date(2027, 10, 11), date(2027, 10, 22)),
+ (tr("Weihnachtsferien"), date(2027, 12, 20), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Halbjahrespause"), date(2028, 1, 28), date(2028, 1, 28)),
+ (tr("Frühjahrsferien"), date(2028, 3, 6), date(2028, 3, 17)),
+ (tr("Himmelfahrt/Pfingsten"), date(2028, 5, 22), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 7, 3), date(2028, 8, 11)),
+ (tr("Herbstferien"), date(2028, 10, 2), date(2028, 10, 13)),
+ (tr("Brückentag"), date(2028, 10, 30), date(2028, 10, 30)),
+ (tr("Weihnachtsferien"), date(2028, 12, 18), date(2028, 12, 29)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Halbjahrespause"), date(2029, 2, 2), date(2029, 2, 2)),
+ (tr("Frühjahrsferien"), date(2029, 3, 5), date(2029, 3, 16)),
+ (tr("Himmelfahrt/Pfingsten"), date(2029, 5, 11), date(2029, 5, 18)),
+ (tr("Sommerferien"), date(2029, 7, 2), date(2029, 8, 10)),
+ (tr("Herbstferien"), date(2029, 10, 1), date(2029, 10, 12)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Halbjahrespause"), date(2030, 2, 1), date(2030, 2, 1)),
+ (tr("Frühjahrsferien"), date(2030, 3, 4), date(2030, 3, 15)),
+ (tr("Himmelfahrt/Pfingsten"), date(2030, 5, 20), date(2030, 5, 24)),
+ (tr("Brückentag"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Sommerferien"), date(2030, 7, 4), date(2030, 8, 14)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_nw(self, year):
+ # Helper to add a range of holidays for Nordrhein-Westfalen (NW)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 6)),
+ (tr("Sommerferien"), date(2026, 7, 20), date(2026, 9, 1)),
+ (tr("Herbstferien"), date(2026, 10, 17), date(2026, 10, 31)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (tr("Pfingsten"), date(2027, 5, 18), date(2027, 5, 18)),
+ (tr("Sommerferien"), date(2027, 7, 19), date(2027, 8, 31)),
+ (tr("Herbstferien"), date(2027, 10, 23), date(2027, 11, 6)),
+ (tr("Weihnachtsferien"), date(2027, 12, 24), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Sommerferien"), date(2028, 7, 10), date(2028, 8, 22)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 11, 4)),
+ (tr("Weihnachtsferien"), date(2028, 12, 21), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 7)),
+ (tr("Pfingsten"), date(2029, 5, 22), date(2029, 5, 22)),
+ (tr("Sommerferien"), date(2029, 7, 2), date(2029, 8, 14)),
+ (tr("Herbstferien"), date(2029, 10, 15), date(2029, 10, 27)),
+ (tr("Weihnachtsferien"), date(2029, 12, 20), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 4, 27)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_rp(self, year):
+ # Helper to add a range of holidays for Rheinland-Pfalz (RP)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Sommerferien"), date(2025, 7, 7), date(2025, 8, 16)),
+ (tr("Herbstferien"), date(2025, 10, 13), date(2025, 10, 25)),
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 8)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 11)),
+ (tr("Sommerferien"), date(2026, 6, 29), date(2026, 8, 8)),
+ (tr("Herbstferien"), date(2026, 10, 5), date(2026, 10, 17)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 9)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (tr("Sommerferien"), date(2027, 6, 28), date(2027, 8, 7)),
+ (tr("Herbstferien"), date(2027, 10, 4), date(2027, 10, 16)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 8)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Sommerferien"), date(2028, 7, 3), date(2028, 8, 12)),
+ (tr("Herbstferien"), date(2028, 10, 9), date(2028, 10, 21)),
+ (tr("Weihnachtsferien"), date(2028, 12, 21), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 9)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 7)),
+ (tr("Sommerferien"), date(2029, 7, 16), date(2029, 8, 25)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 3)),
+ (tr("Weihnachtsferien"), date(2029, 12, 24), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 10)),
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 5, 1)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_hb(self, year):
+ # Helper to add a range of holidays for Bremen (HB)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 5)),
+ (tr("Halbjahresferien"), date(2026, 2, 2), date(2026, 2, 3)),
+ (tr("Osterferien"), date(2026, 3, 23), date(2026, 4, 7)),
+ (tr("Tag nach Himmelfahrt"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Pfingsten"), date(2026, 5, 26), date(2026, 5, 26)),
+ (tr("Sommerferien"), date(2026, 7, 2), date(2026, 8, 12)),
+ (tr("Herbstferien"), date(2026, 10, 12), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 9)),
+ (tr("Halbjahresferien"), date(2027, 2, 1), date(2027, 2, 2)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (tr("Tag nach Himmelfahrt"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Pfingsten"), date(2027, 5, 18), date(2027, 5, 18)),
+ (tr("Sommerferien"), date(2027, 7, 8), date(2027, 8, 18)),
+ (tr("Herbstferien"), date(2027, 10, 18), date(2027, 10, 30)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 8)),
+ (tr("Halbjahresferien"), date(2028, 1, 31), date(2028, 2, 1)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Tag nach Himmelfahrt"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Pfingsten"), date(2028, 6, 6), date(2028, 6, 6)),
+ (tr("Sommerferien"), date(2028, 7, 20), date(2028, 8, 30)),
+ (tr("Tag vor dem 03. Oktober"), date(2028, 10, 2), date(2028, 10, 2)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 11, 4)),
+ (tr("Weihnachtsferien"), date(2028, 12, 27), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 6)),
+ (tr("Halbjahresferien"), date(2029, 2, 1), date(2029, 2, 2)),
+ (tr("Osterferien"), date(2029, 3, 19), date(2029, 4, 3)),
+ (tr("Tag vor dem 01. Mai"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Tag nach Himmelfahrt"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Pfingsten"), date(2029, 5, 22), date(2029, 5, 22)),
+ (tr("Sommerferien"), date(2029, 7, 19), date(2029, 8, 29)),
+ (tr("Tage nach dem 03. Oktober"), date(2029, 10, 4), date(2029, 10, 5)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 5)),
+ (tr("Halbjahresferien"), date(2030, 1, 31), date(2030, 2, 1)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 23)),
+ (tr("Tag nach Himmelfahrt"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Pfingsten"), date(2030, 6, 11), date(2030, 6, 11)),
+ (tr("Sommerferien"), date(2030, 7, 11), date(2030, 8, 21)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_sl(self, year):
+ # Helper to add a range of holidays for Saarland (SL)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 2)),
+ (tr("Fastnachtsferien"), date(2026, 2, 16), date(2026, 2, 20)),
+ (tr("Osterferien"), date(2026, 4, 7), date(2026, 4, 17)),
+ (tr("Sommerferien"), date(2026, 6, 29), date(2026, 8, 7)),
+ (tr("Herbstferien"), date(2026, 10, 5), date(2026, 10, 16)),
+ (tr("Weihnachtsferien"), date(2026, 12, 21), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Fastnachtsferien"), date(2027, 2, 8), date(2027, 2, 12)),
+ (tr("Osterferien"), date(2027, 3, 30), date(2027, 4, 9)),
+ (tr("Sommerferien"), date(2027, 6, 28), date(2027, 8, 6)),
+ (tr("Herbstferien"), date(2027, 10, 4), date(2027, 10, 15)),
+ (tr("Weihnachtsferien"), date(2027, 12, 20), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Fastnachtsferien"), date(2028, 2, 21), date(2028, 2, 29)),
+ (tr("Osterferien"), date(2028, 4, 12), date(2028, 4, 21)),
+ (tr("Sommerferien"), date(2028, 7, 3), date(2028, 8, 11)),
+ (tr("Herbstferien"), date(2028, 10, 9), date(2028, 10, 20)),
+ (tr("Weihnachtsferien"), date(2028, 12, 20), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 2)),
+ (tr("Fastnachtsferien"), date(2029, 2, 12), date(2029, 2, 16)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 6)),
+ (tr("Pfingstferien"), date(2029, 5, 22), date(2029, 5, 25)),
+ (tr("Sommerferien"), date(2029, 7, 16), date(2029, 8, 24)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Fastnachtsferien"), date(2030, 2, 25), date(2030, 3, 5)),
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 4, 26)),
+ (tr("Sommerferien"), date(2030, 7, 22), date(2030, 8, 30)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_th(self, year):
+ # Helper to add a range of holidays for Thüringen (TH)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 3)),
+ (tr("Winterferien"), date(2026, 2, 16), date(2026, 2, 21)),
+ (tr("Osterferien"), date(2026, 4, 7), date(2026, 4, 17)),
+ (tr("Schulfreier Tag"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Sommerferien"), date(2026, 7, 4), date(2026, 8, 14)),
+ (tr("Herbstferien"), date(2026, 10, 12), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 2)),
+ (tr("Winterferien"), date(2027, 2, 1), date(2027, 2, 6)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (tr("Schulfreier Tag"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Sommerferien"), date(2027, 7, 10), date(2027, 8, 20)),
+ (tr("Herbstferien"), date(2027, 10, 9), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Winterferien"), date(2028, 2, 7), date(2028, 2, 12)),
+ (tr("Osterferien"), date(2028, 4, 3), date(2028, 4, 15)),
+ (tr("Schulfreier Tag"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 7, 22), date(2028, 9, 1)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 11, 3)),
+ (tr("Weihnachtsferien"), date(2028, 12, 23), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 5)),
+ (tr("Winterferien"), date(2029, 2, 12), date(2029, 2, 17)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 7)),
+ (tr("Schulfreier Tag"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Sommerferien"), date(2029, 7, 21), date(2029, 8, 31)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 3)),
+ (tr("Weihnachtsferien"), date(2029, 12, 22), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Winterferien"), date(2030, 2, 11), date(2030, 2, 16)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 20)),
+ (tr("Schulfreier Tag"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Sommerferien"), date(2030, 7, 13), date(2030, 8, 23)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_sh(self, year):
+ # Helper to add a range of holidays for Schleswig-Holstein (SH)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 19), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 6)),
+ (tr("Osterferien"), date(2026, 3, 26), date(2026, 4, 10)),
+ (tr("Himmelfahrt"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Sommerferien"), date(2026, 7, 4), date(2026, 8, 15)),
+ (tr("Herbstferien"), date(2026, 10, 12), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 21), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Osterferien"), date(2027, 3, 30), date(2027, 4, 10)),
+ (tr("Himmelfahrt"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Sommerferien"), date(2027, 7, 3), date(2027, 8, 14)),
+ (tr("Herbstferien"), date(2027, 10, 11), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 8)),
+ (tr("Osterferien"), date(2028, 4, 3), date(2028, 4, 15)),
+ (tr("Himmelfahrt"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 6, 24), date(2028, 8, 4)),
+ (tr("Herbstferien"), date(2028, 10, 16), date(2028, 10, 30)),
+ (tr("Weihnachtsferien"), date(2028, 12, 21), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Osterferien"), date(2029, 3, 23), date(2029, 4, 6)),
+ (tr("Himmelfahrt"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Sommerferien"), date(2029, 6, 23), date(2029, 8, 3)),
+ (tr("Herbstferien"), date(2029, 10, 8), date(2029, 10, 19)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 8)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 20)),
+ (tr("Himmelfahrt"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Sommerferien"), date(2030, 7, 8), date(2030, 8, 17)),
+ (tr("Herbstferien"), date(2030, 10, 14), date(2030, 10, 25)),
+ (tr("Weihnachtsferien"), date(2030, 12, 20), date(2030, 12, 31)),
+ ]
+ elif year == 2031:
+ holidays_map = [
+ (tr("Osterferien"), date(2031, 3, 28), date(2031, 4, 10)),
+ (tr("Himmelfahrt"), date(2031, 5, 23), date(2031, 5, 23)),
+ (tr("Weihnachtsferien"), date(2031, 1, 1), date(2031, 1, 6)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_sn(self, year):
+ # Helper to add a range of holidays for Sachsen (SN)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 2)),
+ (tr("Winterferien"), date(2026, 2, 9), date(2026, 2, 21)),
+ (tr("Osterferien"), date(2026, 4, 3), date(2026, 4, 10)),
+ (tr("Sommerferien"), date(2026, 7, 4), date(2026, 8, 14)),
+ (tr("Unterrichtsfreier Tag"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Herbstferien"), date(2026, 10, 12), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 2)),
+ (tr("Winterferien"), date(2027, 2, 8), date(2027, 2, 19)),
+ (tr("Osterferien"), date(2027, 3, 26), date(2027, 4, 2)),
+ (tr("Pfingstferien"), date(2027, 5, 15), date(2027, 5, 18)),
+ (tr("Unterrichtsfreier Tag"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Sommerferien"), date(2027, 7, 10), date(2027, 8, 20)),
+ (tr("Herbstferien"), date(2027, 10, 11), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 1)),
+ (tr("Winterferien"), date(2028, 2, 14), date(2028, 2, 26)),
+ (tr("Osterferien"), date(2028, 4, 14), date(2028, 4, 22)),
+ (tr("Unterrichtsfreier Tag"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 7, 22), date(2028, 9, 1)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 11, 3)),
+ (tr("Weihnachtsferien"), date(2028, 12, 23), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 1)),
+ (tr("Winterferien"), date(2029, 2, 5), date(2029, 2, 16)),
+ (tr("Osterferien"), date(2029, 3, 29), date(2029, 4, 6)),
+ (tr("Pfingstferien"), date(2029, 5, 19), date(2029, 5, 22)),
+ (tr("Unterrichtsfreier Tag"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Sommerferien"), date(2029, 7, 21), date(2029, 8, 31)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 22), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Winterferien"), date(2030, 2, 18), date(2030, 3, 1)),
+ (tr("Osterferien"), date(2030, 4, 19), date(2030, 4, 26)),
+ (tr("Pfingstferien"), date(2030, 6, 8), date(2030, 6, 11)),
+ (tr("Unterrichtsfreier Tag"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Sommerferien"), date(2030, 7, 13), date(2030, 8, 23)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_st(self, year):
+ # Helper to add a range of holidays for Sachsen-Anhalt (ST)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 5)),
+ (tr("Winterferien"), date(2026, 1, 31), date(2026, 2, 6)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 4)),
+ (tr("Pfingstferien"), date(2026, 5, 26), date(2026, 5, 29)),
+ (tr("Sommerferien"), date(2026, 7, 4), date(2026, 8, 14)),
+ (tr("Herbstferien"), date(2026, 10, 19), date(2026, 10, 30)),
+ (tr("Weihnachtsferien"), date(2026, 12, 21), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 5)),
+ (tr("Winterferien"), date(2027, 2, 1), date(2027, 2, 6)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 3, 27)),
+ (tr("Pfingstferien"), date(2027, 5, 15), date(2027, 5, 22)),
+ (tr("Sommerferien"), date(2027, 7, 10), date(2027, 8, 20)),
+ (tr("Herbstferien"), date(2027, 10, 18), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 20), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Winterferien"), date(2028, 2, 7), date(2028, 2, 12)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Pfingstferien"), date(2028, 6, 3), date(2028, 6, 10)),
+ (tr("Sommerferien"), date(2028, 7, 22), date(2028, 9, 1)),
+ (tr("Beweglicher Ferientag"), date(2028, 10, 2), date(2028, 10, 2)),
+ (tr("Herbstferien"), date(2028, 10, 30), date(2028, 11, 3)),
+ (tr("Weihnachtsferien"), date(2028, 12, 21), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 5)),
+ (tr("Winterferien"), date(2029, 2, 5), date(2029, 2, 10)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 3, 31)),
+ (tr("Beweglicher Ferientag"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Pfingstferien"), date(2029, 5, 11), date(2029, 5, 25)),
+ (tr("Sommerferien"), date(2029, 7, 21), date(2029, 8, 31)),
+ (tr("Herbstferien"), date(2029, 10, 29), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 5)),
+ (tr("Winterferien"), date(2030, 2, 4), date(2030, 2, 8)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 20)),
+ (tr("Beweglicher Ferientag"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Pfingstferien"), date(2030, 6, 3), date(2030, 6, 8)),
+ (tr("Sommerferien"), date(2030, 7, 13), date(2030, 8, 23)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_bw(self, year):
+ # Helper to add a range of holidays for Baden-Württemberg
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Sommerferien"), date(2025, 7, 31), date(2025, 9, 13)),
+ (tr("Herbstferien"), date(2025, 10, 27), date(2025, 10, 30)),
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 5)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 11)),
+ (tr("Pfingstferien"), date(2026, 5, 26), date(2026, 6, 5)),
+ (tr("Sommerferien"), date(2026, 7, 30), date(2026, 9, 12)),
+ (tr("Herbstferien"), date(2026, 10, 26), date(2026, 10, 30)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 9)),
+ (tr("Osterferien"), date(2027, 3, 30), date(2027, 4, 3)),
+ (tr("Pfingstferien"), date(2027, 5, 18), date(2027, 5, 29)),
+ (tr("Sommerferien"), date(2027, 7, 29), date(2027, 9, 11)),
+ (tr("Herbstferien"), date(2027, 11, 2), date(2027, 11, 6)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 8)),
+ (tr("Osterferien"), date(2028, 4, 18), date(2028, 4, 22)),
+ (tr("Pfingstferien"), date(2028, 6, 6), date(2028, 6, 17)),
+ (tr("Sommerferien"), date(2028, 7, 27), date(2028, 9, 9)),
+ (tr("Herbstferien"), date(2028, 10, 30), date(2028, 11, 3)),
+ (tr("Weihnachtsferien"), date(2028, 12, 23), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 5)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 7)),
+ (tr("Pfingstferien"), date(2029, 5, 22), date(2029, 6, 1)),
+ (tr("Sommerferien"), date(2029, 7, 26), date(2029, 9, 8)),
+ (tr("Herbstferien"), date(2029, 10, 29), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 22), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 5)),
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 4, 26)),
+ (tr("Pfingstferien"), date(2030, 6, 11), date(2030, 6, 21)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_by(self, year):
+ # Helper to add a range of holidays for Bayern (BY)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 5)),
+ (tr("Frühjahrsferien"), date(2026, 2, 16), date(2026, 2, 20)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 10)),
+ (tr("Pfingstferien"), date(2026, 5, 26), date(2026, 6, 5)),
+ (tr("Sommerferien"), date(2026, 8, 3), date(2026, 9, 14)),
+ (
+ tr("Tage um Allerheiligen"),
+ date(2026, 11, 2),
+ date(2026, 11, 6),
+ ),
+ (tr("Weihnachtsferien"), date(2026, 12, 24), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 8)),
+ (tr("Frühjahrsferien"), date(2027, 2, 8), date(2027, 2, 12)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 2)),
+ (tr("Pfingstferien"), date(2027, 5, 18), date(2027, 5, 28)),
+ (tr("Sommerferien"), date(2027, 8, 2), date(2027, 9, 13)),
+ (
+ tr(" Tage um Allerheiligen"),
+ date(2027, 11, 2),
+ date(2027, 11, 5),
+ ),
+ (tr("Weihnachtsferien"), date(2027, 12, 24), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 7)),
+ (tr("Frühjahrsferien"), date(2028, 2, 28), date(2028, 3, 3)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 21)),
+ (tr("Pfingstferien"), date(2028, 6, 6), date(2028, 6, 16)),
+ (tr("Sommerferien"), date(2028, 7, 31), date(2028, 9, 11)),
+ (
+ tr("Tage um Allerheiligen"),
+ date(2028, 10, 30),
+ date(2028, 11, 3),
+ ),
+ (tr("Weihnachtsferien"), date(2028, 12, 23), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 5)),
+ (tr("Frühjahrsferien"), date(2029, 2, 12), date(2029, 2, 16)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 6)),
+ (tr("Pfingstferien"), date(2029, 5, 22), date(2029, 6, 1)),
+ (tr("Sommerferien"), date(2029, 7, 30), date(2029, 9, 10)),
+ (
+ tr("Tage um Allerheiligen"),
+ date(2029, 10, 29),
+ date(2029, 11, 2),
+ ),
+ (tr("Weihnachtsferien"), date(2029, 12, 24), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Frühjahrsferien"), date(2030, 3, 4), date(2030, 3, 8)),
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 4, 26)),
+ (tr("Pfingstferien"), date(2030, 6, 11), date(2030, 6, 21)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_be(self, year):
+ # Helper to add a range of holidays for Berlin (BE)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 2)),
+ (tr("Winterferien"), date(2026, 2, 2), date(2026, 2, 7)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 10)),
+ (tr("Unterrichtsfreier Tag nach AZVO"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Pfingstferien"), date(2026, 5, 26), date(2026, 5, 26)),
+ (tr("Sommerferien"), date(2026, 7, 9), date(2026, 8, 22)),
+ (tr("Herbstferien"), date(2026, 10, 19), date(2026, 10, 31)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 2)),
+ (tr("Winterferien"), date(2027, 2, 1), date(2027, 2, 6)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 2)),
+ (tr("Unterrichtsfreier Tag nach AZVO"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Pfingstferien"), date(2027, 5, 18), date(2027, 5, 19)),
+ (tr("Sommerferien"), date(2027, 7, 1), date(2027, 8, 14)),
+ (tr("Herbstferien"), date(2027, 10, 11), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 22), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 2)),
+ (tr("Winterferien"), date(2028, 1, 31), date(2028, 2, 5)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Unterrichtsfreier Tag nach AZVO"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Pfingstferien"), date(2028, 6, 1), date(2028, 6, 2)),
+ (tr("Sommerferien"), date(2028, 7, 1), date(2028, 8, 12)),
+ (tr("Herbstferien"), date(2028, 10, 2), date(2028, 10, 14)),
+ (tr("Weihnachtsferien"), date(2028, 12, 22), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 4)),
+ (tr("Winterferien"), date(2029, 1, 29), date(2029, 2, 3)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 6)),
+ (tr("Unterrichtsfreie Tage"), date(2029, 3, 9), date(2029, 3, 9)),
+ (tr("Unterrichtsfreie Tage"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Unterrichtsfreier Tag nach AZVO"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Pfingstferien"), date(2029, 5, 22), date(2029, 5, 25)),
+ (tr("Sommerferien"), date(2029, 7, 1), date(2029, 8, 11)),
+ (tr("Herbstferien"), date(2029, 10, 1), date(2029, 10, 12)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Winterferien"), date(2030, 2, 4), date(2030, 2, 9)),
+ (tr("Osterferien"), date(2030, 4, 15), date(2030, 4, 26)),
+ (tr("Unterrichtsfreier Tag nach AZVO"), date(2030, 5, 31), date(2030, 5, 31)),
+ (tr("Pfingstferien"), date(2030, 6, 7), date(2030, 6, 7)),
+ (tr("Sommerferien"), date(2030, 7, 4), date(2030, 8, 17)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_mv(self, year):
+ # Helper to add a range of holidays for Mecklenburg-Vorpommern (MV)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 20), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 3)),
+ (tr("Winterferien"), date(2026, 2, 9), date(2026, 2, 20)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 8)),
+ (tr("Pfingstferien"), date(2026, 5, 22), date(2026, 5, 26)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Sommerferien"), date(2026, 7, 13), date(2026, 8, 22)),
+ (tr("Herbstferien"), date(2026, 10, 15), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 21), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 2)),
+ (tr("Winterferien"), date(2027, 2, 8), date(2027, 2, 19)),
+ (tr("Osterferien"), date(2027, 3, 24), date(2027, 4, 2)),
+ (tr("Pfingstferien"), date(2027, 5, 14), date(2027, 5, 18)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Sommerferien"), date(2027, 7, 5), date(2027, 8, 14)),
+ (tr("Herbstferien"), date(2027, 10, 14), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 22), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 2)),
+ (tr("Winterferien"), date(2028, 2, 5), date(2028, 2, 17)),
+ (tr("Osterferien"), date(2028, 4, 12), date(2028, 4, 21)),
+ (tr("Pfingstferien"), date(2028, 6, 2), date(2028, 6, 6)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 6, 26), date(2028, 8, 5)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 10, 28)),
+ (tr("Weihnachtsferien"), date(2028, 12, 22), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 4)),
+ (tr("Winterferien"), date(2029, 2, 5), date(2029, 2, 16)),
+ (tr("Osterferien"), date(2029, 3, 28), date(2029, 4, 6)),
+ (tr("Pfingstferien"), date(2029, 5, 18), date(2029, 5, 22)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2029, 3, 9), date(2029, 3, 9)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2029, 3, 30), date(2029, 3, 30)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Zusätzliche feststehende Ferientage"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Sommerferien"), date(2029, 6, 18), date(2029, 7, 28)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 10, 27)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 4)),
+ (tr("Winterferien"), date(2030, 2, 4), date(2030, 2, 15)),
+ (tr("Osterferien"), date(2030, 4, 17), date(2030, 4, 26)),
+ (tr("Pfingstferien"), date(2030, 6, 7), date(2030, 6, 11)),
+ (tr("Sommerferien"), date(2030, 7, 1), date(2030, 8, 10)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_ni(self, year):
+ # Helper to add a range of holidays for Niedersachsen (NI)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [(tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31))]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 5)),
+ (tr("Halbjahresferien"), date(2026, 2, 2), date(2026, 2, 3)),
+ (tr("Osterferien"), date(2026, 3, 23), date(2026, 4, 7)),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2026, 5, 15),
+ date(2026, 5, 15),
+ ),
+ (tr("Pfingstferien"), date(2026, 5, 26), date(2026, 5, 26)),
+ (tr("Sommerferien"), date(2026, 7, 2), date(2026, 8, 12)),
+ (tr("Herbstferien"), date(2026, 10, 12), date(2026, 10, 24)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 9)),
+ (tr("Halbjahresferien"), date(2027, 2, 1), date(2027, 2, 2)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2027, 5, 7),
+ date(2027, 5, 7),
+ ),
+ (tr("Pfingstferien"), date(2027, 5, 18), date(2027, 5, 18)),
+ (tr("Sommerferien"), date(2027, 7, 8), date(2027, 8, 18)),
+ (tr("Herbstferien"), date(2027, 10, 16), date(2027, 10, 30)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 8)),
+ (tr("Halbjahresferien"), date(2028, 1, 31), date(2028, 2, 1)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2028, 5, 26),
+ date(2028, 5, 26),
+ ),
+ (tr("Pfingstferien"), date(2028, 6, 6), date(2028, 6, 6)),
+ (tr("Sommerferien"), date(2028, 7, 20), date(2028, 8, 30)),
+ (tr("Herbstferien"), date(2028, 10, 2), date(2028, 10, 2)),
+ (tr("Herbstferien"), date(2028, 10, 23), date(2028, 11, 4)),
+ (tr("Weihnachtsferien"), date(2028, 12, 27), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 6)),
+ (tr("Halbjahresferien"), date(2029, 2, 1), date(2029, 2, 2)),
+ (tr("Osterferien"), date(2029, 3, 19), date(2029, 4, 3)),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2029, 4, 30),
+ date(2029, 4, 30),
+ ),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2029, 5, 11),
+ date(2029, 5, 11),
+ ),
+ (tr("Pfingstferien"), date(2029, 5, 22), date(2029, 5, 22)),
+ (tr("Sommerferien"), date(2029, 7, 19), date(2029, 8, 29)),
+ (tr("Herbstferien"), date(2029, 10, 4), date(2029, 10, 5)),
+ (tr("Herbstferien"), date(2029, 10, 22), date(2029, 11, 2)),
+ (tr("Weihnachtsferien"), date(2029, 12, 21), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 5)),
+ (tr("Halbjahresferien"), date(2030, 1, 31), date(2030, 2, 1)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 23)),
+ (
+ tr("Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"),
+ date(2030, 5, 31),
+ date(2030, 5, 31),
+ ),
+ (tr("Pfingstferien"), date(2030, 6, 11), date(2030, 6, 11)),
+ (tr("Sommerferien"), date(2030, 7, 11), date(2030, 8, 21)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_bb(self, year):
+ # Helper to add a range of holidays for Brandenburg (BB)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ # Part of the 2025/2026 Christmas range (only 2025 portion)
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 2)),
+ (tr("Winterferien"), date(2026, 2, 2), date(2026, 2, 7)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 10)),
+ (tr("Pfingsten"), date(2026, 5, 26), date(2026, 5, 26)),
+ (tr("Variabler Ferientag"), date(2026, 5, 13), date(2026, 5, 13)),
+ (tr("Variabler Ferientag"), date(2026, 5, 15), date(2026, 5, 15)),
+ (tr("Variabler Ferientag"), date(2026, 5, 18), date(2026, 5, 18)),
+ (tr("Sommerferien"), date(2026, 7, 9), date(2026, 8, 22)),
+ (tr("Herbstferien"), date(2026, 10, 19), date(2026, 10, 30)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 2)),
+ (tr("Winterferien"), date(2027, 2, 1), date(2027, 2, 6)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 3)),
+ (tr("Pfingsten"), date(2027, 5, 18), date(2027, 5, 18)),
+ (tr("Variabler Ferientag"), date(2027, 5, 7), date(2027, 5, 7)),
+ (tr("Sommerferien"), date(2027, 7, 1), date(2027, 8, 14)),
+ (tr("Herbstferien"), date(2027, 10, 11), date(2027, 10, 23)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Winterferien"), date(2028, 1, 31), date(2028, 2, 5)),
+ (tr("Osterferien"), date(2028, 4, 10), date(2028, 4, 22)),
+ (tr("Variabler Ferientag"), date(2028, 5, 26), date(2028, 5, 26)),
+ (tr("Sommerferien"), date(2028, 6, 29), date(2028, 8, 12)),
+ (tr("Herbstferien"), date(2028, 10, 2), date(2028, 10, 14)),
+ (tr("Variabler Ferientag"), date(2028, 10, 30), date(2028, 10, 30)),
+ (tr("Weihnachtsferien"), date(2028, 12, 22), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 2)),
+ (tr("Winterferien"), date(2029, 1, 29), date(2029, 2, 3)),
+ (tr("Osterferien"), date(2029, 3, 26), date(2029, 4, 6)),
+ (tr("Pfingsten"), date(2029, 5, 22), date(2029, 5, 22)),
+ (tr("Variabler Ferientag"), date(2029, 4, 30), date(2029, 4, 30)),
+ (tr("Variabler Ferientag"), date(2029, 5, 11), date(2029, 5, 11)),
+ (tr("Sommerferien"), date(2029, 6, 28), date(2029, 8, 11)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _add_school_holidays_he(self, year):
+ # Helper to add a range of holidays for Hessen (HE)
+ def _add_holiday_range(name, start_date, end_date):
+ current_date = start_date
+ while current_date <= end_date:
+ if current_date.year == self._year:
+ self._add_holiday(name, current_date.month, current_date.day)
+ current_date += timedelta(days=1)
+
+ holidays_map = []
+
+ if year == 2025:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2025, 12, 22), date(2025, 12, 31)),
+ ]
+ elif year == 2026:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2026, 1, 1), date(2026, 1, 10)),
+ (tr("Osterferien"), date(2026, 3, 30), date(2026, 4, 10)),
+ (tr("Sommerferien"), date(2026, 6, 29), date(2026, 8, 7)),
+ (tr("Herbstferien"), date(2026, 10, 5), date(2026, 10, 17)),
+ (tr("Weihnachtsferien"), date(2026, 12, 23), date(2026, 12, 31)),
+ ]
+ elif year == 2027:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2027, 1, 1), date(2027, 1, 10)),
+ (tr("Osterferien"), date(2027, 3, 22), date(2027, 4, 2)),
+ (tr("Sommerferien"), date(2027, 6, 28), date(2027, 8, 6)),
+ (tr("Herbstferien"), date(2027, 10, 4), date(2027, 10, 16)),
+ (tr("Weihnachtsferien"), date(2027, 12, 23), date(2027, 12, 31)),
+ ]
+ elif year == 2028:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2028, 1, 1), date(2028, 1, 11)),
+ (tr("Osterferien"), date(2028, 4, 3), date(2028, 4, 14)),
+ (tr("Sommerferien"), date(2028, 7, 3), date(2028, 8, 11)),
+ (tr("Herbstferien"), date(2028, 10, 9), date(2028, 10, 20)),
+ (tr("Weihnachtsferien"), date(2028, 12, 27), date(2028, 12, 31)),
+ ]
+ elif year == 2029:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2029, 1, 1), date(2029, 1, 11)),
+ (tr("Osterferien"), date(2029, 3, 29), date(2029, 4, 13)),
+ (tr("Sommerferien"), date(2029, 7, 16), date(2029, 8, 24)),
+ (tr("Herbstferien"), date(2029, 10, 15), date(2029, 10, 26)),
+ (tr("Weihnachtsferien"), date(2029, 12, 24), date(2029, 12, 31)),
+ ]
+ elif year == 2030:
+ holidays_map = [
+ (tr("Weihnachtsferien"), date(2030, 1, 1), date(2030, 1, 11)),
+ (tr("Osterferien"), date(2030, 4, 8), date(2030, 4, 22)),
+ (tr("Sommerferien"), date(2030, 7, 22), date(2030, 8, 30)),
+ ]
+
+ for name, start, end in holidays_map:
+ _add_holiday_range(name, start, end)
+
+ def _populate(self, year):
+ super()._populate(year)
+
+ if self.subdiv == "HH" and SCHOOL in self.categories:
+ self._add_school_holidays_hh(year)
+ # Ensure no holidays from other years were accidentally added
+ # (defensive cleanup for cross-year ranges).
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "BB" and SCHOOL in self.categories:
+ self._add_school_holidays_bb(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "HB" and SCHOOL in self.categories:
+ self._add_school_holidays_hb(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "BW" and SCHOOL in self.categories:
+ self._add_school_holidays_bw(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "BY" and SCHOOL in self.categories:
+ self._add_school_holidays_by(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "BE" and SCHOOL in self.categories:
+ self._add_school_holidays_be(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "MV" and SCHOOL in self.categories:
+ self._add_school_holidays_mv(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "RP" and SCHOOL in self.categories:
+ self._add_school_holidays_rp(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "SL" and SCHOOL in self.categories:
+ self._add_school_holidays_sl(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "NI" and SCHOOL in self.categories:
+ self._add_school_holidays_ni(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "NW" and SCHOOL in self.categories:
+ self._add_school_holidays_nw(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "HE" and SCHOOL in self.categories:
+ self._add_school_holidays_he(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "TH" and SCHOOL in self.categories:
+ self._add_school_holidays_th(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "SH" and SCHOOL in self.categories:
+ self._add_school_holidays_sh(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "SN" and SCHOOL in self.categories:
+ self._add_school_holidays_sn(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
+ if self.subdiv == "ST" and SCHOOL in self.categories:
+ self._add_school_holidays_st(year)
+ for dt in list(self.keys()):
+ if dt.year != year:
+ self.pop(dt)
def _populate_public_holidays(self):
# New Year's Day.
diff --git a/holidays/locale/de/LC_MESSAGES/DE.po b/holidays/locale/de/LC_MESSAGES/DE.po
index 90032d5d33..91bd55d212 100644
--- a/holidays/locale/de/LC_MESSAGES/DE.po
+++ b/holidays/locale/de/LC_MESSAGES/DE.po
@@ -13,9 +13,9 @@
# Germany holidays.
msgid ""
msgstr ""
-"Project-Id-Version: Holidays 0.87\n"
+"Project-Id-Version: Holidays 0.88\n"
"POT-Creation-Date: 2023-04-04 16:13+0300\n"
-"PO-Revision-Date: 2025-12-02 18:19+0200\n"
+"PO-Revision-Date: 2025-12-27 00:27+0100\n"
"Last-Translator: ~Jhellico \n"
"Language-Team: Holidays Localization Team\n"
"Language: de\n"
@@ -26,6 +26,87 @@ msgstr ""
"X-Generator: Poedit 3.6\n"
"X-Source-Language: de\n"
+msgid "Weihnachtsferien"
+msgstr ""
+
+msgid "Halbjahrespause"
+msgstr ""
+
+msgid "Frühjahrsferien"
+msgstr ""
+
+msgid "Himmelfahrt/Pfingsten"
+msgstr ""
+
+msgid "Sommerferien"
+msgstr ""
+
+msgid "Herbstferien"
+msgstr ""
+
+msgid "Brückentag"
+msgstr ""
+
+msgid "Osterferien"
+msgstr ""
+
+msgid "Pfingsten"
+msgstr ""
+
+msgid "Halbjahresferien"
+msgstr ""
+
+msgid "Tag nach Himmelfahrt"
+msgstr ""
+
+msgid "Tag vor dem 03. Oktober"
+msgstr ""
+
+msgid "Tag vor dem 01. Mai"
+msgstr ""
+
+msgid "Tage nach dem 03. Oktober"
+msgstr ""
+
+msgid "Fastnachtsferien"
+msgstr ""
+
+msgid "Pfingstferien"
+msgstr ""
+
+msgid "Winterferien"
+msgstr ""
+
+msgid "Schulfreier Tag"
+msgstr ""
+
+msgid "Himmelfahrt"
+msgstr ""
+
+msgid "Unterrichtsfreier Tag"
+msgstr ""
+
+msgid "Beweglicher Ferientag"
+msgstr ""
+
+msgid "Tage um Allerheiligen"
+msgstr ""
+
+msgid "Unterrichtsfreier Tag nach AZVO"
+msgstr ""
+
+msgid "Unterrichtsfreie Tage"
+msgstr ""
+
+msgid "Zusätzliche feststehende Ferientage"
+msgstr ""
+
+msgid "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+msgstr ""
+
+msgid "Variabler Ferientag"
+msgstr ""
+
#. New Year's Day.
msgid "Neujahr"
msgstr ""
diff --git a/holidays/locale/en_US/LC_MESSAGES/DE.po b/holidays/locale/en_US/LC_MESSAGES/DE.po
index 0792a39ca7..f004c51861 100644
--- a/holidays/locale/en_US/LC_MESSAGES/DE.po
+++ b/holidays/locale/en_US/LC_MESSAGES/DE.po
@@ -14,9 +14,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Holidays 0.87\n"
+"Project-Id-Version: Holidays 0.88\n"
"POT-Creation-Date: 2023-04-04 16:13+0300\n"
-"PO-Revision-Date: 2025-12-02 18:19+0200\n"
+"PO-Revision-Date: 2025-12-27 00:27+0100\n"
"Last-Translator: ~Jhellico \n"
"Language-Team: Holidays Localization Team\n"
"Language: en_US\n"
@@ -27,6 +27,87 @@ msgstr ""
"X-Generator: Poedit 3.6\n"
"X-Source-Language: de\n"
+msgid "Weihnachtsferien"
+msgstr "Christmas holidays"
+
+msgid "Halbjahrespause"
+msgstr "mid-term break"
+
+msgid "Frühjahrsferien"
+msgstr "Spring break"
+
+msgid "Himmelfahrt/Pfingsten"
+msgstr "Ascension/Pentecost break"
+
+msgid "Sommerferien"
+msgstr "Summer holidays"
+
+msgid "Herbstferien"
+msgstr "Autumn break"
+
+msgid "Brückentag"
+msgstr "Bridge day"
+
+msgid "Osterferien"
+msgstr "Easter holidays"
+
+msgid "Pfingsten"
+msgstr "Pentecost"
+
+msgid "Halbjahresferien"
+msgstr "mid-term holidays"
+
+msgid "Tag nach Himmelfahrt"
+msgstr "Day after Ascension"
+
+msgid "Tag vor dem 03. Oktober"
+msgstr "Day before German Unity Day"
+
+msgid "Tag vor dem 01. Mai"
+msgstr "Day before May Day"
+
+msgid "Tage nach dem 03. Oktober"
+msgstr "Days after German Unity Day"
+
+msgid "Fastnachtsferien"
+msgstr "Carnival break"
+
+msgid "Pfingstferien"
+msgstr "Pentecost holidays"
+
+msgid "Winterferien"
+msgstr "Winter holidays"
+
+msgid "Schulfreier Tag"
+msgstr "School-free day"
+
+msgid "Himmelfahrt"
+msgstr "Ascension"
+
+msgid "Unterrichtsfreier Tag"
+msgstr "Non-teaching day"
+
+msgid "Beweglicher Ferientag"
+msgstr "Movable holiday"
+
+msgid "Tage um Allerheiligen"
+msgstr "days around All Saints' Day"
+
+msgid "Unterrichtsfreier Tag nach AZVO"
+msgstr "Non-teaching day according to AZVO"
+
+msgid "Unterrichtsfreie Tage"
+msgstr "Non-teaching days"
+
+msgid "Zusätzliche feststehende Ferientage"
+msgstr "Additional fixed holiday days"
+
+msgid "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+msgstr "Holidays connected with May Day and Ascension Day"
+
+msgid "Variabler Ferientag"
+msgstr "Variable holiday"
+
#. New Year's Day.
msgid "Neujahr"
msgstr "New Year's Day"
diff --git a/holidays/locale/th/LC_MESSAGES/DE.po b/holidays/locale/th/LC_MESSAGES/DE.po
index 73180f2c1f..c1cccabf5e 100644
--- a/holidays/locale/th/LC_MESSAGES/DE.po
+++ b/holidays/locale/th/LC_MESSAGES/DE.po
@@ -14,9 +14,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Holidays 0.87\n"
+"Project-Id-Version: Holidays 0.88\n"
"POT-Creation-Date: 2024-09-05 23:21+0700\n"
-"PO-Revision-Date: 2025-12-02 18:20+0200\n"
+"PO-Revision-Date: 2025-12-27 00:53+0100\n"
"Last-Translator: ~Jhellico \n"
"Language-Team: Holidays Localization Team\n"
"Language: th\n"
@@ -27,6 +27,87 @@ msgstr ""
"X-Generator: Poedit 3.6\n"
"X-Source-Language: de\n"
+msgid "Weihnachtsferien"
+msgstr "Weihnachtsferien"
+
+msgid "Halbjahrespause"
+msgstr "Halbjahrespause"
+
+msgid "Frühjahrsferien"
+msgstr "Frühjahrsferien"
+
+msgid "Himmelfahrt/Pfingsten"
+msgstr "Himmelfahrt/Pfingsten"
+
+msgid "Sommerferien"
+msgstr "Sommerferien"
+
+msgid "Herbstferien"
+msgstr "Herbstferien"
+
+msgid "Brückentag"
+msgstr "Brückentag"
+
+msgid "Osterferien"
+msgstr "Osterferien"
+
+msgid "Pfingsten"
+msgstr "Pfingsten"
+
+msgid "Halbjahresferien"
+msgstr "Halbjahresferien"
+
+msgid "Tag nach Himmelfahrt"
+msgstr "Tag nach Himmelfahrt"
+
+msgid "Tag vor dem 03. Oktober"
+msgstr "Tag vor dem 03. Oktober"
+
+msgid "Tag vor dem 01. Mai"
+msgstr "Tag vor dem 01. Mai"
+
+msgid "Tage nach dem 03. Oktober"
+msgstr "Tage nach dem 03. Oktober"
+
+msgid "Fastnachtsferien"
+msgstr "Fastnachtsferien"
+
+msgid "Pfingstferien"
+msgstr "Pfingstferien"
+
+msgid "Winterferien"
+msgstr "Winterferien"
+
+msgid "Schulfreier Tag"
+msgstr "Schulfreier Tag"
+
+msgid "Himmelfahrt"
+msgstr "Himmelfahrt"
+
+msgid "Unterrichtsfreier Tag"
+msgstr "Unterrichtsfreier Tag"
+
+msgid "Beweglicher Ferientag"
+msgstr "Beweglicher Ferientag"
+
+msgid "Tage um Allerheiligen"
+msgstr "Tage um Allerheiligen"
+
+msgid "Unterrichtsfreier Tag nach AZVO"
+msgstr "Unterrichtsfreier Tag nach AZVO"
+
+msgid "Unterrichtsfreie Tage"
+msgstr "Unterrichtsfreie Tage"
+
+msgid "Zusätzliche feststehende Ferientage"
+msgstr "Zusätzliche feststehende Ferientage"
+
+msgid "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+msgstr "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+
+msgid "Variabler Ferientag"
+msgstr "Variabler Ferientag"
+
#. New Year's Day.
msgid "Neujahr"
msgstr "วันขึ้นปีใหม่"
diff --git a/holidays/locale/uk/LC_MESSAGES/DE.po b/holidays/locale/uk/LC_MESSAGES/DE.po
index 9764c6deb1..f6b6967b74 100644
--- a/holidays/locale/uk/LC_MESSAGES/DE.po
+++ b/holidays/locale/uk/LC_MESSAGES/DE.po
@@ -14,9 +14,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Holidays 0.87\n"
+"Project-Id-Version: Holidays 0.88\n"
"POT-Creation-Date: 2023-04-04 16:13+0300\n"
-"PO-Revision-Date: 2025-12-02 18:19+0200\n"
+"PO-Revision-Date: 2025-12-27 00:53+0100\n"
"Last-Translator: ~Jhellico \n"
"Language-Team: Holidays Localization Team\n"
"Language: uk\n"
@@ -27,6 +27,87 @@ msgstr ""
"X-Generator: Poedit 3.6\n"
"X-Source-Language: de\n"
+msgid "Weihnachtsferien"
+msgstr "Weihnachtsferien"
+
+msgid "Halbjahrespause"
+msgstr "Halbjahrespause"
+
+msgid "Frühjahrsferien"
+msgstr "Frühjahrsferien"
+
+msgid "Himmelfahrt/Pfingsten"
+msgstr "Himmelfahrt/Pfingsten"
+
+msgid "Sommerferien"
+msgstr "Sommerferien"
+
+msgid "Herbstferien"
+msgstr "Herbstferien"
+
+msgid "Brückentag"
+msgstr "Brückentag"
+
+msgid "Osterferien"
+msgstr "Osterferien"
+
+msgid "Pfingsten"
+msgstr "Pfingsten"
+
+msgid "Halbjahresferien"
+msgstr "Halbjahresferien"
+
+msgid "Tag nach Himmelfahrt"
+msgstr "Tag nach Himmelfahrt"
+
+msgid "Tag vor dem 03. Oktober"
+msgstr "Tag vor dem 03. Oktober"
+
+msgid "Tag vor dem 01. Mai"
+msgstr "Tag vor dem 01. Mai"
+
+msgid "Tage nach dem 03. Oktober"
+msgstr "Tage nach dem 03. Oktober"
+
+msgid "Fastnachtsferien"
+msgstr "Fastnachtsferien"
+
+msgid "Pfingstferien"
+msgstr "Pfingstferien"
+
+msgid "Winterferien"
+msgstr "Winterferien"
+
+msgid "Schulfreier Tag"
+msgstr "Schulfreier Tag"
+
+msgid "Himmelfahrt"
+msgstr "Himmelfahrt"
+
+msgid "Unterrichtsfreier Tag"
+msgstr "Unterrichtsfreier Tag"
+
+msgid "Beweglicher Ferientag"
+msgstr "Beweglicher Ferientag"
+
+msgid "Tage um Allerheiligen"
+msgstr "Tage um Allerheiligen"
+
+msgid "Unterrichtsfreier Tag nach AZVO"
+msgstr "Unterrichtsfreier Tag nach AZVO"
+
+msgid "Unterrichtsfreie Tage"
+msgstr "Unterrichtsfreie Tage"
+
+msgid "Zusätzliche feststehende Ferientage"
+msgstr "Zusätzliche feststehende Ferientage"
+
+msgid "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+msgstr "Ferien in Verbindung mit dem 1. Mai und Himmelfahrt"
+
+msgid "Variabler Ferientag"
+msgstr "Variabler Ferientag"
+
#. New Year's Day.
msgid "Neujahr"
msgstr "Новий рік"
diff --git a/tests/countries/test_germany.py b/tests/countries/test_germany.py
index 695d089f41..7b01e1c013 100644
--- a/tests/countries/test_germany.py
+++ b/tests/countries/test_germany.py
@@ -356,6 +356,249 @@ def test_l10n_default(self):
("2022-12-26", "Zweiter Weihnachtstag"),
)
+
+class TestGermanySaarlandSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ # 2025 Christmas range spans 2025->2026. Ensure per-year population.
+ h_2025 = Germany(years=2025, subdiv="SL", categories=("school",))
+ self.assertIn("2025-12-22", h_2025)
+ self.assertEqual(h_2025["2025-12-22"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="SL", categories=("school",))
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", h_2026)
+
+ def test_key_2026_ranges(self):
+ h = Germany(years=2026, subdiv="SL", categories=("school",))
+ self.assertIn("2026-02-16", h)
+ self.assertEqual(h["2026-02-16"], "Fastnachtsferien")
+ self.assertIn("2026-04-07", h)
+ self.assertEqual(h["2026-04-07"], "Osterferien")
+ self.assertIn("2026-06-29", h)
+ self.assertEqual(h["2026-06-29"], "Sommerferien")
+ self.assertIn("2026-08-07", h)
+ self.assertEqual(h["2026-08-07"], "Sommerferien")
+ self.assertIn("2026-10-05", h)
+ self.assertEqual(h["2026-10-05"], "Herbstferien")
+
+ def test_2029_and_2030_ranges(self):
+ h_2029 = Germany(years=2029, subdiv="SL", categories=("school",))
+ self.assertIn("2029-05-22", h_2029)
+ self.assertEqual(h_2029["2029-05-22"], "Pfingstferien")
+ self.assertIn("2029-07-16", h_2029)
+ self.assertEqual(h_2029["2029-07-16"], "Sommerferien")
+ self.assertIn("2029-12-21", h_2029)
+ self.assertEqual(h_2029["2029-12-21"], "Weihnachtsferien")
+
+ h_2030 = Germany(years=2030, subdiv="SL", categories=("school",))
+ self.assertIn("2030-01-01", h_2030)
+ self.assertEqual(h_2030["2030-01-01"], "Weihnachtsferien")
+ self.assertIn("2030-02-25", h_2030)
+ self.assertEqual(h_2030["2030-02-25"], "Fastnachtsferien")
+ self.assertIn("2030-07-22", h_2030)
+ self.assertEqual(h_2030["2030-07-22"], "Sommerferien")
+
+
+class TestGermanyThuringiaSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ # 2025 Christmas range spans 2025->2026. Ensure per-year population.
+ h_2025 = Germany(years=2025, subdiv="TH", categories=("school",))
+ self.assertIn("2025-12-22", h_2025)
+ self.assertEqual(h_2025["2025-12-22"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="TH", categories=("school",))
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", h_2026)
+
+ def test_key_2026_ranges(self):
+ h = Germany(years=2026, subdiv="TH", categories=("school",))
+ self.assertIn("2026-02-16", h)
+ self.assertEqual(h["2026-02-16"], "Winterferien")
+ self.assertIn("2026-04-07", h)
+ self.assertEqual(h["2026-04-07"], "Osterferien")
+ self.assertIn("2026-05-15", h)
+ self.assertEqual(h["2026-05-15"], "Schulfreier Tag")
+ self.assertIn("2026-07-04", h)
+ self.assertEqual(h["2026-07-04"], "Sommerferien")
+
+ def test_2027_and_2030_ranges(self):
+ h_2027 = Germany(years=2027, subdiv="TH", categories=("school",))
+ self.assertIn("2027-02-01", h_2027)
+ self.assertEqual(h_2027["2027-02-01"], "Winterferien")
+ self.assertIn("2027-07-10", h_2027)
+ self.assertEqual(h_2027["2027-07-10"], "Sommerferien")
+
+ h_2030 = Germany(years=2030, subdiv="TH", categories=("school",))
+ self.assertIn("2030-01-01", h_2030)
+ self.assertEqual(h_2030["2030-01-01"], "Weihnachtsferien")
+ self.assertIn("2030-05-31", h_2030)
+ self.assertEqual(h_2030["2030-05-31"], "Schulfreier Tag")
+
+
+class TestGermanySchleswigHolsteinSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ h_2025 = Germany(years=2025, subdiv="SH", categories=("school",))
+ self.assertIn("2025-12-19", h_2025)
+ self.assertEqual(h_2025["2025-12-19"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="SH", categories=("school",))
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-19", h_2026)
+
+ def test_key_2026_ranges(self):
+ h = Germany(years=2026, subdiv="SH", categories=("school",))
+ self.assertIn("2026-03-26", h)
+ self.assertEqual(h["2026-03-26"], "Osterferien")
+ self.assertIn("2026-05-15", h)
+ self.assertEqual(h["2026-05-15"], "Himmelfahrt")
+ self.assertIn("2026-07-04", h)
+ self.assertEqual(h["2026-07-04"], "Sommerferien")
+
+ def test_2028_and_2030_ranges(self):
+ h_2028 = Germany(years=2028, subdiv="SH", categories=("school",))
+ self.assertIn("2028-06-24", h_2028)
+ self.assertEqual(h_2028["2028-06-24"], "Sommerferien")
+
+ h_2030 = Germany(years=2030, subdiv="SH", categories=("school",))
+ self.assertIn("2030-07-08", h_2030)
+ self.assertEqual(h_2030["2030-07-08"], "Sommerferien")
+ self.assertIn("2030-05-31", h_2030)
+ self.assertEqual(h_2030["2030-05-31"], "Himmelfahrt")
+
+
+class TestGermanySaxonySchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ h_2025 = Germany(years=2025, subdiv="SN", categories=("school",))
+ self.assertIn("2025-12-22", h_2025)
+ self.assertEqual(h_2025["2025-12-22"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="SN", categories=("school",))
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", h_2026)
+
+ def test_key_2026_ranges(self):
+ h = Germany(years=2026, subdiv="SN", categories=("school",))
+ self.assertIn("2026-02-09", h)
+ self.assertEqual(h["2026-02-09"], "Winterferien")
+ self.assertIn("2026-04-03", h)
+ self.assertEqual(h["2026-04-03"], "Osterferien")
+ self.assertIn("2026-07-04", h)
+ self.assertEqual(h["2026-07-04"], "Sommerferien")
+ self.assertIn("2026-05-15", h)
+ self.assertEqual(h["2026-05-15"], "Unterrichtsfreier Tag")
+
+ def test_2027_and_2029_ranges(self):
+ h_2027 = Germany(years=2027, subdiv="SN", categories=("school",))
+ self.assertIn("2027-05-15", h_2027)
+ self.assertEqual(h_2027["2027-05-15"], "Pfingstferien")
+ self.assertIn("2027-07-10", h_2027)
+ self.assertEqual(h_2027["2027-07-10"], "Sommerferien")
+
+ h_2029 = Germany(years=2029, subdiv="SN", categories=("school",))
+ self.assertIn("2029-03-29", h_2029)
+ self.assertEqual(h_2029["2029-03-29"], "Osterferien")
+ self.assertIn("2029-07-21", h_2029)
+ self.assertEqual(h_2029["2029-07-21"], "Sommerferien")
+
+
+class TestGermanySaxonyAnhaltSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ h_2025 = Germany(years=2025, subdiv="ST", categories=("school",))
+ self.assertIn("2025-12-22", h_2025)
+ self.assertEqual(h_2025["2025-12-22"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="ST", categories=("school",))
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", h_2026)
+
+ def test_key_2026_ranges(self):
+ h = Germany(years=2026, subdiv="ST", categories=("school",))
+ self.assertIn("2026-01-31", h)
+ self.assertEqual(h["2026-01-31"], "Winterferien")
+ self.assertIn("2026-03-30", h)
+ self.assertEqual(h["2026-03-30"], "Osterferien")
+ self.assertIn("2026-05-26", h)
+ self.assertEqual(h["2026-05-26"], "Pfingstferien")
+ self.assertIn("2026-07-04", h)
+ self.assertEqual(h["2026-07-04"], "Sommerferien")
+
+ def test_2028_and_2029_ranges(self):
+ h_2028 = Germany(years=2028, subdiv="ST", categories=("school",))
+ self.assertIn("2028-06-03", h_2028)
+ self.assertEqual(h_2028["2028-06-03"], "Pfingstferien")
+ self.assertIn("2028-10-02", h_2028)
+ self.assertEqual(h_2028["2028-10-02"], "Beweglicher Ferientag")
+
+ h_2029 = Germany(years=2029, subdiv="ST", categories=("school",))
+ self.assertIn("2029-04-30", h_2029)
+ self.assertEqual(h_2029["2029-04-30"], "Beweglicher Ferientag")
+ self.assertIn("2029-05-11", h_2029)
+ self.assertEqual(h_2029["2029-05-11"], "Pfingstferien")
+
+
+class TestGermanyHamburgSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year(self):
+ # 2025 Christmas range spans 2025->2026. Ensure per-year population.
+ h_2025 = Germany(years=2025, subdiv="HH", categories=("school",))
+ self.assertIn("2025-12-17", h_2025)
+ self.assertEqual(h_2025["2025-12-17"], "Weihnachtsferien")
+
+ h_2026 = Germany(years=2026, subdiv="HH", categories=("school",))
+ # 2026 object should include 2026-01-01 but not 2025-12-17
+ self.assertIn("2026-01-01", h_2026)
+ self.assertEqual(h_2026["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-17", h_2026)
+
+ def test_halfyear_and_spring_2026(self):
+ h = Germany(years=2026, subdiv="HH", categories=("school",))
+ self.assertIn("2026-01-30", h)
+ self.assertEqual(h["2026-01-30"], "Halbjahrespause")
+ self.assertIn("2026-03-02", h)
+ self.assertEqual(h["2026-03-02"], "Frühjahrsferien")
+
+ def test_himmelfahrt_pfingsten_and_summer_2026(self):
+ h = Germany(years=2026, subdiv="HH", categories=("school",))
+ self.assertIn("2026-05-11", h)
+ self.assertEqual(h["2026-05-11"], "Himmelfahrt/Pfingsten")
+ self.assertIn("2026-07-09", h)
+ self.assertEqual(h["2026-07-09"], "Sommerferien")
+ self.assertIn("2026-08-19", h)
+ self.assertEqual(h["2026-08-19"], "Sommerferien")
+
+ def test_default_categories_excludes_school(self):
+ # If no categories specified, school category should not be present.
+ h = Germany(years=2026, subdiv="HH")
+ self.assertNotIn("2026-07-09", h)
+
def test_l10n_en_us(self):
self.assertLocalizedHolidays(
"en_US",
@@ -430,3 +673,382 @@ def test_l10n_uk(self):
("2022-12-25", "Перший день Різдва"),
("2022-12-26", "Другий день Різдва"),
)
+
+
+class TestGermanyBadenWuerttembergSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_summer_and_christmas_2025(self):
+ h = Germany(years=2025, subdiv="BW", categories=("school",))
+ self.assertIn("2025-07-31", h)
+ self.assertEqual(h["2025-07-31"], "Sommerferien")
+ self.assertIn("2025-12-22", h)
+ self.assertEqual(h["2025-12-22"], "Weihnachtsferien")
+
+ def test_2026_ranges(self):
+ h = Germany(years=2026, subdiv="BW", categories=("school",))
+ self.assertIn("2026-03-30", h)
+ self.assertEqual(h["2026-03-30"], "Osterferien")
+ self.assertIn("2026-05-26", h)
+ self.assertEqual(h["2026-05-26"], "Pfingstferien")
+
+
+class TestGermanyBayernSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_2025_2026(self):
+ h1 = Germany(years=2025, subdiv="BY", categories=("school",))
+ self.assertIn("2025-12-22", h1)
+ self.assertEqual(h1["2025-12-22"], "Weihnachtsferien")
+
+ h2 = Germany(years=2026, subdiv="BY", categories=("school",))
+ self.assertIn("2026-01-05", h2)
+ self.assertEqual(h2["2026-01-05"], "Weihnachtsferien")
+
+ def test_spring_and_summer_2026(self):
+ h = Germany(years=2026, subdiv="BY", categories=("school",))
+ self.assertIn("2026-02-16", h)
+ self.assertEqual(h["2026-02-16"], "Frühjahrsferien")
+ self.assertIn("2026-08-03", h)
+ self.assertEqual(h["2026-08-03"], "Sommerferien")
+
+
+class TestGermanyBerlinSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_and_winter_2025_2026(self):
+ h = Germany(years=2025, subdiv="BE", categories=("school",))
+ self.assertIn("2025-12-22", h)
+ self.assertEqual(h["2025-12-22"], "Weihnachtsferien")
+
+
+class TestGermanyBrandenburgSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ g25 = Germany(years=2025, subdiv="BB", categories=("school",))
+ self.assertIn("2025-12-22", g25)
+ self.assertEqual(g25["2025-12-22"], "Weihnachtsferien")
+
+ g26 = Germany(years=2026, subdiv="BB", categories=("school",))
+ # 2026 object should include the 2026 portion of Christmas but not 2025-12-22
+ self.assertIn("2026-01-01", g26)
+ self.assertEqual(g26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", g26)
+
+ def test_spring_and_pfingsten_2026(self):
+ g = Germany(years=2026, subdiv="BB", categories=("school",))
+ self.assertIn("2026-02-02", g)
+ self.assertEqual(g["2026-02-02"], "Winterferien")
+ self.assertIn("2026-03-30", g)
+ self.assertEqual(g["2026-03-30"], "Osterferien")
+ self.assertIn("2026-05-26", g)
+ self.assertEqual(g["2026-05-26"], "Pfingsten")
+ # Variable days
+ self.assertIn("2026-05-13", g)
+ self.assertIn("2026-05-15", g)
+ self.assertIn("2026-05-18", g)
+
+ def test_summer_and_autumn_2026(self):
+ g = Germany(years=2026, subdiv="BB", categories=("school",))
+ self.assertIn("2026-07-09", g)
+ self.assertEqual(g["2026-07-09"], "Sommerferien")
+ self.assertIn("2026-10-19", g)
+ self.assertEqual(g["2026-10-19"], "Herbstferien")
+
+ def test_variable_days_2028_2029(self):
+ g28 = Germany(years=2028, subdiv="BB", categories=("school",))
+ self.assertIn("2028-05-26", g28)
+ self.assertIn("2028-10-30", g28)
+
+ g29 = Germany(years=2029, subdiv="BB", categories=("school",))
+ self.assertIn("2029-04-30", g29)
+ self.assertIn("2029-05-11", g29)
+ self.assertIn("2029-05-22", g29)
+
+
+class TestGermanyBremenSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ b25 = Germany(years=2025, subdiv="HB", categories=("school",))
+ self.assertIn("2025-12-22", b25)
+ self.assertEqual(b25["2025-12-22"], "Weihnachtsferien")
+
+ b26 = Germany(years=2026, subdiv="HB", categories=("school",))
+ self.assertIn("2026-01-01", b26)
+ self.assertEqual(b26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", b26)
+
+ def test_halfyear_and_easter_2026(self):
+ b = Germany(years=2026, subdiv="HB", categories=("school",))
+ self.assertIn("2026-02-02", b)
+ self.assertEqual(b["2026-02-02"], "Halbjahresferien")
+ self.assertIn("2026-03-23", b)
+ self.assertEqual(b["2026-03-23"], "Osterferien")
+
+ def test_himmelfahrt_pfingsten_and_summer_2026(self):
+ b = Germany(years=2026, subdiv="HB", categories=("school",))
+ self.assertIn("2026-05-15", b)
+ self.assertEqual(b["2026-05-15"], "Tag nach Himmelfahrt")
+ self.assertIn("2026-05-26", b)
+ self.assertEqual(b["2026-05-26"], "Pfingsten")
+ self.assertIn("2026-07-02", b)
+ self.assertEqual(b["2026-07-02"], "Sommerferien")
+
+ def test_autumn_and_christmas_2026_2027(self):
+ b = Germany(years=2026, subdiv="HB", categories=("school",))
+ self.assertIn("2026-10-12", b)
+ self.assertEqual(b["2026-10-12"], "Herbstferien")
+
+ b27 = Germany(years=2027, subdiv="HB", categories=("school",))
+ self.assertIn("2027-01-01", b27)
+ self.assertIn("2027-12-23", b27)
+
+ def test_special_days_2028_2029(self):
+ b28 = Germany(years=2028, subdiv="HB", categories=("school",))
+ self.assertIn("2028-10-02", b28)
+ self.assertEqual(b28["2028-10-02"], "Tag vor dem 03. Oktober")
+
+ b29 = Germany(years=2029, subdiv="HB", categories=("school",))
+ self.assertIn("2029-04-30", b29)
+ self.assertIn("2029-10-04", b29)
+
+ def test_summer_2030(self):
+ b30 = Germany(years=2030, subdiv="HB", categories=("school",))
+ self.assertIn("2030-07-11", b30)
+ self.assertEqual(b30["2030-07-11"], "Sommerferien")
+
+
+class TestGermanyHessenSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ h25 = Germany(years=2025, subdiv="HE", categories=("school",))
+ self.assertIn("2025-12-22", h25)
+ self.assertEqual(h25["2025-12-22"], "Weihnachtsferien")
+
+ h26 = Germany(years=2026, subdiv="HE", categories=("school",))
+ self.assertIn("2026-01-01", h26)
+ self.assertEqual(h26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", h26)
+
+ def test_easter_and_summer_2026(self):
+ h = Germany(years=2026, subdiv="HE", categories=("school",))
+ self.assertIn("2026-03-30", h)
+ self.assertEqual(h["2026-03-30"], "Osterferien")
+ self.assertIn("2026-06-29", h)
+ self.assertEqual(h["2026-06-29"], "Sommerferien")
+
+ def test_autumn_and_christmas_2026_2027(self):
+ h = Germany(years=2026, subdiv="HE", categories=("school",))
+ self.assertIn("2026-10-05", h)
+ self.assertEqual(h["2026-10-05"], "Herbstferien")
+
+ h27 = Germany(years=2027, subdiv="HE", categories=("school",))
+ self.assertIn("2027-12-23", h27)
+ self.assertEqual(h27["2027-12-23"], "Weihnachtsferien")
+
+ def test_ranges_through_2030(self):
+ h28 = Germany(years=2028, subdiv="HE", categories=("school",))
+ self.assertIn("2028-07-03", h28)
+ self.assertIn("2028-10-09", h28)
+
+ h29 = Germany(years=2029, subdiv="HE", categories=("school",))
+ self.assertIn("2029-07-16", h29)
+ self.assertIn("2029-10-15", h29)
+
+ h30 = Germany(years=2030, subdiv="HE", categories=("school",))
+ self.assertIn("2030-07-22", h30)
+
+
+class TestGermanyMecklenburgVorpommernSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ m25 = Germany(years=2025, subdiv="MV", categories=("school",))
+ self.assertIn("2025-12-20", m25)
+ self.assertEqual(m25["2025-12-20"], "Weihnachtsferien")
+
+ m26 = Germany(years=2026, subdiv="MV", categories=("school",))
+ self.assertIn("2026-01-01", m26)
+ self.assertEqual(m26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-20", m26)
+
+ def test_winter_easter_pfingsten_2026(self):
+ m = Germany(years=2026, subdiv="MV", categories=("school",))
+ self.assertIn("2026-02-09", m)
+ self.assertEqual(m["2026-02-09"], "Winterferien")
+ self.assertIn("2026-03-30", m)
+ self.assertEqual(m["2026-03-30"], "Osterferien")
+ self.assertIn("2026-05-22", m)
+ self.assertEqual(m["2026-05-22"], "Pfingstferien")
+ self.assertIn("2026-05-15", m)
+
+ def test_summer_and_autumn_2026(self):
+ m = Germany(years=2026, subdiv="MV", categories=("school",))
+ self.assertIn("2026-07-13", m)
+ self.assertEqual(m["2026-07-13"], "Sommerferien")
+ self.assertIn("2026-10-15", m)
+ self.assertEqual(m["2026-10-15"], "Herbstferien")
+
+ def test_variable_and_special_days_2027_2029(self):
+ m27 = Germany(years=2027, subdiv="MV", categories=("school",))
+ self.assertIn("2027-05-07", m27)
+ self.assertIn("2027-07-05", m27)
+
+ m29 = Germany(years=2029, subdiv="MV", categories=("school",))
+ self.assertIn("2029-03-09", m29)
+ self.assertIn("2029-04-30", m29)
+ self.assertIn("2029-05-11", m29)
+ self.assertIn("2029-06-18", m29)
+
+ def test_ranges_through_2030(self):
+ m30 = Germany(years=2030, subdiv="MV", categories=("school",))
+ self.assertIn("2030-04-17", m30)
+ self.assertIn("2030-07-01", m30)
+
+
+class TestGermanyNiedersachsenSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ n25 = Germany(years=2025, subdiv="NI", categories=("school",))
+ self.assertIn("2025-12-22", n25)
+ self.assertEqual(n25["2025-12-22"], "Weihnachtsferien")
+
+ n26 = Germany(years=2026, subdiv="NI", categories=("school",))
+ self.assertIn("2026-01-01", n26)
+ self.assertEqual(n26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", n26)
+
+ def test_halfyear_and_easter_2026(self):
+ n = Germany(years=2026, subdiv="NI", categories=("school",))
+ self.assertIn("2026-02-02", n)
+ self.assertEqual(n["2026-02-02"], "Halbjahresferien")
+ self.assertIn("2026-03-23", n)
+ self.assertEqual(n["2026-03-23"], "Osterferien")
+
+ def test_may_and_pfingsten_2026(self):
+ n = Germany(years=2026, subdiv="NI", categories=("school",))
+ self.assertIn("2026-05-15", n)
+ self.assertIn("2026-05-26", n)
+
+ def test_summer_and_autumn_2026(self):
+ n = Germany(years=2026, subdiv="NI", categories=("school",))
+ self.assertIn("2026-07-02", n)
+ self.assertIn("2026-10-12", n)
+
+ def test_ranges_through_2030(self):
+ n27 = Germany(years=2027, subdiv="NI", categories=("school",))
+ self.assertIn("2027-07-08", n27)
+ self.assertIn("2027-10-16", n27)
+
+ n29 = Germany(years=2029, subdiv="NI", categories=("school",))
+ self.assertIn("2029-07-19", n29)
+ self.assertIn("2029-10-04", n29)
+
+ n30 = Germany(years=2030, subdiv="NI", categories=("school",))
+ self.assertIn("2030-07-11", n30)
+
+
+class TestGermanyNordrheinWestfalenSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_christmas_cross_year_2025_2026(self):
+ w25 = Germany(years=2025, subdiv="NW", categories=("school",))
+ self.assertIn("2025-12-22", w25)
+ self.assertEqual(w25["2025-12-22"], "Weihnachtsferien")
+
+ w26 = Germany(years=2026, subdiv="NW", categories=("school",))
+ self.assertIn("2026-01-01", w26)
+ self.assertEqual(w26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", w26)
+
+ def test_summer_2026(self):
+ w = Germany(years=2026, subdiv="NW", categories=("school",))
+ self.assertIn("2026-07-20", w)
+ self.assertIn("2026-09-01", w)
+
+ def test_autumn_2026(self):
+ w = Germany(years=2026, subdiv="NW", categories=("school",))
+ self.assertIn("2026-10-17", w)
+ self.assertIn("2026-10-31", w)
+
+ def test_oster_and_pfingsten_2027(self):
+ w27 = Germany(years=2027, subdiv="NW", categories=("school",))
+ self.assertIn("2027-03-22", w27)
+ self.assertIn("2027-05-18", w27)
+
+ def test_ranges_through_2030(self):
+ w29 = Germany(years=2029, subdiv="NW", categories=("school",))
+ self.assertIn("2029-03-26", w29)
+ self.assertIn("2029-07-02", w29)
+ self.assertIn("2029-10-15", w29)
+
+ w30 = Germany(years=2030, subdiv="NW", categories=("school",))
+ self.assertIn("2030-04-15", w30)
+
+
+class TestGermanyRheinlandPfalzSchoolHolidays(CommonCountryTests, TestCase):
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass(Germany, with_subdiv_categories=True)
+
+ def test_summer_and_christmas_2025(self):
+ r25 = Germany(years=2025, subdiv="RP", categories=("school",))
+ self.assertIn("2025-07-07", r25)
+ self.assertEqual(r25["2025-07-07"], "Sommerferien")
+ self.assertIn("2025-12-22", r25)
+ self.assertEqual(r25["2025-12-22"], "Weihnachtsferien")
+
+ def test_2026_ranges(self):
+ r26 = Germany(years=2026, subdiv="RP", categories=("school",))
+ self.assertIn("2026-03-30", r26)
+ self.assertEqual(r26["2026-03-30"], "Osterferien")
+ self.assertIn("2026-06-29", r26)
+ self.assertEqual(r26["2026-06-29"], "Sommerferien")
+
+ def test_cross_year_christmas(self):
+ r26 = Germany(years=2026, subdiv="RP", categories=("school",))
+ self.assertIn("2026-01-01", r26)
+ self.assertEqual(r26["2026-01-01"], "Weihnachtsferien")
+ self.assertNotIn("2025-12-22", r26)
+
+ def test_ranges_through_2030(self):
+ r29 = Germany(years=2029, subdiv="RP", categories=("school",))
+ self.assertIn("2029-07-16", r29)
+ self.assertIn("2029-10-22", r29)
+
+ r30 = Germany(years=2030, subdiv="RP", categories=("school",))
+ self.assertIn("2030-01-01", r30)
+ self.assertIn("2030-04-15", r30)
+
+ h2 = Germany(years=2026, subdiv="BE", categories=("school",))
+ self.assertIn("2026-02-02", h2)
+ self.assertEqual(h2["2026-02-02"], "Winterferien")
+
+ def test_special_and_summer_2026(self):
+ h = Germany(years=2026, subdiv="BE", categories=("school",))
+ self.assertIn("2026-05-15", h)
+ self.assertEqual(h["2026-05-15"], "Unterrichtsfreier Tag nach AZVO")
+ self.assertIn("2026-07-09", h)
+ self.assertEqual(h["2026-07-09"], "Sommerferien")