Repository: focus-shift/jollyday
Pull request #811 (2025-07-16 13:08:44)

712 base jdk 17
<!--

Thanks for contributing.
Please review the following notes before submitting you pull request.

Please look for other issues or pull requests which already work on this topic. Is somebody already on it? Do you need to synchronize?

# Security Vulnerabilities

🛑 STOP! 🛑 If your contribution fixes a security vulnerability, please do not submit it.
Instead, please write an E-Mail to to one of the maintainer with all the information
to recreate the security vulnerability.

# Describing Your Changes

If, having reviewed the notes above, you're ready to submit your pull request, please
provide a brief description of the proposed changes.

If they:
 🐞 fix a bug, please describe the broken behaviour and how the changes fix it.
    Please label with 'type: bug' and 'status: new'
    
 🎁 make an enhancement, please describe the new functionality and why you believe it's useful.
    Please label with 'type: enhancement' and 'status: new'
 
If your pull request relates to any existing issues,
please reference them by using the issue number prefixed with #.

-->



Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d494ff2a..a0aeee54 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,7 +17,7 @@ jobs:
     name: Build
     strategy:
       matrix:
-        java: [ '11', '17', '21', '24' ]
+        java: [ '17', '21', '24' ]
         os: [ 'ubuntu-24.04', 'macos-14', 'windows-2022' ]
     runs-on: ${{ matrix.os }}
     steps:
@@ -41,13 +41,11 @@ jobs:
         uses: actions/checkout@v4
         with:
           fetch-depth: 0
-      - name: Set up JDK 11 and 17
+      - name: Set up JDK 17
         uses: actions/setup-java@v4
         with:
           distribution: 'temurin'
-          java-version: |
-            11
-            17
+          java-version-file: ".tool-versions"
           cache: 'maven'
       - name: Run tests with JaxB
         run: >
diff --git a/.tool-versions b/.tool-versions
index 9f2ba5f9..8d6041de 100644
--- a/.tool-versions
+++ b/.tool-versions
@@ -1,1 +1,1 @@
-java temurin-11.0.27+6
+java temurin-17.0.15+6
diff --git a/README.md b/README.md
index 104abefe..b22392cf 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ Jollyday is a java library to query public holidays. Currently, we support **ove
 
 ## How to use it
 
-**Jollyday** is based on **Java 11** and can be used directly as dependency via maven or gradle e.g.
+**Jollyday** is based on **Java 17** and can be used directly as dependency via maven or gradle e.g.
 The calculation basis of the public holidays for each country is based on a xml file and will be mapped via Jakarta XML Binding or Jackson.
 If you already use one of these libraries in your project than just use the specific jollyday dependency.
 
