| name | jollyday |
|---|---|
| description | A Java library for querying public holidays supporting 160+ countries with XML-based holiday calendar configuration |
Jollyday is a Java library to query public holidays. It currently supports over 160 countries. The holiday data is stored in XML files (one for each country) and will be read from the classpath.
- Supports 160+ countries with public holiday data
- ISO 3166-1 alpha-2 country code support
- ISO 3166-2 subdivision support (states, provinces, regions)
- Multiple holiday types: Fixed dates, moving holidays (Easter-based, Islamic calendar, etc.)
- XML-based configuration with validation via XSD
- Supports JAXB and Jackson for XML unmarshalling
- Java 17+ required
| Module | Description |
|---|---|
jollyday-core |
Core API, holiday data, parser implementations |
jollyday-jackson |
Jackson XML binding implementation |
jollyday-jaxb |
Jakarta XML Binding implementation |
jollyday-tests |
Integration and country-specific tests |
jollyday/
├── jollyday-core/
│ ├── src/main/java/de/focus_shift/jollyday/core/
│ │ ├── Holiday.java # Holiday value object
│ │ ├── HolidayManager.java # Main API entry point
│ │ ├── HolidayCalendar.java # Enum of all supported countries
│ │ ├── ManagerParameters.java # Configuration builder
│ │ ├── impl/ # Manager implementations
│ │ ├── parser/ # Holiday parsing API
│ │ │ └── impl/ # Parser implementations
│ │ └── spi/ # Holiday configuration interfaces
│ └── src/main/resources/
│ ├── holidays/ # Country holiday XML files
│ ├── descriptions/ # Localized holiday descriptions
│ ├── focus_shift.de/jollyday/ # XSD schema definition
│ └── jollyday.properties # Default configuration
├── jollyday-jackson/ # Jackson XML unmarshalling
├── jollyday-jaxb/ # JAXB XML unmarshalling
└── jollyday-tests/ # Test suite
| Type | Description | Examples |
|---|---|---|
| Fixed | Same calendar date every year | New Year (Jan 1), Christmas (Dec 25) |
| FixedWeekday | Specific weekday occurrence in month | Labor Day (first Monday in Sept) |
| ChristianHoliday | Easter-based moving holidays | Good Friday, Easter Monday, Ascension |
| IslamicHoliday | Islamic calendar holidays | Eid al-Fitr, Eid al-Adha |
| EthiopianOrthodoxHoliday | Ethiopian Orthodox holidays | Timkat, Meskel |
| RelativeToFixed | Relative to a fixed date | German Repentance Day (Wednesday before Nov 23) |
| RelativeToWeekdayInMonth | Relative to a moving holiday | Various country-specific holidays |
| Category | Description |
|---|---|
| Public Holiday | Official non-working days (paid time off) |
| Bank Holiday | Days when financial institutions are closed |
| Observance | Celebrations without official time off |
- ISO 3166-1 alpha-2: Country codes (e.g.,
DE,US,FR) - ISO 3166-2: Subdivision codes (e.g.,
DE-BYfor Bavaria, Germany)
<?xml version="1.0" encoding="UTF-8"?>
<Configuration hierarchy="[country_code]" description="[Country Name]"
xmlns="https://focus_shift.de/jollyday/schema/holiday"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://focus_shift.de/jollyday/schema/holiday https://focus_shift.de/jollyday/schema/holiday/holiday.xsd">
<Holidays>
<!-- National holidays -->
</Holidays>
<Sources>
<Source>https://en.wikipedia.org/wiki/Public_holidays_in_[Country]</Source>
<Source of="ISO 3166">https://www.iso.org/obp/ui/#iso:code:3166:[CODE]</Source>
</Sources>
</Configuration><Fixed month="JANUARY" day="1" descriptionPropertiesKey="NEW_YEAR"/>
<Fixed month="DECEMBER" day="25" validFrom="1990" descriptionPropertiesKey="CHRISTMAS"/><FixedWeekday which="FIRST" weekday="MONDAY" month="SEPTEMBER" descriptionPropertiesKey="LABOUR_DAY"/>
<FixedWeekday which="LAST" weekday="MONDAY" month="MAY" descriptionPropertiesKey="MEMORIAL_DAY"/>which: FIRST, SECOND, THIRD, FOURTH, LAST
<ChristianHoliday type="GOOD_FRIDAY"/>
<ChristianHoliday type="EASTER_MONDAY"/>
<ChristianHoliday type="ASCENSION_DAY"/>
<ChristianHoliday type="WHIT_MONDAY"/>
<ChristianHoliday type="CORPUS_CHRISTI"/><IslamicHoliday type="ID_AL_FITR"/>
<IslamicHoliday type="ID_UL_ADHA"/>
<IslamicHoliday type="NEWYEAR"/><RelativeToFixed descriptionPropertiesKey="REPENTANCE_PRAYER">
<Weekday>WEDNESDAY</Weekday>
<When>BEFORE</When>
<Date month="NOVEMBER" day="23"/>
</RelativeToFixed><SubConfigurations hierarchy="bw" description="Baden-Württemberg">
<Holidays>
<Fixed month="MARCH" day="19" descriptionPropertiesKey="ST_JOSEPH"/>
</Holidays>
</SubConfigurations>| Attribute | Description | Values |
|---|---|---|
month |
Month name | JANUARY, FEBRUARY, ... DECEMBER |
day |
Day of month | 1-31 |
weekday |
Day of week | MONDAY, TUESDAY, ... SUNDAY |
which |
Occurrence | FIRST, SECOND, THIRD, FOURTH, LAST |
validFrom |
Start year | e.g., 1990 |
validTo |
End year | e.g., 2020 |
descriptionPropertiesKey |
Description key | UPPERCASE_WITH_UNDERSCORES |
import de.focus_shift.jollyday.core.Holiday;
import de.focus_shift.jollyday.core.HolidayManager;
import de.focus_shift.jollyday.core.ManagerParameters;
import de.focus_shift.jollyday.core.HolidayCalendar;
import java.util.Set;
import java.time.Year;
// Get all German holidays for 2024
HolidayManager manager = HolidayManager.getInstance(ManagerParameters.create(HolidayCalendar.GERMANY));
Set<Holiday> holidays = manager.getHolidays(Year.of(2024));
// Check if a date is a holiday
boolean isHoliday = manager.isHoliday(LocalDate.of(2024, 12, 25));
// Get holidays for a subdivision (Baden-Württemberg)
boolean isHolidayInBW = manager.isHoliday(LocalDate.of(2024, 3, 19), "bw");Holiday holiday = holidays.iterator().next();
holiday.getDate(); // LocalDate
holiday getDescription(); // Holiday name
holiday.getDescription(Locale.GERMAN); // Localized name
holiday getType(); // HolidayType (PUBLIC_HOLIDAY, BANK_HOLIDAY, OBSERVANCE)Located in jollyday-core/src/main/resources/jollyday.properties:
manager.impl=de.focus_shift.jollyday.core.impl.DefaultHolidayManager
configuration.service.impl=de.focus_shift.jollyday.jackson.JacksonConfigurationServiceparser.impl.de.focus_shift.jollyday.core.spi.FixedHolidayConfiguration = de.focus_shift.jollyday.core.parser.impl.FixedParser
parser.impl.de.focus_shift.jollyday.core.spi.ChristianHolidayConfiguration = de.focus_shift.jollyday.core.parser.impl.ChristianHolidayParser
parser.impl.de.focus_shift.jollyday.core.spi.IslamicHolidayConfiguration = de.focus_shift.jollyday.core.parser.impl.IslamicHolidayParserManagerParameters params = ManagerParameters.create(HolidayCalendar.GERMANY);
params.setProperty("manager.impl", "de.focus_shift.jollyday.core.impl.SpecialHolidayManager");
HolidayManager manager = HolidayManager.getInstance(params);Located in jollyday-core/src/main/java/de/focus_shift/jollyday/core/HolidayCalendar.java:
- Organized alphabetically by ISO country code
- Each entry:
COUNTRY_NAME("ISO_CODE") - Grouped by starting letter on same line
public enum HolidayCalendar {
ANTARCTICA("AQ"), ALBANIA("AL"), ANDORRA("AD"), ARGENTINA("AR"), ...
GERMANY("DE"), GREECE("GR"), ...
UNITED_STATES("US"), ...
}All parsers implement HolidayParser:
public interface HolidayParser {
Set<Holiday> parse(HolidayConfiguration configuration);
}| Directory | Purpose |
|---|---|
holidays/ |
Country XML files (Holidays_de.xml, Holidays_us.xml) |
descriptions/ |
Localized holiday and country names |
descriptions/holiday_descriptions.properties |
English holiday names |
descriptions/holiday_descriptions_de.properties |
German holiday names |
descriptions/country_descriptions.properties |
English country names |
Location: .agents/skills/add-new-holiday-calendar/SKILL.md
Create XML holiday calendar configuration files for a new country or region. Covers:
- Root structure with namespace declarations
- Holiday types: Fixed, FixedWeekday, Christian, Islamic, RelativeToFixed
- Moving conditions and validity periods
- Regional/subdivision configurations
Location: .agents/skills/add-holiday-descriptions/SKILL.md
Add holiday description properties for localization. Covers:
- Base English descriptions in
holiday_descriptions.properties - Localized descriptions (de, el, fr, nl, pt, sv)
- Key naming conventions for holiday keys
- Common holiday keys reference
Location: .agents/skills/add-country-descriptions/SKILL.md
Add country description properties for localization. Covers:
- Base English descriptions in
country_descriptions.properties - Localized country descriptions (de, el, fr, nl, pt, sv)
- ISO 3166-1 alpha-2 country code conventions
- Multi-language localization examples
Location: .agents/skills/register-holiday-calendar/SKILL.md
Register a new holiday calendar in the HolidayCalendar enum. Covers:
- Alphabetical organization by ISO country code
- File location:
jollyday-core/src/main/java/de/focus_shift/jollyday/core/HolidayCalendar.java - Entry format:
COUNTRY_NAME("ISO_CODE")
Location: .agents/skills/write-holiday-tests/SKILL.md
Write country-specific holiday tests using CalendarCheckerApi. Covers:
- Test file location and naming conventions
- Assertion methods for all holiday types
- Testing regional/subdivision holidays
- Testing edge cases (moving conditions, historical changes)
Location: .agents/skills/add-subdivision/SKILL.md
Add regional/subdivision holiday configurations based on ISO 3166-2 codes. Covers:
- ISO 3166-2 subdivision codes and format
- SubConfigurations XML structure
- Nested subdivisions (cities within states)
- Validity periods for regional holidays
- Testing subdivisions with CalendarCheckerApi
| Component | Version |
|---|---|
| Java | 17+ |
| Maven | 3.8.5+ |
| JUnit | 6.0.3+ |
| Jackson/JAXB | As defined in POM |
- Schema XSD:
jollyday-core/src/main/resources/focus_shift.de/jollyday/schema/holiday/holiday.xsd - GitHub: https://github.com/focus-shift/jollyday
- Maven Central: https://central.sonatype.com/artifact/de.focus-shift/jollyday-core
- Javadoc: https://www.javadoc.io/doc/de.focus-shift/jollyday-core
- Issues: https://github.com/focus-shift/jollyday/issues
- Discussions: https://github.com/focus-shift/jollyday/discussions
Apache License, Version 2.0