Skip to content

focus-shift/jollyday

Repository files navigation

Jollyday Build Status Coverage Maven Central Javadocs

Jollyday is a java library to query public holidays. Currently, we support over 90 countries.

How to use it

Jollyday is based on Java 11 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.

Maven (click to expand)

You need the core library, that defines all functionality and the api for you as developer.

<dependency>
  <groupId>de.focus-shift</groupId>
  <artifactId>jollyday-core</artifactId>
  <version>${version}</version>
</dependency>

XML-Binding libraries

Additionally, the XML-Binding library of your choice. At the moment we do support JAXB and Jackson, but in the future there could be more that these.

Jakarta XML Binding (JAXB)

<dependency>
  <groupId>de.focus-shift</groupId>
  <artifactId>jollyday-jaxb</artifactId>
  <version>${version}</version>
</dependency>

Jackson

<dependency>
  <groupId>de.focus-shift</groupId>
  <artifactId>jollyday-jackson</artifactId>
  <version>${version}</version>
</dependency>
Gradle (click to expand)

You need the core library, that defines all functionality and the api for you as developer.

implementation group: 'de.focus-shift', name: 'jollyday-core', version: '${version}'

XML-Binding libraries

Additionally, the XML-Binding library of your choice. At the moment we do support JAXB and Jackson, but in the future there could be more that these.

Jakarta XML Binding (JAXB)

implementation group: 'de.focus-shift', name: 'jollyday-jaxb', version: '${version}'

Jackson

implementation group: 'de.focus-shift', name: 'jollyday-jackson', version: '${version}'
with the Java Platform Module System (click to expand)

If you want to use Jollyday in a project that is modularized via java modules you need to require the de.focus_shift.jollyday.core module via

module your.application {
  ...
  requires de.focus_shift.jollyday.core;
  ...
}

Configuration

via jollyday.properties (click to expand)

Providing own properties

The configuration resides within the jollyday.properties and can be overridden by:

URLs
Specifying a comma separated list of URLs with the system property de.focus_shift.jollyday.config.urls which point to properties files to overload the basic properties.

-Dde.focus_shift.jollyday.config.urls=file:/some/path/new.properties,http://myserver/some/path/further.properties,jar:file:myLibrary.jar!/my.properties

Classes
Specifying a comma separated list of classes which implement the ConfigurationProvider interface with the system property de.focus_shift.jollyday.config.providers. This will overload the basic and the URL specified properties.

-Dde.focus_shift.jollyday.config.providers=some.package.name.MyConfigurationProvider,some.other.package.AnotherConfigurationProvider

URLs and Classes
The order of loading properties is Base -> URLs -> ConfigurationProvider.

Providing own implementations

Manager implementation
A manager implementation extends the abstract HolidayManager class and does the actual holiday parsing. The basic API properties are used to define the manager implementation class used for the specific country the manager is created for.

manager.impl=de.focus_shift.jollyday.core.impl.DefaultHolidayManager

This configuration defines a manager implementation class used as a default for every country. You can define a manager implementation on a per country base.

manager.impl=de.focus_shift.jollyday.core.impl.XMLManager
manager.impl.us=de.focus_shift.jollyday.core.impl.MyXMLManager

This will let the MyXMLManager class be used for calculating US holidays and the XMLManager for all other countries.

Parser implementation
A parser implementation is used for parsing the XML file content. There are several parsers configured depending on the class to parse the info from.

parser.impl.de.focus_shift.jollyday.core.spi.Fixed                       = de.focus_shift.jollyday.core.parser.impl.FixedParser
parser.impl.de.focus_shift.jollyday.core.spi.FixedWeekdayInMonth         = de.focus_shift.jollyday.core.parser.impl.FixedWeekdayInMonthParser
parser.impl.de.focus_shift.jollyday.core.spi.IslamicHoliday              = de.focus_shift.jollyday.core.parser.impl.IslamicHolidayParser
parser.impl.de.focus_shift.jollyday.core.spi.ChristianHoliday            = de.focus_shift.jollyday.core.parser.impl.ChristianHolidayParser
parser.impl.de.focus_shift.jollyday.core.spi.RelativeToFixed             = de.focus_shift.jollyday.core.parser.impl.RelativeToFixedParser
parser.impl.de.focus_shift.jollyday.core.spi.RelativeToWeekdayInMonth    = de.focus_shift.jollyday.core.parser.impl.RelativeToWeekdayInMonthParser
parser.impl.de.focus_shift.jollyday.core.spi.FixedWeekdayBetweenFixed    = de.focus_shift.jollyday.core.parser.impl.FixedWeekdayBetweenFixedParser
parser.impl.de.focus_shift.jollyday.core.spi.FixedWeekdayRelativeToFixed = de.focus_shift.jollyday.core.parser.impl.FixedWeekdayRelativeToFixedParser
parser.impl.de.focus_shift.jollyday.core.spi.EthiopianOrthodoxHoliday    = de.focus_shift.jollyday.core.parser.impl.EthiopianOrthodoxHolidayParser
parser.impl.de.focus_shift.jollyday.core.spi.RelativeToEasterSunday      = de.focus_shift.jollyday.core.parser.impl.RelativeToEasterSundayParser

The configuration property name starts with parser.impl and finishes with the XML class name. The value is the parser implementation class name which implements the HolidayParser interface.

