@suzukihayate/jp-holidays 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/index.d.ts +24 -0
- package/index.js +141 -0
- package/package.json +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hayate Suzuki (鈴木颯)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# jp-holidays
|
|
2
|
+
|
|
3
|
+
日本の祝日を**計算で求める**、依存ゼロのライブラリです。祝日のデータファイルを毎年更新する必要がありません。
|
|
4
|
+
|
|
5
|
+
- 固定日・ハッピーマンデー(成人の日・海の日・敬老の日・スポーツの日)
|
|
6
|
+
- **春分の日・秋分の日**(天文近似式)
|
|
7
|
+
- **振替休日**(祝日が日曜のとき)・**国民の休日**(祝日に挟まれた平日)
|
|
8
|
+
- **五輪特例**(2020/2021 の海の日・スポーツの日・山の日の移動)
|
|
9
|
+
- 依存ゼロ・型定義つき・ESM をそのまま import
|
|
10
|
+
|
|
11
|
+
対応範囲:**1980〜2099 年**(春分・秋分の近似式が有効な範囲)。
|
|
12
|
+
|
|
13
|
+
## インストール
|
|
14
|
+
```bash
|
|
15
|
+
npm install @suzukihayate/jp-holidays
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 使い方
|
|
19
|
+
```js
|
|
20
|
+
import { holidays, isHoliday, holidayName } from '@suzukihayate/jp-holidays';
|
|
21
|
+
|
|
22
|
+
holidays(2024);
|
|
23
|
+
// [ { date: 2024-01-01, name: '元日' },
|
|
24
|
+
// { date: 2024-01-08, name: '成人の日' }, ... 振替休日も含む ]
|
|
25
|
+
|
|
26
|
+
isHoliday('2024-05-03'); // true
|
|
27
|
+
isHoliday('2024-06-02'); // false
|
|
28
|
+
holidayName('2024-05-06'); // "振替休日"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
- `holidays(year)` — その年の祝日を `{ date, name }[]`(日付順)で返す
|
|
33
|
+
- `isHoliday(input)` — `Date` / `"YYYY-MM-DD"` が祝日か
|
|
34
|
+
- `holidayName(input)` — 祝日名(祝日でなければ `null`)
|
|
35
|
+
|
|
36
|
+
## 正確性
|
|
37
|
+
2024 年の全祝日(振替休日含む)、2020 年の五輪特例、国民の休日などをテストで検証しています(`node --test`)。春分・秋分は 1980〜2099 年で官報の確定日と一致する近似式を使用しています。
|
|
38
|
+
|
|
39
|
+
## License
|
|
40
|
+
MIT © 2026 Hayate Suzuki
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface Holiday {
|
|
2
|
+
/** 祝日の日付(ローカルタイムの Date)。 */
|
|
3
|
+
date: Date;
|
|
4
|
+
/** 祝日名(例: "元日"、"振替休日")。 */
|
|
5
|
+
name: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type DateInput = Date | string;
|
|
9
|
+
|
|
10
|
+
/** 指定年(1980〜2099)の祝日を計算して返す(日付順)。 */
|
|
11
|
+
export function holidays(year: number): Holiday[];
|
|
12
|
+
|
|
13
|
+
/** 日付(Date / "YYYY-MM-DD")が祝日か判定する。 */
|
|
14
|
+
export function isHoliday(input: DateInput): boolean;
|
|
15
|
+
|
|
16
|
+
/** 日付が祝日ならその名称、そうでなければ null を返す。 */
|
|
17
|
+
export function holidayName(input: DateInput): string | null;
|
|
18
|
+
|
|
19
|
+
declare const _default: {
|
|
20
|
+
holidays: typeof holidays;
|
|
21
|
+
isHoliday: typeof isHoliday;
|
|
22
|
+
holidayName: typeof holidayName;
|
|
23
|
+
};
|
|
24
|
+
export default _default;
|
package/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// jp-holidays — 日本の祝日を「計算」で求める依存ゼロのライブラリ(データファイル不要)。
|
|
2
|
+
// - 固定日・ハッピーマンデー・春分/秋分(天文近似)
|
|
3
|
+
// - 振替休日(祝日が日曜の場合)・国民の休日(祝日に挟まれた平日)
|
|
4
|
+
// - 五輪特例(2020/2021 の海の日・スポーツの日・山の日の移動)
|
|
5
|
+
// 対応範囲: 1980〜2099 年(春分・秋分の近似式が有効な範囲)。
|
|
6
|
+
|
|
7
|
+
const MIN_YEAR = 1980;
|
|
8
|
+
const MAX_YEAR = 2099;
|
|
9
|
+
|
|
10
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
11
|
+
const ymd = (d) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;
|
|
12
|
+
|
|
13
|
+
/** 指定月の第n月曜日。 */
|
|
14
|
+
function nthMonday(year, month, nth) {
|
|
15
|
+
const firstDow = new Date(year, month - 1, 1).getDay(); // 0=日
|
|
16
|
+
const firstMon = 1 + ((1 - firstDow + 7) % 7);
|
|
17
|
+
return new Date(year, month - 1, firstMon + (nth - 1) * 7);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** 春分の日(1980-2099 の近似式)。 */
|
|
21
|
+
function shunbun(y) {
|
|
22
|
+
return Math.floor(20.8431 + 0.242194 * (y - 1980) - Math.floor((y - 1980) / 4));
|
|
23
|
+
}
|
|
24
|
+
/** 秋分の日(1980-2099 の近似式)。 */
|
|
25
|
+
function shubun(y) {
|
|
26
|
+
return Math.floor(23.2488 + 0.242194 * (y - 1980) - Math.floor((y - 1980) / 4));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** その年の「国民の祝日」(振替・国民の休日を除く本来の祝日)を求める。 */
|
|
30
|
+
function baseHolidays(y) {
|
|
31
|
+
const list = [];
|
|
32
|
+
const add = (month, day, name) => list.push({ month, day, name });
|
|
33
|
+
|
|
34
|
+
add(1, 1, '元日');
|
|
35
|
+
add(...mdOf(nthMonday(y, 1, 2)), '成人の日'); // 2000年以降。本ライブラリは1980-2099対応なので常にハッピーマンデー
|
|
36
|
+
add(2, 11, '建国記念の日');
|
|
37
|
+
if (y >= 2020) add(2, 23, '天皇誕生日');
|
|
38
|
+
else add(12, 23, '天皇誕生日'); // 1989-2018(2019は無し→下で除外)
|
|
39
|
+
if (y === 2019) {
|
|
40
|
+
// 2019年は天皇誕生日なし
|
|
41
|
+
for (let i = list.length - 1; i >= 0; i--) if (list[i].name === '天皇誕生日') list.splice(i, 1);
|
|
42
|
+
}
|
|
43
|
+
add(3, shunbun(y), '春分の日');
|
|
44
|
+
add(4, 29, '昭和の日'); // 2007年以降(本対応範囲では常に昭和の日)
|
|
45
|
+
add(5, 3, '憲法記念日');
|
|
46
|
+
add(5, 4, 'みどりの日'); // 2007年以降
|
|
47
|
+
add(5, 5, 'こどもの日');
|
|
48
|
+
|
|
49
|
+
// 海の日
|
|
50
|
+
if (y === 2020) add(7, 23, '海の日');
|
|
51
|
+
else if (y === 2021) add(7, 22, '海の日');
|
|
52
|
+
else add(...mdOf(nthMonday(y, 7, 3)), '海の日'); // 2003年以降
|
|
53
|
+
|
|
54
|
+
// スポーツの日(旧・体育の日)
|
|
55
|
+
const sportsName = y >= 2020 ? 'スポーツの日' : '体育の日';
|
|
56
|
+
if (y === 2020) add(7, 24, sportsName);
|
|
57
|
+
else if (y === 2021) add(7, 23, sportsName);
|
|
58
|
+
else add(...mdOf(nthMonday(y, 10, 2)), sportsName);
|
|
59
|
+
|
|
60
|
+
// 山の日(2016年以降)
|
|
61
|
+
if (y >= 2016) {
|
|
62
|
+
if (y === 2020) add(8, 10, '山の日');
|
|
63
|
+
else if (y === 2021) add(8, 8, '山の日');
|
|
64
|
+
else add(8, 11, '山の日');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
add(...mdOf(nthMonday(y, 9, 3)), '敬老の日'); // 2003年以降
|
|
68
|
+
add(9, shubun(y), '秋分の日');
|
|
69
|
+
add(11, 3, '文化の日');
|
|
70
|
+
add(11, 23, '勤労感謝の日');
|
|
71
|
+
|
|
72
|
+
return list.map((h) => ({ date: new Date(y, h.month - 1, h.day), name: h.name }))
|
|
73
|
+
.sort((a, b) => a.date - b.date);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function mdOf(date) { return [date.getMonth() + 1, date.getDate()]; }
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 指定年の祝日を計算して返す(日付順)。
|
|
80
|
+
* @param {number} year 1980〜2099
|
|
81
|
+
* @returns {{ date: Date, name: string }[]}
|
|
82
|
+
*/
|
|
83
|
+
export function holidays(year) {
|
|
84
|
+
const y = Number(year);
|
|
85
|
+
if (!Number.isInteger(y) || y < MIN_YEAR || y > MAX_YEAR) {
|
|
86
|
+
throw new RangeError(`jp-holidays: 対応年は ${MIN_YEAR}〜${MAX_YEAR} です(指定: ${year})`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const base = baseHolidays(y);
|
|
90
|
+
const map = new Map(base.map((h) => [ymd(h.date), h.name]));
|
|
91
|
+
|
|
92
|
+
// 国民の休日(前後が祝日の平日。1986年以降)
|
|
93
|
+
if (y >= 1986) {
|
|
94
|
+
const start = new Date(y, 0, 1), end = new Date(y, 11, 31);
|
|
95
|
+
for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
|
|
96
|
+
const k = ymd(d);
|
|
97
|
+
if (map.has(k) || d.getDay() === 0) continue;
|
|
98
|
+
const prev = new Date(d); prev.setDate(prev.getDate() - 1);
|
|
99
|
+
const next = new Date(d); next.setDate(next.getDate() + 1);
|
|
100
|
+
if (map.has(ymd(prev)) && map.has(ymd(next))) {
|
|
101
|
+
base.push({ date: new Date(d), name: '国民の休日' });
|
|
102
|
+
map.set(k, '国民の休日');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 振替休日(祝日が日曜のとき、次の祝日でない日。1973年以降=本対応範囲では常に有効)
|
|
108
|
+
const result = base.slice().sort((a, b) => a.date - b.date);
|
|
109
|
+
for (const h of result.slice()) {
|
|
110
|
+
if (h.date.getDay() !== 0) continue;
|
|
111
|
+
const sub = new Date(h.date);
|
|
112
|
+
do { sub.setDate(sub.getDate() + 1); } while (map.has(ymd(sub)));
|
|
113
|
+
base.push({ date: new Date(sub), name: '振替休日' });
|
|
114
|
+
map.set(ymd(sub), '振替休日');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return base.sort((a, b) => a.date - b.date);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** 日付(Date / "YYYY-MM-DD")が祝日か判定する。 */
|
|
121
|
+
export function isHoliday(input) {
|
|
122
|
+
return holidayName(input) !== null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** 日付が祝日ならその名称、そうでなければ null を返す。 */
|
|
126
|
+
export function holidayName(input) {
|
|
127
|
+
let d;
|
|
128
|
+
if (input instanceof Date) d = input;
|
|
129
|
+
else if (typeof input === 'string') {
|
|
130
|
+
const m = input.match(/^(\d{4})-(\d{1,2})-(\d{1,2})/);
|
|
131
|
+
if (!m) throw new TypeError('jp-holidays: 日付は Date か "YYYY-MM-DD" で指定してください。');
|
|
132
|
+
d = new Date(+m[1], +m[2] - 1, +m[3]);
|
|
133
|
+
} else {
|
|
134
|
+
throw new TypeError('jp-holidays: 日付は Date か "YYYY-MM-DD" で指定してください。');
|
|
135
|
+
}
|
|
136
|
+
const key = ymd(d);
|
|
137
|
+
for (const h of holidays(d.getFullYear())) if (ymd(h.date) === key) return h.name;
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export default { holidays, isHoliday, holidayName };
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@suzukihayate/jp-holidays",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "日本の祝日を計算で求める依存ゼロのライブラリ。春分・秋分、ハッピーマンデー、振替休日、国民の休日、五輪特例に対応。",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"types": "index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./index.d.ts",
|
|
11
|
+
"default": "./index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["index.js", "index.d.ts", "README.md", "LICENSE"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node --test"
|
|
17
|
+
},
|
|
18
|
+
"keywords": ["japanese-holidays", "祝日", "holidays", "japan", "calendar", "振替休日", "国民の休日", "zero-dependency"],
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/HaYaTedonn/jp-holidays.git"
|
|
22
|
+
},
|
|
23
|
+
"author": "Hayate Suzuki",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"engines": { "node": ">=18" },
|
|
26
|
+
"sideEffects": false
|
|
27
|
+
}
|