Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/dist
/holiday_jp.egg-info
/venv
134 changes: 92 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,116 @@
[![PyPI downloads](https://img.shields.io/pypi/dm/holiday-jp.svg)](https://pypi.org/project/holiday-jp/)
[![GitHub release](https://img.shields.io/github/release/holiday-jp/holiday_jp-python.svg)](https://github.com/holiday-jp/holiday_jp-python/releases)

# holiday_jp-python
# holiday_jp-python リポジトリ

Japanese holiday for Python 3+
using dataset from https://github.com/holiday-jp/holiday_jp
## 概要

## install
`holiday_jp-python` リポジトリは、**Python言語**向けの日本の祝日データを提供するライブラリです。このライブラリを使用することで、簡単に日本の祝日情報を取得し、カレンダーアプリケーションや日程管理ツールなどで利用することができます。[holiday-jp](https://github.com/holiday-jp/holiday_jp) データセットを使用。

> pip3 install holiday-jp
## インストール

### If you want to contribute
Build on linux with python 3.x
`pip` を使用して、簡単に `holiday_jp` ライブラリをインストールできます。

#### Clone the project or download the source
> git clone https://github.com/holiday-jp/holiday_jp-python

#### test
> python3 -m unittest holiday_jp.test
```bash
pip install holiday-jp
```

OR
## 使用方法

> make test
```python
from holiday_jp import HolidayJp

Build command:
> python3 setup.py sdist
# 特定の年の祝日を取得
holidays_2024 = HolidayJp.year_holidays(year=2024)
print([one_holiday.date_obj for one_holiday in holidays_2024])

OR
>> [datetime.date(2024, 1, 1), datetime.date(2024, 1, 8), datetime.date(2024, 2, 11), datetime.date(2024, 2, 12), datetime.date(2024, 2, 23), datetime.date(2024, 3, 20), datetime.date(2024, 4, 29), datetime.date(2024, 5, 3), datetime.date(2024, 5, 4), datetime.date(2024, 5, 5),...

> make build
# 休日の情報を文字列として取得するためのフォーマットを指定する。
def format_holiday_as_string(holiday):
return f"{holiday.date_obj.strftime('%Y年%m月%d日')}({holiday.week})「{holiday.name}」"

It will build the package and be available in the dist/ directory
print([format_holiday_as_string(one_holiday) for one_holiday in holidays_2024])

### alternative install
>> ['2024年01月01日(月)「元日」', '2024年01月08日(月)「成人の日」', '2024年02月11日(日)「建国記念の日」', '2024年02月12日(月)「建国記念の日 振替休日」', '2024年02月23日(金)「天皇誕生日」', '2024年03月20日(水)「春分の日」', '2024年04月29日(月)「昭和の日」', '2024年05月03日(金)「憲法記念日」',...
```

download the release and install this way:
pip3 install holiday_jp-xxx.tar.gz
## サポートされている機能

## Usage
- 特定の月の祝日一覧を取得:

```python
from holiday_jp import HolidayJp
# with string date YYYY-MM-DD
if HolidayJp('1990-01-01').is_holiday:
print('True')

import datetime
# 特定の月の祝日一覧を取得
holidays_may_2024 = HolidayJp.month_holidays(year=2024, month=5)
print([one_holiday.date_obj for one_holiday in holidays_may_2024])

>> [datetime.date(2024, 5, 3), datetime.date(2024, 5, 4), datetime.date(2024, 5, 5), datetime.date(2024, 5, 6)]
```

- 特定の日が振替休日かどうかを確認:

```python
from holiday_jp import HolidayJp
# or date object
if HolidayJp(datetime.date.today()).is_holiday:
print('False')
else:
print('True')

# Between return holidays between 2 dates in text
holidays = HolidayJp.between('2009-01-01', '2009-01-31')
new_year_day = holidays[0]
self.assertEqual(datetime.date(year=2009, month=1, day=1), new_year_day.date_obj)
self.assertEqual('元日', new_year_day.name)

# Or date object
holidays = HolidayJp.between(datetime.date(year=2008, month=12, day=23), datetime.date(year=2009, month=1, day=12))

# 特定の日が振替休日かどうかを確認
is_substitute_holiday = holiday.is_substitute_holiday(date='2024-05-06')
print(is_substitute_holiday)

>> True
```

- 今日が祝日かどうかを確認:

```python
from datetime import date

# 今日が祝日かどうかを確認
today_is_holiday = holiday.is_holiday(date=date.today())
print(today_is_holiday)

>> False
```

For more usage check the unit test holiday_jp/test.py
これらの例を使用することで、`holiday_jp` ライブラリを柔軟かつ効果的に利用することができます。ライブラリのドキュメントも参照して、さらに詳細な情報を得ることができます。

## 貢献

バグ報告や新機能の提案は、GitHubのイシュートラッカーを使用してください。また、プルリクエストも歓迎しています。詳細については、CONTRIBUTING.md ファイルを参照してください。

## ライセンス

このプロジェクトは MIT License ライセンスの下で公開されています。詳細については、[LICENSE](https://github.com/holiday-jp/holiday_jp-python/blob/master/LICENSE) ファイルを参照してください。


## 代替

`holiday_jp` と [jpholiday](https://github.com/Lalcs/jpholiday) の比較


1. データの正確性とアップデート

holiday_jp-python: 日本の祝日データは、holiday-jp から抽出され、更新が頻繁に行われています。GitHub リポジトリは、最新のデータと連携しています。 holiday_jp-python は、holiday-jp/holiday_jp リポジトリのメンテナンスおよびコミュニティによってサポートされています。

jpholiday: jpholiday は、祝日API からデータを取得しています。ライブラリのメンテナンスとデータのアップデートは、APIの提供者に依存しています。

2. インターフェースと使用方法

holiday_jp-python: holiday_jp ライブラリは、シンプルで直感的なAPIを提供し、特定の年や月の祝日情報を取得する際に柔軟性があります。

jpholiday: jpholiday も使いやすいライブラリであり、jpholidayモジュールから祝日情報を取得することができます。ただし、一部の機能やオプションが異なる場合があります。

3. カスタマイズオプション

holiday_jp-python: holiday_jp は、特定の日が振替休日かどうかや国民の休日かどうかを確認するための専用の関数を提供しており、柔軟なオプションを利用できます。

jpholiday: jpholiday も同様の機能を提供していますが、それぞれのライブラリで提供されているオプションには若干の違いがあります。

## まとめ

どちらのライブラリも、日本の祝日情報を取得するために便利で使いやすいものであり、プロジェクトの要件や好みによって選択できます。holiday_jp-python は、holiday-jp/holiday_jp リポジトリの共通データセットをベースにしており、コミュニティによってメンテナンスされています。両方のドキュメントを参照し、使用例を確認した上で、プロジェクトに最適なものを選択することをお勧めします。



ありがとうございます。楽しんで使っていただけることを願っています!
120 changes: 92 additions & 28 deletions holiday_jp/holiday_jp.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,43 @@
class HolidayJp(object):
"""Holiday in Japan."""

date_obj = '' # the date object
date_obj = None # the date object
week = '' # the week day in jp ex: 木
week_en = '' # the week day in en ex: Thursday
name = '' # the name of the holiday in jp ex: 元日
name_en = '' # the name of the holiday in en ex: New Year's Day
is_holiday = False # if the day is a holiday day
is_holiday = False # if the day is a national holiday
is_substitute_holiday = False # if the day is a substitute holiday
is_business_day = False # if the day is from [monday, friday]

# defaul business day can be overwritten depends on context
BUSINESS_DAY = ['月', '火', '水', '木', '金']
# default business days Monday is 0 and Sunday is 6
BUSINESS_DAY = [i for i in range(0, 5)]

HOLIDAY_DATASET = HolidayDataset.HOLIDAYS
DATASET_FORMAT = '%Y-%m-%d'

DATE_FORMAT = '%Y-%m-%d'

def __init__(self, date):
"""init the date and fill the property.

date: string with the following format yyyy-mm-dd (default, overwrite DATE_FORMAT for other format)
or date object
def __init__(self, date) -> None:
"""Initialize a HolidayJp instance.

Parameters:
date (str or datetime.date): The date to initialize the instance for.
If a string, must be in the format defined in the DATE_FORMAT constante (default 'YYYY-MM-DD').

Sets the following instance attributes based on the given date:
- date_obj: The parsed date object.
- is_holiday: Whether the date is a national holiday.
- week: The weekday in Japanese.
- week_en: The weekday in English.
- name: The holiday name in Japanese (if a holiday).
- name_en: The holiday name in English (if a holiday).
- is_business_day: Whether the date is a business day.
- is_substitute_holiday: Whether the date is a substitute holiday.
"""
self.date_obj = self._format_date(date)
if self.date_obj.weekday() in self.BUSINESS_DAY:
self.is_business_day = True

date_str = self.date_obj.strftime(self.DATE_FORMAT)
if self.HOLIDAY_DATASET.get(date_str):
Expand All @@ -38,18 +52,25 @@ def __init__(self, date):
self.week_en = self.HOLIDAY_DATASET[date_str]['week_en']
self.name = self.HOLIDAY_DATASET[date_str]['name']
self.name_en = self.HOLIDAY_DATASET[date_str]['name_en']
if self.week in self.BUSINESS_DAY:
self.is_business_day = True
else:
# Monday is 0 and Sunday is 6.
if self.date_obj.weekday() < 5:
self.is_business_day = True
self.is_substitute_holiday = self._check_substitute()

@classmethod
def _format_date(cls, date):
"""Format the date to date object."""
def _format_date(cls, date) -> datetime.date:
"""Format a date string or date object to a date object.

Parameters:
date (str or datetime.date): The date to format.
If a string, must match the DATE_FORMAT class constant.

Returns:
datetime.date: The formatted date object.

Raises:
Exception: If the date string does not match the expected format.
"""
import unicodedata
date_obj = None
date_obj = date

# if date is string support the following format otherwise must be a date or datetime object
if isinstance(date, str):
# normalize
Expand All @@ -61,17 +82,28 @@ def _format_date(cls, date):
date_obj = datetime.datetime.strptime(date, cls.DATE_FORMAT).date()
except Exception as e:
raise e
else:
date_obj = date

return date_obj

@classmethod
def between(cls, start, last):
"""Return a tuple of HolidayJp objects between 2 dates.
def between(cls, start, last) -> list:
"""Returns a list of HolidayJp objects between the given start and end dates.

start, last: string with the following format yyyy-mm-dd
or date object
The start and end dates can be strings in the format 'yyyy-mm-dd' or
datetime.date objects.

Iterates day-by-day from start to end date and creates a HolidayJp object
for each date that exists in the holiday dataset.

Parameters:
start: The start date, either as string or datetime.date
end: The end date, either as string or datetime.date

Returns:
A list of HolidayJp objects between the start and end dates inclusive.

Raises:
ValueError if end date is before start date.
"""
start = cls._format_date(start)
last = cls._format_date(last)
Expand All @@ -97,14 +129,46 @@ def between(cls, start, last):
return result

@classmethod
def year_holidays(cls, year):
"""Return a list of HolidayJp for a given year."""
def year_holidays(cls, year) -> list:
"""Returns a list of HolidayJp objects for the given year.

Iterates day-by-day from Jan 1 to Dec 31 of the given year, and creates a
HolidayJp object for each date that exists in the holiday dataset.

Parameters:
year (int): The year to get holidays for

Returns:
list: A list of HolidayJp objects representing the holidays in the given year.
"""
return cls.between('%s-01-01' % year, '%s-12-31' % year)

@classmethod
def month_holidays(cls, year, month):
"""Return a list of HolidayJp for a given month year."""
def month_holidays(cls, year, month) -> list:
"""Returns a list of HolidayJp objects for the given month and year.

Iterates day-by-day from the 1st to the last day of the given month and year,
and creates a HolidayJp object for each date that exists in the holiday dataset.

Parameters:
year (int): The year to get holidays for
month (int): The month to get holidays for, 1-12

Returns:
list: A list of HolidayJp objects representing the holidays in the given month and year.
"""
import calendar
# get the last day of the month
last_day = calendar.monthrange(year, month)
return cls.between('%s-%s-01' % (year, month), '%s-%s-%s' % (year, month, last_day[1]))

def _check_substitute(self) -> bool:
"""Check if the given date is a substitute holiday in Japan.

A substitute holiday is when a national holiday falls on a Sunday,
so the following Monday is also a holiday.

Returns:
bool: True if the date is a substitute holiday, False otherwise.
"""
return self.is_holiday and '振替休日' in self.name
8 changes: 8 additions & 0 deletions holiday_jp/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,11 @@ def test_month_holidays(self):
gw_holiday = HolidayJp.month_holidays(2020, 5)
# only 4 days for golden week need to take day off!
self.assertEqual(len(gw_holiday), 4)

def test_check_substitute_true(self):
holiday = HolidayJp('2023-01-02')
self.assertTrue(holiday._check_substitute())

def test_check_substitute_false(self):
random_date = datetime.date(2023, 2, 15)
self.assertFalse(HolidayJp(random_date)._check_substitute())
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='holiday_jp',
version='22.10.31',
version='24.01.20',
url='https://github.com/LUXEYS/holiday_jp-python',
license='MIT',
author='Luxeys',
Expand Down