Pure-Python library for handling Japanese public holidays based on official Cabinet Office data
npx @tessl/cli install tessl/pypi-jpholiday@1.0.0A comprehensive Python library for handling Japanese public holidays based on official data from the Japanese Cabinet Office. JPHoliday enables developers to easily check if specific dates are holidays, retrieve holiday names, get all holidays for a given year or month, and filter holidays within date ranges. The library supports both datetime.date and datetime.datetime objects, includes accurate holiday calculations through 2026 (with extended calculations beyond that), implements substitute holidays for holidays falling on weekends, and provides extensibility through custom holiday checkers.
pip install jpholidayimport jpholidayClass-based API:
from jpholiday import JPHolidayCustom holiday checker interface:
from jpholiday import OriginalHolidayCheckerInterfaceHoliday model:
from jpholiday.model.holiday import HolidayExceptions:
from jpholiday.exception import JPHolidayTypeErrorimport jpholiday
import datetime
# Check if a date is a holiday
is_holiday = jpholiday.is_holiday(datetime.date(2024, 1, 1)) # True
print(is_holiday)
# Get holiday name
holiday_name = jpholiday.is_holiday_name(datetime.date(2024, 1, 1)) # '元日'
print(holiday_name)
# Get all holidays for a year
holidays_2024 = jpholiday.year_holidays(2024)
for date, name in holidays_2024:
print(f"{date}: {name}")
# Get holidays in a date range
holidays_jan = jpholiday.between(
datetime.date(2024, 1, 1),
datetime.date(2024, 1, 31)
)
for date, name in holidays_jan:
print(f"{date}: {name}")Class-based usage:
from jpholiday import JPHoliday
import datetime
jpholiday = JPHoliday()
# Get Holiday objects instead of tuples
holidays = jpholiday.holidays(datetime.date(2024, 1, 1))
for holiday in holidays:
print(f"{holiday.date}: {holiday.name}")
# Check if date is holiday
is_holiday = jpholiday.is_holiday(datetime.date(2024, 1, 1))
print(is_holiday)Check if specific dates are Japanese public holidays and retrieve holiday names.
from typing import Union, Optional
import datetime
def is_holiday(date: Union[datetime.date, datetime.datetime]) -> bool:
"""
Check if a given date is a Japanese public holiday.
Args:
date: Date to check, supports both datetime.date and datetime.datetime
Returns:
True if the date is a holiday, False otherwise
Raises:
JPHolidayTypeError: If date is not datetime.date or datetime.datetime
"""
def is_holiday_name(date: Union[datetime.date, datetime.datetime]) -> Optional[str]:
"""
Get the holiday name for a given date.
Args:
date: Date to check, supports both datetime.date and datetime.datetime
Returns:
Holiday name as string if the date is a holiday, None otherwise
Raises:
JPHolidayTypeError: If date is not datetime.date or datetime.datetime
"""Retrieve collections of holidays for years, months, or date ranges.
import datetime
def year_holidays(year: int) -> list[tuple[datetime.date, str]]:
"""
Get all holidays for a given year.
Args:
year: Year to get holidays for
Returns:
List of (date, name) tuples for all holidays in the year
"""
def month_holidays(year: int, month: int) -> list[tuple[datetime.date, str]]:
"""
Get all holidays for a given month.
Args:
year: Year containing the month
month: Month to get holidays for (1-12)
Returns:
List of (date, name) tuples for all holidays in the month
"""
def between(
start_date: Union[datetime.date, datetime.datetime],
end_date: Union[datetime.date, datetime.datetime]
) -> list[tuple[datetime.date, str]]:
"""
Get holidays between two dates (inclusive).
Args:
start_date: Start of date range
end_date: End of date range
Returns:
List of (date, name) tuples for all holidays in the range
Raises:
JPHolidayTypeError: If dates are not datetime.date or datetime.datetime
"""Register and unregister custom holiday checkers to extend the library with additional holidays.
from jpholiday import OriginalHolidayCheckerInterface
def register(checker: OriginalHolidayCheckerInterface):
"""
Register a custom holiday checker to add additional holidays.
Args:
checker: Custom holiday checker implementing OriginalHolidayCheckerInterface
"""
def unregister(checker: OriginalHolidayCheckerInterface):
"""
Unregister a previously registered custom holiday checker.
Args:
checker: Custom holiday checker to remove
"""Object-oriented interface providing the same functionality with Holiday objects instead of tuples.
from typing import Union, Iterator
import datetime
from jpholiday.model.holiday import Holiday
from jpholiday import OriginalHolidayCheckerInterface
class JPHoliday:
"""
Main class for Japanese holiday operations with caching and custom checker support.
"""
def __init__(self):
"""Create a new JPHoliday instance with in-memory cache and registry."""
def holidays(self, date: Union[datetime.date, datetime.datetime]) -> list[Holiday]:
"""
Get Holiday objects for a given date.
Args:
date: Date to check
Returns:
List of Holiday objects for the date (empty if no holidays)
Raises:
JPHolidayTypeError: If date is not datetime.date or datetime.datetime
"""
def is_holiday(self, date: Union[datetime.date, datetime.datetime]) -> bool:
"""
Check if a given date is a holiday.
Args:
date: Date to check
Returns:
True if the date is a holiday, False otherwise
"""
def year_holidays(self, year: int) -> list[Holiday]:
"""
Get all holidays for a year as Holiday objects.
Args:
year: Year to get holidays for
Returns:
List of Holiday objects for the year
"""
def iter_year_holidays(self, year: int) -> Iterator[Holiday]:
"""
Get iterator over holidays for a year.
Args:
year: Year to get holidays for
Returns:
Iterator yielding Holiday objects
"""
def month_holidays(self, year: int, month: int) -> list[Holiday]:
"""
Get all holidays for a month as Holiday objects.
Args:
year: Year containing the month
month: Month to get holidays for (1-12)
Returns:
List of Holiday objects for the month
"""
def iter_month_holidays(self, year: int, month: int) -> Iterator[Holiday]:
"""
Get iterator over holidays for a month.
Args:
year: Year containing the month
month: Month to get holidays for (1-12)
Returns:
Iterator yielding Holiday objects
"""
def between(
self,
start_date: Union[datetime.date, datetime.datetime],
end_date: Union[datetime.date, datetime.datetime]
) -> list[Holiday]:
"""
Get holidays between two dates as Holiday objects.
Args:
start_date: Start of date range
end_date: End of date range
Returns:
List of Holiday objects in the range
"""
def iter_between(
self,
start_date: Union[datetime.date, datetime.datetime],
end_date: Union[datetime.date, datetime.datetime]
) -> Iterator[Holiday]:
"""
Get iterator over holidays between two dates.
Args:
start_date: Start of date range
end_date: End of date range
Returns:
Iterator yielding Holiday objects
"""
def register(self, checker: OriginalHolidayCheckerInterface):
"""
Register a custom holiday checker.
Args:
checker: Custom holiday checker to register
"""
def unregister(self, checker: OriginalHolidayCheckerInterface):
"""
Unregister a custom holiday checker.
Args:
checker: Custom holiday checker to unregister
"""import dataclasses
import datetime
from abc import ABC, abstractmethod
@dataclasses.dataclass(frozen=True)
class Holiday:
"""
Immutable dataclass representing a Japanese holiday.
"""
date: datetime.date # The holiday date
name: str # The holiday name in Japanese
def to_tuple(self) -> tuple[datetime.date, str]:
"""
Convert to (date, name) tuple for compatibility with functional API.
Returns:
Tuple of (date, name)
"""
class OriginalHolidayCheckerInterface(ABC):
"""
Abstract base class for implementing custom holiday checkers.
"""
@abstractmethod
def is_holiday(self, date: datetime.date) -> bool:
"""
Check if the given date is a holiday according to this checker.
Args:
date: Date to check
Returns:
True if the date is a holiday, False otherwise
"""
@abstractmethod
def holiday_name(self, date: datetime.date) -> str:
"""
Get the holiday name for the given date.
Args:
date: Date to get holiday name for
Returns:
Holiday name as string
"""
# Exception types
class JPHolidayException(Exception):
"""Base exception for jpholiday library."""
pass
class JPHolidayTypeError(JPHolidayException):
"""Raised when invalid types are passed to functions."""
passimport jpholiday
from jpholiday import OriginalHolidayCheckerInterface
import datetime
# Define a custom holiday checker
class CompanyHolidayChecker(OriginalHolidayCheckerInterface):
def is_holiday(self, date: datetime.date) -> bool:
# Company founding day
if date == datetime.date(date.year, 3, 15):
return True
return False
def holiday_name(self, date: datetime.date) -> str:
return '創立記念日'
# Register the custom checker
custom_checker = CompanyHolidayChecker()
jpholiday.register(custom_checker)
# Now company holidays are included
print(jpholiday.is_holiday(datetime.date(2024, 3, 15))) # True
print(jpholiday.is_holiday_name(datetime.date(2024, 3, 15))) # '創立記念日'
# Unregister when done
jpholiday.unregister(custom_checker)The library validates input types and raises JPHolidayTypeError for invalid inputs:
import jpholiday
from jpholiday.exception import JPHolidayTypeError
try:
# This will raise JPHolidayTypeError
jpholiday.is_holiday("2024-01-01") # String instead of date
except JPHolidayTypeError as e:
print(f"Type error: {e}")
try:
# This will raise JPHolidayTypeError
jpholiday.is_holiday(20240101) # Integer instead of date
except JPHolidayTypeError as e:
print(f"Type error: {e}")# Functional API (most common)
import jpholiday
jpholiday.is_holiday(datetime.date(2024, 1, 1))
# Class-based API
from jpholiday import JPHoliday
jp = JPHoliday()
jp.is_holiday(datetime.date(2024, 1, 1))
# Custom holiday implementation
from jpholiday import OriginalHolidayCheckerInterface
# Working with Holiday objects
from jpholiday.model.holiday import Holiday
# Exception handling
from jpholiday.exception import JPHolidayTypeError, JPHolidayException