@@ -360,7 +360,7 @@ If you want to raise an **issue or bug** you can create a [new issue](https://gi
 
 ### Requirements
 
-* [JDK 11](https://openjdk.java.net/install/)
+* [JDK 17](https://openjdk.java.net/install/)
 
 ### Architecture decision record (ADR)
 
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/impl/DefaultHolidayManager.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/impl/DefaultHolidayManager.java
index 217c0771..bc6a36b7 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/impl/DefaultHolidayManager.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/impl/DefaultHolidayManager.java
@@ -219,8 +219,7 @@ public class DefaultHolidayManager extends HolidayManager {
     try {
       final Method[] declaredMethods = config.getClass().getDeclaredMethods();
       for (Method declaredMethod : declaredMethods) {
-        if (declaredMethod.getGenericReturnType() instanceof ParameterizedType) {
-          final ParameterizedType parameterizedType = (ParameterizedType) declaredMethod.getGenericReturnType();
+        if (declaredMethod.getGenericReturnType() instanceof ParameterizedType parameterizedType) {
           final Type actualTypeArgument = parameterizedType.getActualTypeArguments()[0];
           final List<?> holidays = (List<?>) declaredMethod.invoke(config);
           if (!holidays.isEmpty()) {
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/functions/FindWeekDayRelativeToDate.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/functions/FindWeekDayRelativeToDate.java
index 13520951..47f9d8a1 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/functions/FindWeekDayRelativeToDate.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/functions/FindWeekDayRelativeToDate.java
@@ -39,20 +39,11 @@ public class FindWeekDayRelativeToDate implements Function<FixedWeekdayRelativeT
    * @return the day moved to the weekday and in the direction as specified
    */
   private LocalDate moveDateToFirstOccurrenceOfWeekday(final FixedWeekdayRelativeToFixed fixedWeekdayRelativeToFixed, final LocalDate day) {
-    final TemporalAdjuster adjuster;
-    switch (fixedWeekdayRelativeToFixed.when()) {
-      case AFTER:
-        adjuster = next(fixedWeekdayRelativeToFixed.weekday());
-        break;
-      case BEFORE:
-        adjuster = previous(fixedWeekdayRelativeToFixed.weekday());
-        break;
-      case CLOSEST:
-        adjuster = closest(fixedWeekdayRelativeToFixed.weekday());
-        break;
-      default:
-        throw new IllegalArgumentException("Unsupported relative adjustment: " + fixedWeekdayRelativeToFixed.when());
-    }
+    final TemporalAdjuster adjuster = switch (fixedWeekdayRelativeToFixed.when()) {
+      case AFTER -> next(fixedWeekdayRelativeToFixed.weekday());
+      case BEFORE -> previous(fixedWeekdayRelativeToFixed.weekday());
+      case CLOSEST -> closest(fixedWeekdayRelativeToFixed.weekday());
+    };
     return day.with(adjuster);
   }
 
@@ -66,16 +57,12 @@ public class FindWeekDayRelativeToDate implements Function<FixedWeekdayRelativeT
     if (fixedWeekdayRelativeToFixed.when() == Relation.CLOSEST) {
       return 0;
     }
-    switch (fixedWeekdayRelativeToFixed.which()) {
-      case SECOND:
-        return 7;
-      case THIRD:
-        return 14;
-      case FOURTH:
-        return 21;
-      default:
-        return 0;
-    }
+    return switch (fixedWeekdayRelativeToFixed.which()) {
+      case SECOND -> 7;
+      case THIRD -> 14;
+      case FOURTH -> 21;
+      default -> 0;
+    };
   }
 
   /**
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/ChristianHolidayParser.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/ChristianHolidayParser.java
index d0b1d612..cc270e42 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/ChristianHolidayParser.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/ChristianHolidayParser.java
@@ -28,60 +28,23 @@ public class ChristianHolidayParser implements HolidayParser {
 
         final LocalDate easterSunday = new CalculateEasterSunday(year).apply(christianHolidayConfiguration.chronology());
 
-        final LocalDate actualDate;
-        switch (christianHolidayConfiguration.type()) {
-          case EASTER:
-            actualDate = easterSunday;
-            break;
-          case CLEAN_MONDAY:
-          case SHROVE_MONDAY:
-            actualDate = easterSunday.minusDays(48);
-            break;
-          case MARDI_GRAS:
-          case CARNIVAL:
-            actualDate = easterSunday.minusDays(47);
-            break;
-          case ASH_WEDNESDAY:
-            actualDate = easterSunday.minusDays(46);
-            break;
-          case MAUNDY_THURSDAY:
-            actualDate = easterSunday.minusDays(3);
-            break;
-          case GOOD_FRIDAY:
-            actualDate = easterSunday.minusDays(2);
-            break;
-          case EASTER_SATURDAY:
-            actualDate = easterSunday.minusDays(1);
-            break;
-          case EASTER_MONDAY:
-            actualDate = easterSunday.plusDays(1);
-            break;
-          case EASTER_TUESDAY:
-            actualDate = easterSunday.plusDays(2);
-            break;
-          case GENERAL_PRAYER_DAY:
-            actualDate = easterSunday.plusDays(26);
-            break;
-          case ASCENSION_DAY:
-            actualDate = easterSunday.plusDays(39);
-            break;
-          case PENTECOST:
-          case WHIT_SUNDAY:
-            actualDate = easterSunday.plusDays(49);
-            break;
-          case WHIT_MONDAY:
-          case PENTECOST_MONDAY:
-            actualDate = easterSunday.plusDays(50);
-            break;
-          case CORPUS_CHRISTI:
-            actualDate = easterSunday.plusDays(60);
-            break;
-          case SACRED_HEART:
-            actualDate = easterSunday.plusDays(68);
-            break;
-          default:
-            throw new IllegalArgumentException("Unknown christian holiday type " + christianHolidayConfiguration.type());
-        }
+        final LocalDate actualDate = switch (christianHolidayConfiguration.type()) {
+          case EASTER -> easterSunday;
+          case CLEAN_MONDAY, SHROVE_MONDAY -> easterSunday.minusDays(48);
+          case MARDI_GRAS, CARNIVAL -> easterSunday.minusDays(47);
+          case ASH_WEDNESDAY -> easterSunday.minusDays(46);
+          case MAUNDY_THURSDAY -> easterSunday.minusDays(3);
+          case GOOD_FRIDAY -> easterSunday.minusDays(2);
+          case EASTER_SATURDAY -> easterSunday.minusDays(1);
+          case EASTER_MONDAY -> easterSunday.plusDays(1);
+          case EASTER_TUESDAY -> easterSunday.plusDays(2);
+          case GENERAL_PRAYER_DAY -> easterSunday.plusDays(26);
+          case ASCENSION_DAY -> easterSunday.plusDays(39);
+          case PENTECOST, WHIT_SUNDAY -> easterSunday.plusDays(49);
+          case WHIT_MONDAY, PENTECOST_MONDAY -> easterSunday.plusDays(50);
+          case CORPUS_CHRISTI -> easterSunday.plusDays(60);
+          case SACRED_HEART -> easterSunday.plusDays(68);
+        };
 
         return new MoveDateRelative(actualDate).apply(christianHolidayConfiguration)
           .map(observedDate -> new CreateHoliday(actualDate, observedDate))
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/EthiopianOrthodoxHolidayParser.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/EthiopianOrthodoxHolidayParser.java
index 54ebab1c..8baf0dc6 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/EthiopianOrthodoxHolidayParser.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/EthiopianOrthodoxHolidayParser.java
@@ -25,20 +25,14 @@ public class EthiopianOrthodoxHolidayParser implements HolidayParser {
     return holidays.ethiopianOrthodoxHolidays().stream()
       .filter(new ValidLimitation(year))
       .flatMap(eoh -> {
-        final Stream<LocalDate> ethiopianHolidays;
-        switch (eoh.type()) {
-          case TIMKAT:
-            ethiopianHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(5, 10, CopticChronology.INSTANCE, 0).apply(year);
-            break;
-          case ENKUTATASH:
-            ethiopianHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 1, CopticChronology.INSTANCE, 0).apply(year);
-            break;
-          case MESKEL:
-            ethiopianHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 17, CopticChronology.INSTANCE, 0).apply(year);
-            break;
-          default:
-            throw new IllegalArgumentException("Unknown ethiopian orthodox holiday type " + eoh.type());
-        }
+        final Stream<LocalDate> ethiopianHolidays = switch (eoh.type()) {
+          case TIMKAT ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(5, 10, CopticChronology.INSTANCE, 0).apply(year);
+          case ENKUTATASH ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 1, CopticChronology.INSTANCE, 0).apply(year);
+          case MESKEL ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 17, CopticChronology.INSTANCE, 0).apply(year);
+        };
         return ethiopianHolidays.map(date -> new CreateHoliday(date).apply(eoh));
       })
       .collect(toList());
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/IslamicHolidayParser.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/IslamicHolidayParser.java
index 3d1c05f2..78e10354 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/IslamicHolidayParser.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/impl/IslamicHolidayParser.java
@@ -27,57 +27,38 @@ public class IslamicHolidayParser implements HolidayParser {
       .filter(new ValidLimitation(year))
       .flatMap(islamicHoliday -> {
 
-        final Stream<LocalDate> islamicHolidays;
-
-        switch (islamicHoliday.type()) {
-          case NEWYEAR:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 1, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ASCHURA:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 10, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case RAMADAN_END:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 1, HijrahChronology.INSTANCE, -1).apply(year);
-            break;
-          case ID_AL_FITR:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 1, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ID_AL_FITR_2:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 2, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ID_AL_FITR_3:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 3, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ARAFAAT:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 9, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ID_UL_ADHA:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 10, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ID_UL_ADHA_2:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 11, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case ID_UL_ADHA_3:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 12, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case LAILAT_AL_BARAT:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(8, 15, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case LAILAT_AL_MIRAJ:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(7, 27, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case LAILAT_AL_QADR:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(9, 27, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case MAWLID_AN_NABI:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(3, 12, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          case RAMADAN:
-            islamicHolidays = new CalculateRelativeDatesFromChronologyWithinGregorianYear(9, 1, HijrahChronology.INSTANCE, 0).apply(year);
-            break;
-          default:
-            throw new IllegalArgumentException("Unknown islamic holiday " + islamicHoliday.type());
-        }
+        final Stream<LocalDate> islamicHolidays = switch (islamicHoliday.type()) {
+          case NEWYEAR ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 1, HijrahChronology.INSTANCE, 0).apply(year);
+          case ASCHURA ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(1, 10, HijrahChronology.INSTANCE, 0).apply(year);
+          case RAMADAN_END ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 1, HijrahChronology.INSTANCE, -1).apply(year);
+          case ID_AL_FITR ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 1, HijrahChronology.INSTANCE, 0).apply(year);
+          case ID_AL_FITR_2 ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 2, HijrahChronology.INSTANCE, 0).apply(year);
+          case ID_AL_FITR_3 ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(10, 3, HijrahChronology.INSTANCE, 0).apply(year);
+          case ARAFAAT ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 9, HijrahChronology.INSTANCE, 0).apply(year);
+          case ID_UL_ADHA ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 10, HijrahChronology.INSTANCE, 0).apply(year);
+          case ID_UL_ADHA_2 ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 11, HijrahChronology.INSTANCE, 0).apply(year);
+          case ID_UL_ADHA_3 ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(12, 12, HijrahChronology.INSTANCE, 0).apply(year);
+          case LAILAT_AL_BARAT ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(8, 15, HijrahChronology.INSTANCE, 0).apply(year);
+          case LAILAT_AL_MIRAJ ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(7, 27, HijrahChronology.INSTANCE, 0).apply(year);
+          case LAILAT_AL_QADR ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(9, 27, HijrahChronology.INSTANCE, 0).apply(year);
+          case MAWLID_AN_NABI ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(3, 12, HijrahChronology.INSTANCE, 0).apply(year);
+          case RAMADAN ->
+            new CalculateRelativeDatesFromChronologyWithinGregorianYear(9, 1, HijrahChronology.INSTANCE, 0).apply(year);
+        };
 
         return islamicHolidays
           .map(date -> new DescribedDateHolder(islamicHoliday, date, new MoveDateRelative(date).apply(islamicHoliday).orElse(null)))
diff --git a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycle.java b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycle.java
index 984ef693..cea34dc1 100644
--- a/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycle.java
+++ b/jollyday-core/src/main/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycle.java
@@ -16,26 +16,16 @@ public class ValidCycle implements Predicate<Limited> {
 
   @Override
   public boolean test(final Limited limited) {
-    switch (limited.cycle()) {
-      case EVERY_YEAR:
-        return true;
-      case ODD_YEARS:
-        return year.getValue() % 2 != 0;
-      case EVEN_YEARS:
-        return year.getValue() % 2 == 0;
-      case TWO_YEARS:
-        return isValidWithReferenceYear(limited, Period.ofYears(2));
-      case THREE_YEARS:
-        return isValidWithReferenceYear(limited, Period.ofYears(3));
-      case FOUR_YEARS:
-        return isValidWithReferenceYear(limited, Period.ofYears(4));
-      case FIVE_YEARS:
-        return isValidWithReferenceYear(limited, Period.ofYears(5));
-      case SIX_YEARS:
-        return isValidWithReferenceYear(limited, Period.ofYears(6));
-      default:
-        throw new IllegalArgumentException("Cannot handle unknown cycle type '" + limited.cycle() + "'.");
-    }
+    return switch (limited.cycle()) {
+      case EVERY_YEAR -> true;
+      case ODD_YEARS -> year.getValue() % 2 != 0;
+      case EVEN_YEARS -> year.getValue() % 2 == 0;
+      case TWO_YEARS -> isValidWithReferenceYear(limited, Period.ofYears(2));
+      case THREE_YEARS -> isValidWithReferenceYear(limited, Period.ofYears(3));
+      case FOUR_YEARS -> isValidWithReferenceYear(limited, Period.ofYears(4));
+      case FIVE_YEARS -> isValidWithReferenceYear(limited, Period.ofYears(5));
+      case SIX_YEARS -> isValidWithReferenceYear(limited, Period.ofYears(6));
+    };
   }
 
   /**
diff --git a/pom.xml b/pom.xml
index 1636533d..7cb9ae0e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
 
   <properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-    <java.version>11</java.version>
+    <java.version>17</java.version>
 
     <tests.groups>!BenchmarkTest</tests.groups>
 


Test patch:
diff --git a/jollyday-core/src/test/java/de/focus_shift/jollyday/core/descriptions/CountryDescriptionsTest.java b/jollyday-core/src/test/java/de/focus_shift/jollyday/core/descriptions/CountryDescriptionsTest.java
index 523d2402..e468bd03 100644
--- a/jollyday-core/src/test/java/de/focus_shift/jollyday/core/descriptions/CountryDescriptionsTest.java
+++ b/jollyday-core/src/test/java/de/focus_shift/jollyday/core/descriptions/CountryDescriptionsTest.java
@@ -43,7 +43,7 @@ class CountryDescriptionsTest {
   }
 
   private void compareL1WithL2(ResourceBundle l1, ResourceBundle l2) {
-    final Locale locale = "".equals(l2.getLocale().getCountry()) ? Locale.ENGLISH : l2.getLocale();
+    final Locale locale = l2.getLocale().getCountry().isEmpty() ? Locale.ENGLISH : l2.getLocale();
     final Enumeration<String> keys = l1.getKeys();
     final Set<String> l2KeySet = new HashSet<>(list(l2.getKeys()));
     final StringBuilder misses = new StringBuilder();
@@ -53,7 +53,7 @@ class CountryDescriptionsTest {
         misses.append(locale).append(" misses ").append(propertyName).append('\n');
       }
     }
-    if (misses.length() > 0) {
+    if (!misses.isEmpty()) {
       fail(misses.toString());
     }
   }
diff --git a/jollyday-core/src/test/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycleTest.java b/jollyday-core/src/test/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycleTest.java
index c901771f..38d60f7b 100644
--- a/jollyday-core/src/test/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycleTest.java
+++ b/jollyday-core/src/test/java/de/focus_shift/jollyday/core/parser/predicates/ValidCycleTest.java
@@ -154,27 +154,14 @@ class ValidCycleTest {
   }
 
   private static int getModulo(Limited.YearCycle cycle) {
-    int modulo = 0;
-    switch (cycle) {
-      case TWO_YEARS:
-        modulo = 2;
-        break;
-      case THREE_YEARS:
-        modulo = 3;
-        break;
-      case FOUR_YEARS:
-        modulo = 4;
-        break;
-      case FIVE_YEARS:
-        modulo = 5;
-        break;
-      case SIX_YEARS:
-        modulo = 6;
-        break;
-      default:
-        throw new IllegalStateException("Unexpected value: " + cycle);
-    }
-    return modulo;
+    return switch (cycle) {
+      case TWO_YEARS -> 2;
+      case THREE_YEARS -> 3;
+      case FOUR_YEARS -> 4;
+      case FIVE_YEARS -> 5;
+      case SIX_YEARS -> 6;
+      default -> throw new IllegalStateException("Unexpected value: " + cycle);
+    };
   }
 
   @Property
diff --git a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/CalendarChecker.java b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/CalendarChecker.java
index d317e31e..c46e0366 100644
--- a/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/CalendarChecker.java
+++ b/jollyday-tests/src/test/java/de/focus_shift/jollyday/tests/CalendarChecker.java
@@ -199,7 +199,7 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
 
     clearProperties();
 
-    final HolidayManager holidayManager = HolidayManager.getInstance(create(checks.get(0).getCalendar()));
+    final HolidayManager holidayManager = HolidayManager.getInstance(create(checks.get(0).calendar()));
 
     for (HolidayCalendarCheck check : checks) {
       switch (check.category) {
@@ -220,28 +220,28 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
   private void checkByDate(final HolidayCalendarCheck check, final HolidayManager holidayManager) {
     final YearArbitrary yearArbitrary = createYearArbitrary();
 
-    for (final YearRange invalidRange : check.getInvalidRanges()) {
+    for (final YearRange invalidRange : check.invalidRanges()) {
       yearArbitrary
-        .between(invalidRange.getFrom().getValue(), invalidRange.getTo().getValue())
+        .between(invalidRange.from().getValue(), invalidRange.to().getValue())
         .forEachValue(year -> {
-            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.getSubdivisions());
-            final LocalDate dateToCheck = LocalDate.of(year.getValue(), check.getMonth(), check.getDay());
+            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.subdivisions());
+            final LocalDate dateToCheck = LocalDate.of(year.getValue(), check.month(), check.day());
             final LocalDate shiftLocalDate = shiftLocalDate(check, dateToCheck);
-            final Holiday holiday = new Holiday(shiftLocalDate, check.getPropertiesKey(), check.getHolidayType());
-            assertHolidayNotPresent(holidays, holiday, holidayManager, check.getSubdivisions());
+            final Holiday holiday = new Holiday(shiftLocalDate, check.propertiesKey(), check.holidayType());
+            assertHolidayNotPresent(holidays, holiday, holidayManager, check.subdivisions());
           }
         );
     }
 
-    for (final YearRange validRange : check.getValidRanges()) {
+    for (final YearRange validRange : check.validRanges()) {
       yearArbitrary
-        .between(validRange.getFrom().getValue(), validRange.getTo().getValue())
+        .between(validRange.from().getValue(), validRange.to().getValue())
         .forEachValue(year -> {
-            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.getSubdivisions());
-            final LocalDate dateToCheck = LocalDate.of(year.getValue(), check.getMonth(), check.getDay());
+            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.subdivisions());
+            final LocalDate dateToCheck = LocalDate.of(year.getValue(), check.month(), check.day());
             final LocalDate shiftLocalDate = shiftLocalDate(check, dateToCheck);
-            final Holiday holiday = new Holiday(shiftLocalDate, check.getPropertiesKey(), check.getHolidayType());
-            assertHolidayPresent(holidays, holiday, holidayManager, check.getSubdivisions());
+            final Holiday holiday = new Holiday(shiftLocalDate, check.propertiesKey(), check.holidayType());
+            assertHolidayPresent(holidays, holiday, holidayManager, check.subdivisions());
           }
         );
     }
@@ -274,11 +274,11 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
 
     LocalDate shiftedDate = date;
     for (WeekDayFromTo shift : check.validShifts) {
-      if (shift != null && date.getDayOfWeek().equals(shift.getFrom())) {
+      if (shift != null && date.getDayOfWeek().equals(shift.from())) {
         if (shift.adjuster == NEXT) {
-          shiftedDate = date.with(nextOrSame(shift.getTo()));
+          shiftedDate = date.with(nextOrSame(shift.to()));
         } else {
-          shiftedDate = date.with(previousOrSame(shift.getTo()));
+          shiftedDate = date.with(previousOrSame(shift.to()));
         }
       }
     }
@@ -289,32 +289,32 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
   private void checkByKey(final HolidayCalendarCheck check, final HolidayManager holidayManager) {
     final YearArbitrary yearArbitrary = createYearArbitrary();
 
-    for (final YearRange invalidRange : check.getInvalidRanges()) {
+    for (final YearRange invalidRange : check.invalidRanges()) {
       yearArbitrary
-        .between(invalidRange.getFrom().getValue(), invalidRange.getTo().getValue())
+        .between(invalidRange.from().getValue(), invalidRange.to().getValue())
         .forEachValue(year -> {
-            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.getSubdivisions());
+            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.subdivisions());
             assertThat(holidays)
               .isNotEmpty()
-              .filteredOn(holiday -> holiday.getPropertiesKey().equals(check.getPropertiesKey()))
+              .filteredOn(holiday -> holiday.getPropertiesKey().equals(check.propertiesKey()))
               .extracting(Holiday::getType)
-              .withFailMessage("Holiday '" + check.getPropertiesKey() + "' with holiday type '" + check.holidayType + "' in year '" + year + "' not found.")
-              .doesNotContain(check.getHolidayType());
+              .withFailMessage("Holiday '" + check.propertiesKey() + "' with holiday type '" + check.holidayType + "' in year '" + year + "' not found.")
+              .doesNotContain(check.holidayType());
           }
         );
     }
 
-    for (final YearRange validRange : check.getValidRanges()) {
+    for (final YearRange validRange : check.validRanges()) {
       yearArbitrary
-        .between(validRange.getFrom().getValue(), validRange.getTo().getValue())
+        .between(validRange.from().getValue(), validRange.to().getValue())
         .forEachValue(year -> {
-            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.getSubdivisions());
+            final Set<Holiday> holidays = holidayManager.getHolidays(year, check.subdivisions());
             assertThat(holidays)
               .isNotEmpty()
-              .filteredOn(holiday -> holiday.getPropertiesKey().equals(check.getPropertiesKey()))
+              .filteredOn(holiday -> holiday.getPropertiesKey().equals(check.propertiesKey()))
               .extracting(Holiday::getType)
-              .withFailMessage("Holiday '" + check.getPropertiesKey() + "' with holiday type '" + check.holidayType + "' in year '" + year + "' and in subdivision '" + Arrays.toString(check.getSubdivisions()) + "' not found.")
-              .contains(check.getHolidayType());
+              .withFailMessage("Holiday '" + check.propertiesKey() + "' with holiday type '" + check.holidayType + "' in year '" + year + "' and in subdivision '" + Arrays.toString(check.subdivisions()) + "' not found.")
+              .contains(check.holidayType());
           }
         );
     }
@@ -336,21 +336,15 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
     this.validShifts = new ArrayList<>();
   }
 
-  private static final class HolidayCalendarCheck {
+  private record HolidayCalendarCheck(
+    HolidayCalendar calendar, String propertiesKey, Month month, int day,
+    HolidayType holidayType, List<YearRange> validRanges,
+    List<YearRange> invalidRanges, List<WeekDayFromTo> validShifts,
+    String[] subdivisions, Category category
+  ) {
 
     private static final YearRange DEFAULT_YEAR_RANGE = new YearRange(Year.of(1900), Year.of(2500));
 
-    private final HolidayCalendar calendar;
-    private final List<YearRange> validRanges;
-    private final List<YearRange> invalidRanges;
-    private final List<WeekDayFromTo> validShifts;
-    private final Month month;
-    private final int day;
-    private final String propertiesKey;
-    private final HolidayType holidayType;
-    private final String[] subdivisions;
-    private final Category category;
-
     private HolidayCalendarCheck(
       HolidayCalendar calendar,
       String propertiesKey, Month month, int day, HolidayType holidayType,
@@ -368,92 +362,16 @@ public class CalendarChecker implements CalendarCheckerApi.Holiday, CalendarChec
       this.subdivisions = subdivisions;
       this.category = category;
     }
-
-    public HolidayCalendar getCalendar() {
-      return calendar;
-    }
-
-    public List<YearRange> getValidRanges() {
-      return validRanges;
-    }
-
-    public List<YearRange> getInvalidRanges() {
-      return invalidRanges;
-    }
-
-    public List<WeekDayFromTo> getValidShifts() {
-      return validShifts;
-    }
-
-    public Month getMonth() {
-      return month;
-    }
-
-    public int getDay() {
-      return day;
-    }
-
-    public String getPropertiesKey() {
-      return propertiesKey;
-    }
-
-    public HolidayType getHolidayType() {
-      return holidayType;
-    }
-
-    public String[] getSubdivisions() {
-      return subdivisions;
-    }
-
-    public Category getCategory() {
-      return category;
-    }
   }
 
-  private static final class YearRange {
-
-    private final Year from;
-    private final Year to;
-
-    private YearRange(final Year from, final Year to) {
+  private record YearRange(Year from, Year to) {
+    private YearRange {
       if (from != null && to != null) {
         Assertions.assertFalse(from.isAfter(to), "To must be greater than or equal to the from year.");
       }
-      this.from = from;
-      this.to = to;
-    }
-
-    public Year getFrom() {
-      return from;
-    }
-
-    public Year getTo() {
-      return to;
     }
   }
 
-  private static final class WeekDayFromTo {
-
-    private final DayOfWeek from;
-    private final DayOfWeek to;
-    private final Adjuster adjuster;
-
-    private WeekDayFromTo(final DayOfWeek from, final DayOfWeek to, final Adjuster adjuster) {
-      this.from = from;
-      this.to = to;
-      this.adjuster = adjuster;
-    }
-
-    public DayOfWeek getFrom() {
-      return from;
-    }
-
-    public DayOfWeek getTo() {
-      return to;
-    }
-
-    public Adjuster getAdjuster() {
-      return adjuster;
-    }
+  private record WeekDayFromTo(DayOfWeek from, DayOfWeek to, Adjuster adjuster) {
   }
 }