Examples

Retrieve public holidays for a year (click to expand)

Returns all german public holidays in 2022

import de.focus_shift.jollyday.core.Holiday;
import de.focus_shift.jollyday.core.HolidayManager;
import de.focus_shift.jollyday.core.ManagerParameters;

import java.util.Set;

import static de.focus_shift.jollyday.core.HolidayCalendar.GERMANY;

final HolidayManager holidayManager = HolidayManager.getInstance(ManagerParameters.create(GERMANY));
final Set<Holiday> holidays = holidayManager.getHolidays(Year.of(2022));
Retrieve public holidays for a period of days (click to expand)

Returns all german public holidays from the 15th of april in 2022 until the 31st of may in 2023

import de.focus_shift.jollyday.core.Holiday;
import de.focus_shift.jollyday.core.HolidayManager;
import de.focus_shift.jollyday.core.ManagerParameters;

import java.time.LocalDate;
import java.util.Set;

import static de.focus_shift.jollyday.core.HolidayCalendar.GERMANY;

final HolidayManager holidayManager = HolidayManager.getInstance(ManagerParameters.create(GERMANY));
final Set<Holiday> holidays = holidayManager.getHolidays(LocalDate.of(2022, 4, 15), LocalDate.of(2023, 5, 31));
Check if a specific date is a public holiday (click to expand)

Returns true or false if a date is a public holidays in germany.

import de.focus_shift.jollyday.core.HolidayManager;
import de.focus_shift.jollyday.core.ManagerParameters;

import java.time.LocalDate;

import static de.focus_shift.jollyday.core.HolidayCalendar.GERMANY;

final HolidayManager holidayManager = HolidayManager.getInstance(ManagerParameters.create(GERMANY));
final boolean isHoliday = holidayManager.isHoliday(LocalDate.of(2022, 6, 6));

Returns true or false if a date is a public holidays in Baden-Württemberg in germany.

import de.focus_shift.jollyday.core.HolidayManager;
import de.focus_shift.jollyday.core.ManagerParameters;

import java.time.LocalDate;

import static de.focus_shift.jollyday.core.HolidayCalendar.GERMANY;

final HolidayManager holidayManager = HolidayManager.getInstance(ManagerParameters.create(GERMANY));
final boolean isHoliday = holidayManager.isHoliday(LocalDate.of(2022, 6, 6), "bw");
Override an existing country (click to expand)

If you want to override the public holidays of a provided country like Germany, you need to put a holiday file under the path holidays/ and name it Holidays_de.xml on your classpath. Jollyday will pick up yours at first. The file and the hierarchy need to be identical to the one you want to override.

The holiday file structure needs to look like the one below. The XML Schema Definition file can be viewed here

<?xml version="1.0" encoding="UTF-8"?>

<Configuration hierarchy="de" description="Germany"
               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>
    <!-- Add the holidays here-->
  </Holidays>

  ...
  
  <SubConfigurations hierarchy="bw" description="Baden-Württemberg">
    <Holidays>
    ...
    </Holidays>
  </SubConfigurations>
</Configuration>

ISO 3166

To retrieve the public holidays of a country the ISO 3166-1 alpha-2 standard is used. A list of current ISO 3166-1 alpha-2 codes is available at wikipedia.

To access the public holidays of a subdivision of a country, e.g. Baden-Württemberg of Germany the ISO 3166-2 standard is used. A list of current ISO 3166-2 codes is available at wikipedia.

Data precision

Precision Supported
Country (ISO 3166-1 alpha-2) Yes
Subdivisions (ISO 3166-2) Yes
City Holiday Yes

Holiday types

The following holiday types are supported:

Public Holiday
Public holidays are days when most of the public enjoys a paid non-working days. These days are determined by local laws and regulations. Countries use various names for these official non-working days, such as:

Other Names for Public Holiday Country Businesses
Bank Holiday United Kingdom Closed
National Holiday Most Countries Closed
Red Days Norway Closed
Regular Holidays Philippines Closed
Restricted Holidays India Closed
Statutory Holiday Canada Closed

We will declare all of these as Public Holiday

Bank Holiday
Bank holidays are days when financial institutions and government offices (and government-regulated businesses) are closed as determined by local laws and regulations. Other businesses, such as offices and retail stores, may also be closed on these days, though are not mandated to by local laws and regulations.

Observance
Observance, is a celebration or commemoration that doesn't include a day off from work. When people celebrate or commemorate something, but do not have a day off from work for that reason, we call it an observance. There are different types of observance like Religious, Secular, Awareness, International or National observance. We will declare all of these as Observance

Unofficial Holidays
Holidays which are not public or bank holidays. Unofficial holidays are deprecated and will be replaced by the other types over time.

Development

If you want to support us at the development on jollyday than take a look at Contributing to jollyday. If you have any kind of questions please go to Discussions and see if there are already answers and if not please open a discussion with your question. If you want to raise an issue or bug you can create a new issue

Requirements

Architecture decision record (ADR)

git hooks (optional)

There are some app specific git hooks to automate stuff like:

  • Add 'closes #issue-number' to the commit message

If you want to take advantage of this automation you can run:

git config core.hooksPath '.githooks' 

The git hooks can be found in the .githooks directory.

License

Apache License, Version 2.0