bizdays-toolkit 0.16.0 → 0.17.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/CHANGELOG.md +29 -1
- package/README.md +88 -18
- package/dist/core/calendar.js +6 -0
- package/dist/core/diagnose.d.ts +23 -4
- package/dist/core/diagnose.js +66 -10
- package/dist/core/errors.d.ts +2 -0
- package/dist/core/schedule.d.ts +11 -0
- package/dist/core/schedule.js +28 -4
- package/dist/diagnose/index.d.ts +1 -1
- package/dist/sg/index.d.ts +23 -0
- package/dist/sg/index.js +31 -0
- package/dist/sg/rules.d.ts +41 -0
- package/dist/sg/rules.js +156 -0
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.17.0] - 2026-10-25
|
|
8
|
+
|
|
9
|
+
### 移行
|
|
10
|
+
|
|
11
|
+
動作が変わる既存の API はない(既定値はこれまでどおり)。`Calendar`・`Schedule`・`HolidayLookup` に項目 `unconfirmedHolidays` が加わり、`createCalendar`・`createSchedule` の設定と `diagnoseCalendar`・`diagnoseSchedule` の第 2 引数が増える。監視のワークフローの改名(`govuk-watch.yml` → `data-watch.yml`)により、cron-job.org の URL を直す(RELEASING.md)。版ごとの作業は [docs/migration.md](./docs/migration.md) にまとめた。
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- 未確定の祝日のガード `unconfirmedHolidays: "accept" | "throw"`(カレンダー・スケジュール共通。既定 `"accept"`)を追加した。`"throw"` では、評価した日(探索が途中で通る日、祝日の翌日・祝前日の規則が見る隣の日を含む)が未確定の祝日(`confirmed: false`)なら `code: "unconfirmed-holiday"` の `RangeError` を投げる。`holidaysInYear`・`holidaysBetween` は投げないので、影響する日を列挙できる。合成はどれかが `"throw"` なら `"throw"`。エラーコードに `unconfirmed-holiday` を追加した
|
|
16
|
+
- 診断の第 2 引数 `{ asOf: "YYYY-MM-DD" }`(型 `DiagnoseOptions`)を追加した。基準日より前に終わった規則・個別の日付を `info` の `expired` で返す。省略時の結果は変わらない。診断コードに `expired` を追加した
|
|
17
|
+
- シンガポールの祝日 `bizdays-toolkit/sg`(提供元 `sg`。ID `SG`、`Asia/Singapore`、種別 `regular`・`substitute`・`special`、型 `SgHoliday`・`SgHolidayKind`・`KnownSgHolidayKind`)を追加した。MOM が告示した 2020〜2027 年の日付を表で持ち、日曜日に当たった祝日の振替を Holidays Act の規則で計算する。それより後の年は予測せず `out-of-range`。data.gov.sg のコレクション 691(MOM)で全日照合し、2022 年の既知の差分(改定後の告示との食い違い)はフィクスチャに出典付きで記録した
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- 診断: 判定に祝日を使わない設定(提供元がない、または `holidayPolicy: "ignore"` / `holiday: "weekday"` で祝日に従属する規則もない)の `unconfirmedHolidays: "throw"` を `info` の `redundant` にする。診断は未確定の祝日を `"accept"` で評価する
|
|
22
|
+
- 診断: 第 2 引数がオブジェクトでなければ `invalid-argument`、`asOf` が暦日の文字列でなければ `invalid-date` の例外を投げる(設定の誤りは診断結果で返す現状のまま)
|
|
23
|
+
- 振替元をさかのぼるときに祝日の例外を飲み込む範囲を `out-of-range` だけにした(`unconfirmed-holiday` などは投げ直す。これまでは提供元の例外も飲み込んでいた)
|
|
24
|
+
- README: シンガポールの節、「未確定の祝日」の節(レシピ付き)、診断の `asOf` と `expired`、出典にシンガポールと Singapore Open Data Licence を足した。サイズの値を測り直した(ルート約 10.0KB・日本の祝日込み約 11.8KB・英国の祝日込み約 11.7KB・シンガポールの祝日込み約 10.9KB。0.17.0 で測定)
|
|
25
|
+
- `RELEASING.md`: 「シンガポールのデータの更新」の節を足し、監視のワークフローの改名と cron-job.org の URL の修正を書いた
|
|
26
|
+
- `docs/decisions.md`: 44 番(未確定の祝日のガード・診断の基準日・シンガポールの祝日)を追加し、15・28 番に監視のワークフローの改名を書いた
|
|
27
|
+
|
|
28
|
+
### 開発
|
|
29
|
+
|
|
30
|
+
- 監視のワークフローを `govuk-watch.yml` から `data-watch.yml` に改名し、英国とシンガポールの照合を 1 回の起動で順に行う(issue のラベルは `govuk-data`・`datagovsg-data`。ハートビートは両方が動いたときだけ)。`scripts/verify-datagovsg.ts`(`pnpm verify:datagovsg`。`--file`・`--write`・`--report`・`--simulate`)とフィクスチャ `test/fixtures/datagovsg-public-holidays.json`(既知の差分を含む)を追加した
|
|
31
|
+
- テスト: `test/unconfirmed-holidays.test.ts`・`test/diagnose-as-of.test.ts`・`test/sg-rules.test.ts`・`test/sg-datagovsg.test.ts` を追加し、`smoke.mjs`・CJS・利用者の型チェックにシンガポールと新しい設定を足した
|
|
32
|
+
- サイズの上限(`size-limits.json`)を上げ、`./sg` のエントリーを足した。ルート 24,000 → 25,000、`./jp` 27,000 → 28,000、`./uk` 6,700 → 7,500、`./diagnose` 30,500 → 32,000(gzip)。未確定の祝日のガードと診断の基準日のため。`./sg` は 6,000(日付とエラーの共通の実装を含む)
|
|
33
|
+
|
|
7
34
|
## [0.16.0] - 2026-10-23
|
|
8
35
|
|
|
9
36
|
### 移行
|
|
@@ -431,7 +458,8 @@
|
|
|
431
458
|
|
|
432
459
|
- 日本: 2026 年 2 月の官報(2027 年の春分・秋分の日)まで反映(`dataVersion: "2026-02"`、`confirmedThrough: 2027`)
|
|
433
460
|
|
|
434
|
-
[Unreleased]: https://github.com/inohan77/bizdays-toolkit/compare/v0.
|
|
461
|
+
[Unreleased]: https://github.com/inohan77/bizdays-toolkit/compare/v0.17.0...HEAD
|
|
462
|
+
[0.17.0]: https://github.com/inohan77/bizdays-toolkit/compare/v0.16.0...v0.17.0
|
|
435
463
|
[0.16.0]: https://github.com/inohan77/bizdays-toolkit/compare/v0.15.0...v0.16.0
|
|
436
464
|
[0.15.0]: https://github.com/inohan77/bizdays-toolkit/compare/v0.14.1...v0.15.0
|
|
437
465
|
[0.14.1]: https://github.com/inohan77/bizdays-toolkit/compare/v0.14.0...v0.14.1
|
package/README.md
CHANGED
|
@@ -21,6 +21,7 @@ A business-day calendar that combines public holidays with company or store clos
|
|
|
21
21
|
|
|
22
22
|
- **Japanese holidays verified day by day against the Cabinet Office data**: from 1955 through the latest year announced in the Official Gazette, every date in the Cabinet Office "National Holidays" CSV is checked in the tests (substitute holidays, citizens' holidays, holidays for imperial ceremonies and the Olympic moves included)
|
|
23
23
|
- **UK bank holidays verified day by day against GOV.UK**: choose England, Wales, Scotland or Northern Ireland. From 2012 through the last year GOV.UK has published, every date and name is checked against the GOV.UK data in the tests, and differences are watched daily
|
|
24
|
+
- **Singapore public holidays verified day by day against data.gov.sg**: the dates gazetted by the Ministry of Manpower (2020 through the last year gazetted), with the days in lieu for holidays on a Sunday, are checked against the MOM collection on data.gov.sg in the tests, and differences are watched daily
|
|
24
25
|
- **Recurring rules**: rules such as "closed on the 3rd Wednesday", "closed every other Wednesday", "stocktaking on the last day of the month", "closed on Mondays (on the next weekday if Monday is a holiday)" or "closed on the day after a holiday", together with what happens when they fall on a holiday (follow the holiday, apply anyway, or move to the next day). Rules can have an effective period, so "closed on Tuesdays instead of Mondays from April 2027" is one calendar
|
|
25
26
|
- **Day-by-day values (e.g. store hours)**: values that change by weekday, holiday and specific date, such as "closed on Tuesdays, Sunday hours on holidays, closed on New Year's Day, short hours on New Year's Eve", are looked up with the same rules
|
|
26
27
|
- **Option diagnostics**: `diagnoseCalendar` and `diagnoseSchedule` from `bizdays-toolkit/diagnose` list rules that can never apply, rules whose removal changes nothing, typos in option keys, calendars with no business day and more, without throwing. One line in your tests keeps a change of settings from silently killing a rule
|
|
@@ -28,9 +29,9 @@ A business-day calendar that combines public holidays with company or store clos
|
|
|
28
29
|
- **Business-day arithmetic**: closed weekdays, annual closures (including ranges across the new year), specific closed and open dates, and holidays combine to compute "N business days later", "next business day after the cut-off time" and more
|
|
29
30
|
- **A calendar from a schedule**: `createCalendarFromSchedule` turns a schedule such as store hours into a business-day calendar, so the hours are the only configuration and business-day arithmetic works on them
|
|
30
31
|
- **Combining calendars**: `combineCalendars` builds a calendar of the days on which all of several calendars are open (your company and the bank, for a remittance date) or any of them is open (any of several stores), and business-day arithmetic works on the result
|
|
31
|
-
- **Time-zone safe**: instants such as `Date` are converted to a civil date in the calendar's time zone (`Asia/Tokyo` for Japan, `Europe/London` for the UK) before evaluation. A server running in UTC does not treat 00:00–09:00 in Japan as the previous day
|
|
32
|
-
- **Lightweight, zero dependencies**: about
|
|
33
|
-
- **Extensible to other countries and regions**: holiday providers are pluggable through the `HolidayProvider` interface. Japan
|
|
32
|
+
- **Time-zone safe**: instants such as `Date` are converted to a civil date in the calendar's time zone (`Asia/Tokyo` for Japan, `Europe/London` for the UK, `Asia/Singapore` for Singapore) before evaluation. A server running in UTC does not treat 00:00–09:00 in Japan as the previous day
|
|
33
|
+
- **Lightweight, zero dependencies**: about 10.0 KB min+gzip (about 11.8 KB with Japanese holidays, about 11.7 KB with UK bank holidays, about 10.9 KB with Singapore holidays; measured for 0.17.0). ESM, bundled types and `sideEffects: false`. Written in standard JavaScript and `Intl` only (no Node.js APIs); CI tests it on Node.js, Chrome, Firefox, Edge, Safari, Cloudflare Workers, Bun and Deno
|
|
34
|
+
- **Extensible to other countries and regions**: holiday providers are pluggable through the `HolidayProvider` interface. Japan, the UK and Singapore are bundled
|
|
34
35
|
|
|
35
36
|
## Installation
|
|
36
37
|
|
|
@@ -93,6 +94,23 @@ const ukWide = createCalendar({ holidays: [england, scotland, northernIreland] }
|
|
|
93
94
|
- Local holidays set by Scottish councils are not included. Whether a bank holiday is a day off depends on the employment contract and similar arrangements
|
|
94
95
|
- One-off bank holidays may be announced only about ten days ahead. Differences from GOV.UK are watched daily and released as patch versions
|
|
95
96
|
|
|
97
|
+
### Singapore public holidays
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { createCalendar } from "bizdays-toolkit";
|
|
101
|
+
import { sg } from "bizdays-toolkit/sg";
|
|
102
|
+
|
|
103
|
+
const singapore = createCalendar({ holidays: sg, closedWeekdays: [0, 6] });
|
|
104
|
+
singapore.isBusinessDay("2026-08-10"); // false (National Day falls on a Sunday; Monday is the holiday in lieu)
|
|
105
|
+
singapore.addBusinessDays("2026-02-16", 1); // "2026-02-19" (Chinese New Year on February 17 and 18)
|
|
106
|
+
sg.holidaysInYear(2026).find((h) => h.kind === "substitute");
|
|
107
|
+
// { date: "2026-06-01", name: "Vesak Day", nameEn: "Vesak Day", kind: "substitute", confirmed: true }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
- `sg` (ID `SG`, time zone `Asia/Singapore`) is one provider; Singapore has no regional holidays. `kind` is `regular` (an annual public holiday), `substitute` (the day after a public holiday that falls on a Sunday, which the Holidays Act makes a public holiday; it has the name of the original holiday) or `special` (a one-off holiday declared by the Government, such as Polling Day). A public holiday on a Saturday has no substitute day
|
|
111
|
+
- Chinese New Year, Hari Raya Puasa, Hari Raya Haji, Vesak Day and Deepavali follow the lunar, Islamic and Hindu calendars, so they cannot be computed from rules. The dates are the ones gazetted by the Ministry of Manpower (MOM), year by year, and the substitute days follow the rule of the Holidays Act. Supported years are the years MOM has gazetted (currently 2020–2027; `confirmedThrough` is the same as the last supported year). Later years are not predicted and are outside the supported years (`out-of-range`), so `sg` never returns `confirmed: false`
|
|
112
|
+
- The dates are verified against the "Singapore Public Holidays" collection on data.gov.sg (MOM). Where that data differs from the gazetted dates (2022: the revised Hari Raya dates and two missing substitute days), the gazetted dates are used. Differences from data.gov.sg are watched daily and released as patch versions
|
|
113
|
+
|
|
96
114
|
### Business-day calendars
|
|
97
115
|
|
|
98
116
|
```ts
|
|
@@ -623,7 +641,37 @@ createCalendar({ holidays: jpWithNames }).getHoliday("2026-01-01")?.names; // {
|
|
|
623
641
|
|
|
624
642
|
### Outside the supported years
|
|
625
643
|
|
|
626
|
-
Evaluating a date outside the holiday provider's supported years (1955–2099 for Japan, 2012–2099 for the UK) throws a `RangeError`. To treat such dates as having no holidays, set `outOfRange: "ignore"`.
|
|
644
|
+
Evaluating a date outside the holiday provider's supported years (1955–2099 for Japan, 2012–2099 for the UK, 2020–2027 for Singapore) throws a `RangeError`. To treat such dates as having no holidays, set `outOfRange: "ignore"`.
|
|
645
|
+
|
|
646
|
+
### Unconfirmed holidays
|
|
647
|
+
|
|
648
|
+
Years after the provider's `confirmedThrough` may contain predicted holidays (`confirmed: false`): the Japanese equinox days, whose dates are published in the Official Gazette every February for the next year, and UK bank holidays after the last year GOV.UK has published. By default the predictions are used. With `unconfirmedHolidays: "throw"` (next to `outOfRange`, on calendars and schedules), any evaluation that looks up an unconfirmed holiday throws a `RangeError` with `code: "unconfirmed-holiday"`, so that a result which would depend on a prediction, such as a due date in a five-year repayment schedule or a date written into a contract, is never produced silently. "Any evaluation" includes the days a search passes through (`addBusinessDays`, `adjust`, `dueDate`, `closingMonth` and so on) and the neighbouring day a `dayAfterHoliday` or `dayBeforeHoliday` rule looks at, not only the day asked about. `holidaysInYear` and `holidaysBetween` never throw, so they are the way out: after catching the error, list the days that are affected.
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
import { createCalendar, isBizdaysError } from "bizdays-toolkit";
|
|
652
|
+
import { jp } from "bizdays-toolkit/jp";
|
|
653
|
+
|
|
654
|
+
const strict = createCalendar({
|
|
655
|
+
holidays: jp,
|
|
656
|
+
closedWeekdays: [0, 6],
|
|
657
|
+
unconfirmedHolidays: "throw",
|
|
658
|
+
});
|
|
659
|
+
try {
|
|
660
|
+
strict.dueDate("2028-03", { day: 20, convention: "following" });
|
|
661
|
+
} catch (e) {
|
|
662
|
+
if (isBizdaysError(e) && e.code === "unconfirmed-holiday") {
|
|
663
|
+
// Recompute after the Official Gazette of February 2028; these are the days involved
|
|
664
|
+
strict
|
|
665
|
+
.holidaysBetween("2028-01-01", "2028-12-31")
|
|
666
|
+
.filter((h) => !h.confirmed)
|
|
667
|
+
.map((h) => h.date); // ["2028-03-20", "2028-09-22"]
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
- It matters only when the results depend on holidays. With `holidayPolicy: "ignore"` (or `holiday: "weekday"` in a schedule) and no holiday-based rule (`holiday`, `dayAfterHoliday`, `dayBeforeHoliday`, `"after-holiday"`), the results do not change, but `dayInfo` still looks up the holiday it reports and throws. Option diagnostics flag such options as `redundant`
|
|
673
|
+
- Combined calendars throw if any of their calendars throws; a calendar made from a schedule follows the schedule
|
|
674
|
+
- The option catches holidays that are predicted, not holidays that are unknown: a one-off UK bank holiday announced later is absent from the predictions, and Singapore has no predictions at all (later years are `out-of-range`)
|
|
627
675
|
|
|
628
676
|
### Errors
|
|
629
677
|
|
|
@@ -645,7 +693,7 @@ Main codes: `invalid-date`, `invalid-input`, `invalid-month`, `invalid-month-day
|
|
|
645
693
|
|
|
646
694
|
### Option diagnostics
|
|
647
695
|
|
|
648
|
-
`diagnoseCalendar` and `diagnoseSchedule` from `bizdays-toolkit/diagnose` examine options and return a list of problems. They never throw (an empty array means no problems).
|
|
696
|
+
`diagnoseCalendar` and `diagnoseSchedule` from `bizdays-toolkit/diagnose` examine options and return a list of problems. They never throw for a problem in the options (an empty array means no problems); only a wrong second argument (see `asOf` below) throws.
|
|
649
697
|
|
|
650
698
|
```ts
|
|
651
699
|
import { diagnoseCalendar } from "bizdays-toolkit/diagnose";
|
|
@@ -670,16 +718,17 @@ diagnoseCalendar({
|
|
|
670
718
|
// ]
|
|
671
719
|
```
|
|
672
720
|
|
|
673
|
-
| `severity` | `code` | Meaning
|
|
674
|
-
| ---------- | ---------------------------- |
|
|
675
|
-
| `error` | The same codes as exceptions | Errors that make `createCalendar` or `createSchedule` throw. Creation stops at the first one; diagnostics return them all
|
|
676
|
-
| `error` | `invalid-provider-data` | Errors in the data returned by a holiday provider. Creation checks only the years used; diagnostics check every supported year
|
|
677
|
-
| `warning` | `unknown-option` | Unknown keys (ignored at creation). If a close known key exists, `message` suggests it
|
|
678
|
-
| `warning` | `shadowed` | A rule fully covered by an earlier rule of the same type (`relatedPath`) and never used
|
|
679
|
-
| `warning` | `never-matches` | A recurring rule that matches no day (such as `{ day: 30, months: [2] }`, a 5th Wednesday with an effective period that has none, or `dayAfterHoliday` without a holiday provider)
|
|
680
|
-
| `warning` | `out-of-range` | A specific date, or the effective period of a rule, outside the supported years of the holiday provider (`relatedPath`)
|
|
681
|
-
| `warning` | `no-business-day` | No business day at all (calendars only; searching for a business day throws)
|
|
682
|
-
| `info` | `redundant` | A rule whose removal changes nothing (covered by a combination of earlier rules, same as a closed weekday, the same value as the weekday in a schedule, and so on)
|
|
721
|
+
| `severity` | `code` | Meaning |
|
|
722
|
+
| ---------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
723
|
+
| `error` | The same codes as exceptions | Errors that make `createCalendar` or `createSchedule` throw. Creation stops at the first one; diagnostics return them all |
|
|
724
|
+
| `error` | `invalid-provider-data` | Errors in the data returned by a holiday provider. Creation checks only the years used; diagnostics check every supported year |
|
|
725
|
+
| `warning` | `unknown-option` | Unknown keys (ignored at creation). If a close known key exists, `message` suggests it |
|
|
726
|
+
| `warning` | `shadowed` | A rule fully covered by an earlier rule of the same type (`relatedPath`) and never used |
|
|
727
|
+
| `warning` | `never-matches` | A recurring rule that matches no day (such as `{ day: 30, months: [2] }`, a 5th Wednesday with an effective period that has none, or `dayAfterHoliday` without a holiday provider) |
|
|
728
|
+
| `warning` | `out-of-range` | A specific date, or the effective period of a rule, outside the supported years of the holiday provider (`relatedPath`) |
|
|
729
|
+
| `warning` | `no-business-day` | No business day at all (calendars only; searching for a business day throws) |
|
|
730
|
+
| `info` | `redundant` | A rule whose removal changes nothing (covered by a combination of earlier rules, same as a closed weekday, the same value as the weekday in a schedule, and so on), or `unconfirmedHolidays: "throw"` in options whose results do not use holidays |
|
|
731
|
+
| `info` | `expired` | Only with `asOf` (below): a rule or date that ended before the given day |
|
|
683
732
|
|
|
684
733
|
- Branch on `code`. `message` is in English and its wording may change. Future versions may add codes
|
|
685
734
|
- When there is an `error`, the rule relation checks (`shadowed`, `redundant` and so on) are skipped
|
|
@@ -690,6 +739,25 @@ diagnoseCalendar({
|
|
|
690
739
|
- `redundant` compares the results with and without the rule day by day. Specific dates are checked over their range; annual dates and recurring rules are checked, with specific dates removed, over the holiday provider's supported years (1955–2099 for Japan), or 2001–2028 without a provider (28 years cover every combination of weekday and date; with `interval` rules the range is extended to the length of their cycle, such as 56 years for every other week). Effective periods outside that range are checked as well (with `outOfRange: "throw"`, only within the supported years). `message` names the years checked. Schedule values are compared by content for arrays and plain objects, and by identity otherwise (such as `Date`)
|
|
691
740
|
- With Japanese holidays, checking every day takes a few hundred milliseconds. Use it in tests or at startup, not per request. As a development and test tool, it lives in a subpath so it stays out of your app's main bundle
|
|
692
741
|
|
|
742
|
+
**Finding rules that have ended** (`asOf`): options accumulate over the years, for example in a multi-store service that stores each store's options as JSON. Pass `{ asOf: "YYYY-MM-DD" }` as the second argument and every rule with an `effectiveTo` before that day, and every specific date or range that ends before it, is returned as `info` with code `expired` (independent of `redundant`: these rules did affect the past). Without `asOf` nothing is returned as `expired`, so a test such as `assert.deepEqual(diagnoseCalendar(options), [])` does not drift with the date. `asOf` takes only a date string (a `Date` would need a time zone); other values throw `invalid-date`, a second argument that is not an object throws `invalid-argument`, and unknown keys in it are ignored.
|
|
743
|
+
|
|
744
|
+
```ts
|
|
745
|
+
import { diagnoseCalendar } from "bizdays-toolkit/diagnose";
|
|
746
|
+
import { jp } from "bizdays-toolkit/jp";
|
|
747
|
+
|
|
748
|
+
diagnoseCalendar(
|
|
749
|
+
{
|
|
750
|
+
holidays: jp,
|
|
751
|
+
closedRecurring: [
|
|
752
|
+
{ weekday: 1, name: "Closed on Mondays", effectiveTo: "2027-03-31" },
|
|
753
|
+
{ weekday: 2, name: "Closed on Tuesdays", effectiveFrom: "2027-04-01" },
|
|
754
|
+
],
|
|
755
|
+
closedDates: ["2026-02-10"],
|
|
756
|
+
},
|
|
757
|
+
{ asOf: "2028-01-01" },
|
|
758
|
+
).map((d) => [d.code, d.path]); // [["expired", "closedDates[0]"], ["expired", "closedRecurring[0]"]]
|
|
759
|
+
```
|
|
760
|
+
|
|
693
761
|
Keeping options safe with a test:
|
|
694
762
|
|
|
695
763
|
```ts
|
|
@@ -707,9 +775,9 @@ test("the shipping calendar options have no problems", () => {
|
|
|
707
775
|
|
|
708
776
|
Versioning follows [Semantic Versioning](https://semver.org/). See [RELEASING.md](https://github.com/inohan77/bizdays-toolkit/blob/main/RELEASING.md) (Japanese) for details.
|
|
709
777
|
|
|
710
|
-
- Official data updates (new, moved and one-off holidays by law, Official Gazette or proclamation, fixed equinox days in Japan, newly published years on GOV.UK) are released as **patch** versions, so they reach you with either `^` or `~`
|
|
778
|
+
- Official data updates (new, moved and one-off holidays by law, Official Gazette or proclamation, fixed equinox days in Japan, newly published years on GOV.UK, newly gazetted years and revised dates in Singapore) are released as **patch** versions, so they reach you with either `^` or `~`
|
|
711
779
|
- To freeze the holiday results, pin an exact version (for example `"bizdays-toolkit": "0.8.0"`)
|
|
712
|
-
- The reflected data is shown by the provider's `dataVersion` (for Japan, the year and month of the Official Gazette reflected; for the UK, the year and month of the GOV.UK data reflected) and `confirmedThrough` (`jp.dataVersion`, `england.confirmedThrough` and so on). The module-level constants `dataVersion` and `confirmedThrough` in `bizdays-toolkit/jp` and `bizdays-toolkit/uk` are deprecated since 0.12.0 and will be removed in 1.0.0
|
|
780
|
+
- The reflected data is shown by the provider's `dataVersion` (for Japan, the year and month of the Official Gazette reflected; for the UK and Singapore, the year and month of the GOV.UK or data.gov.sg data reflected) and `confirmedThrough` (`jp.dataVersion`, `england.confirmedThrough` and so on). The module-level constants `dataVersion` and `confirmedThrough` in `bizdays-toolkit/jp` and `bizdays-toolkit/uk` are deprecated since 0.12.0 and will be removed in 1.0.0
|
|
713
781
|
- Before 1.0.0, minor versions may contain breaking changes. What you need to change when moving between minor versions is listed in the [migration guide](https://github.com/inohan77/bizdays-toolkit/blob/main/docs/migration.md) (Japanese) and in the "移行" (migration) part of each version in the CHANGELOG
|
|
714
782
|
- Decision reasons (`reason`), holiday kinds (`kind`), error codes and diagnostic codes may gain values in future versions. When you branch on their values, handle "anything else" too (see "互換性の約束", the compatibility promise, in [RELEASING.md](https://github.com/inohan77/bizdays-toolkit/blob/main/RELEASING.md))
|
|
715
783
|
|
|
@@ -719,7 +787,9 @@ Japanese holidays are verified with the "National Holidays" CSV published on the
|
|
|
719
787
|
|
|
720
788
|
UK bank holidays are verified with the GOV.UK bank holidays data (<https://www.gov.uk/bank-holidays.json>, and for earlier years the history of the official GOV.UK repositories [alphagov/calendars](https://github.com/alphagov/calendars) and [alphagov/frontend](https://github.com/alphagov/frontend)), and the Welsh names of the Wales holidays with the Welsh version of GOV.UK (the verification data is a test fixture only; not included in the package).
|
|
721
789
|
|
|
722
|
-
|
|
790
|
+
Singapore public holidays are verified with the "Singapore Public Holidays" collection published by the Ministry of Manpower on data.gov.sg (<https://data.gov.sg/collections/691/view>), with the Ministry's press releases as the authority where the two differ (the verification data is a test fixture only; not included in the package).
|
|
791
|
+
|
|
792
|
+
Contains public sector information licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/), and data from data.gov.sg made available under the [Singapore Open Data Licence](https://data.gov.sg/open-data-licence).
|
|
723
793
|
|
|
724
794
|
## License
|
|
725
795
|
|
package/dist/core/calendar.js
CHANGED
|
@@ -27,6 +27,7 @@ const CALENDAR_OPTION_KEYS = [
|
|
|
27
27
|
"holidays",
|
|
28
28
|
"timeZone",
|
|
29
29
|
"outOfRange",
|
|
30
|
+
"unconfirmedHolidays",
|
|
30
31
|
"closedWeekdays",
|
|
31
32
|
"closedAnnual",
|
|
32
33
|
"closedDates",
|
|
@@ -264,6 +265,7 @@ function buildCalendar(lookup, isOpen, info, maxSearchDays) {
|
|
|
264
265
|
timeZone: lookup.timeZone,
|
|
265
266
|
providers: lookup.providers,
|
|
266
267
|
outOfRange: lookup.outOfRange,
|
|
268
|
+
unconfirmedHolidays: lookup.unconfirmedHolidays,
|
|
267
269
|
dateOf,
|
|
268
270
|
civilOf: lookup.civilOf,
|
|
269
271
|
instantOf: lookup.instantOf,
|
|
@@ -401,6 +403,10 @@ export function combineCalendars(calendars, options) {
|
|
|
401
403
|
providers: Object.freeze(providers),
|
|
402
404
|
timeZone: zones[0],
|
|
403
405
|
outOfRange: calendars.every((c) => c.outOfRange === "ignore") ? "ignore" : "throw",
|
|
406
|
+
// 未確定の祝日も同じ考え方: どれかが "throw" なら、そのカレンダーの判定が例外になるので合成の holiday も "throw"
|
|
407
|
+
unconfirmedHolidays: calendars.some((c) => c.unconfirmedHolidays === "throw")
|
|
408
|
+
? "throw"
|
|
409
|
+
: "accept",
|
|
404
410
|
});
|
|
405
411
|
const isOpen = (date) => mode === "all"
|
|
406
412
|
? calendars.every((c) => c.isBusinessDay(date))
|
package/dist/core/diagnose.d.ts
CHANGED
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
* never-matches … 当てはまる日がない繰り返しの規則(2 月 30 日、有効期間の中に第 5 水曜日がない、提供元のない設定の祝日の翌日・祝前日、など)
|
|
12
12
|
* out-of-range … 個別の日付、または規則の有効期間が祝日の提供元の対応年の外にある(relatedPath に提供元)
|
|
13
13
|
* no-business-day … 営業日が 1 日もない設定(営業日カレンダーのみ)
|
|
14
|
-
* - info … redundant:
|
|
14
|
+
* - info … redundant: 取り除いても結果が変わらない規則・設定(判定に祝日を使わない設定の unconfirmedHolidays: "throw" を含む)
|
|
15
|
+
* expired: 第 2 引数の asOf より前に終わった規則・日付(asOf を渡したときだけ)
|
|
16
|
+
*
|
|
17
|
+
* 未確定の祝日の扱い(unconfirmedHolidays)は診断では常に "accept" で評価する。診断は設定の形を調べるもので、
|
|
18
|
+
* 祝日が確定しているかどうかは関係がなく、"throw" のまま評価すると例外を握りつぶして「当てはまらない」と誤判定するため
|
|
15
19
|
*
|
|
16
20
|
* 判定の順番(個別の日付 → 毎年の月日 → 繰り返し(over)→ 祝日 → 繰り返し(under・振替先)→ 曜日)は
|
|
17
21
|
* 固定なので、shadowed は同じ種類の規則どうしに限って調べる。種類をまたいで使われない規則は
|
|
@@ -19,6 +23,7 @@
|
|
|
19
23
|
* 有効期間(effectiveFrom・effectiveTo)のある規則は期間の包含も、周期(interval)のある規則は周期の包含も
|
|
20
24
|
* shadowed の条件にする。redundant の走査の範囲は、周期がそろう長さと、範囲の外にある有効期間まで広げる
|
|
21
25
|
*/
|
|
26
|
+
import { type DateString } from "./date.ts";
|
|
22
27
|
import { type CalendarOptions } from "./calendar.ts";
|
|
23
28
|
import { type KnownErrorCode } from "./errors.ts";
|
|
24
29
|
import { type ScheduleOptions } from "./schedule.ts";
|
|
@@ -44,7 +49,9 @@ export type KnownDiagnosticCode = KnownErrorCode
|
|
|
44
49
|
/** 当てはまる日がない繰り返しの規則 */
|
|
45
50
|
| "never-matches"
|
|
46
51
|
/** 取り除いても結果が変わらない */
|
|
47
|
-
| "redundant"
|
|
52
|
+
| "redundant"
|
|
53
|
+
/** 基準日(asOf)より前に終わった規則・日付(整理の候補) */
|
|
54
|
+
| "expired";
|
|
48
55
|
/**
|
|
49
56
|
* 診断コード。将来の版で値が増えることがあるので、分岐では「その他」も扱うこと。
|
|
50
57
|
* @public
|
|
@@ -63,6 +70,18 @@ export interface Diagnostic {
|
|
|
63
70
|
/** 関係する別の位置(shadowed では覆っている先の規則、out-of-range では祝日の提供元) */
|
|
64
71
|
readonly relatedPath?: string;
|
|
65
72
|
}
|
|
73
|
+
/** 診断を実行する。祝日の提供元の誤り(年ごとに初めて使うときに分かる)も error として返す */
|
|
74
|
+
/**
|
|
75
|
+
* 診断のオプション(第 2 引数)。
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
export interface DiagnoseOptions {
|
|
79
|
+
/**
|
|
80
|
+
* 基準日 "YYYY-MM-DD"。指定すると、この日より前に終わった規則・日付(有効期間の effectiveTo、個別の日付・期間の終わり)を
|
|
81
|
+
* info の expired として返す(整理の候補)。省略時は返さない(現在時刻は使わず、結果を決定的に保つ)
|
|
82
|
+
*/
|
|
83
|
+
readonly asOf?: DateString;
|
|
84
|
+
}
|
|
66
85
|
/**
|
|
67
86
|
* 営業日カレンダーの設定を診断する。例外は投げず、見つけた問題を返す(問題がなければ空の配列)。
|
|
68
87
|
*
|
|
@@ -70,7 +89,7 @@ export interface Diagnostic {
|
|
|
70
89
|
* JavaScript から渡された型の合わない設定も受け付ける。
|
|
71
90
|
* @public
|
|
72
91
|
*/
|
|
73
|
-
export declare function diagnoseCalendar(options?: CalendarOptions | object): readonly Diagnostic[];
|
|
92
|
+
export declare function diagnoseCalendar(options?: CalendarOptions | object, diagnoseOptions?: DiagnoseOptions): readonly Diagnostic[];
|
|
74
93
|
/**
|
|
75
94
|
* スケジュールの設定を診断する。例外は投げず、見つけた問題を返す(問題がなければ空の配列)。
|
|
76
95
|
*
|
|
@@ -78,4 +97,4 @@ export declare function diagnoseCalendar(options?: CalendarOptions | object): re
|
|
|
78
97
|
* error があるときは、規則どうしの診断(shadowed・redundant など)は行わない。
|
|
79
98
|
* @public
|
|
80
99
|
*/
|
|
81
|
-
export declare function diagnoseSchedule(options: ScheduleOptions<unknown> | object): readonly Diagnostic[];
|
|
100
|
+
export declare function diagnoseSchedule(options: ScheduleOptions<unknown> | object, diagnoseOptions?: DiagnoseOptions): readonly Diagnostic[];
|
package/dist/core/diagnose.js
CHANGED
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
* never-matches … 当てはまる日がない繰り返しの規則(2 月 30 日、有効期間の中に第 5 水曜日がない、提供元のない設定の祝日の翌日・祝前日、など)
|
|
12
12
|
* out-of-range … 個別の日付、または規則の有効期間が祝日の提供元の対応年の外にある(relatedPath に提供元)
|
|
13
13
|
* no-business-day … 営業日が 1 日もない設定(営業日カレンダーのみ)
|
|
14
|
-
* - info … redundant:
|
|
14
|
+
* - info … redundant: 取り除いても結果が変わらない規則・設定(判定に祝日を使わない設定の unconfirmedHolidays: "throw" を含む)
|
|
15
|
+
* expired: 第 2 引数の asOf より前に終わった規則・日付(asOf を渡したときだけ)
|
|
16
|
+
*
|
|
17
|
+
* 未確定の祝日の扱い(unconfirmedHolidays)は診断では常に "accept" で評価する。診断は設定の形を調べるもので、
|
|
18
|
+
* 祝日が確定しているかどうかは関係がなく、"throw" のまま評価すると例外を握りつぶして「当てはまらない」と誤判定するため
|
|
15
19
|
*
|
|
16
20
|
* 判定の順番(個別の日付 → 毎年の月日 → 繰り返し(over)→ 祝日 → 繰り返し(under・振替先)→ 曜日)は
|
|
17
21
|
* 固定なので、shadowed は同じ種類の規則どうしに限って調べる。種類をまたいで使われない規則は
|
|
@@ -19,9 +23,9 @@
|
|
|
19
23
|
* 有効期間(effectiveFrom・effectiveTo)のある規則は期間の包含も、周期(interval)のある規則は周期の包含も
|
|
20
24
|
* shadowed の条件にする。redundant の走査の範囲は、周期がそろう長さと、範囲の外にある有効期間まで広げる
|
|
21
25
|
*/
|
|
22
|
-
import { daysInMonth, fromDayNumber, parseDate, toDayNumber } from "./date.js";
|
|
26
|
+
import { daysInMonth, fromDayNumber, isValidDate, parseDate, toDayNumber, } from "./date.js";
|
|
23
27
|
import { compileCalendarOptions } from "./calendar.js";
|
|
24
|
-
import { IssueCollector } from "./errors.js";
|
|
28
|
+
import { IssueCollector, rangeError } from "./errors.js";
|
|
25
29
|
import { compileScheduleOptions, createHolidayLookup, createResolver, inPeriod, matchMonthDay, matchPattern, } from "./schedule.js";
|
|
26
30
|
// ------------------------------------------------------------
|
|
27
31
|
// 知らないキーの候補
|
|
@@ -306,7 +310,7 @@ function analyze(c, compiled, isCalendar) {
|
|
|
306
310
|
const { source, dates, annual, recurring } = compiled;
|
|
307
311
|
if (!checkProviderData(c, source))
|
|
308
312
|
return;
|
|
309
|
-
const lookup = createHolidayLookup(source);
|
|
313
|
+
const lookup = createHolidayLookup({ ...source, unconfirmedHolidays: "accept" });
|
|
310
314
|
const cycle = patternCycle(recurring);
|
|
311
315
|
const window = scanWindow(source, [...annual, ...recurring], cycle);
|
|
312
316
|
/** 使われないことが分かった規則(redundant を重ねて出さない) */
|
|
@@ -487,9 +491,59 @@ function analyze(c, compiled, isCalendar) {
|
|
|
487
491
|
: `Removing this rule does not change any result (checked ${window.label})`);
|
|
488
492
|
}
|
|
489
493
|
}
|
|
490
|
-
/**
|
|
491
|
-
function
|
|
494
|
+
/** 第 2 引数を検証する(設定の誤りは診断結果で返すが、引数の誤りは例外。知らないキーは無視する) */
|
|
495
|
+
function compileDiagnoseOptions(options) {
|
|
496
|
+
if (options === undefined)
|
|
497
|
+
return { asOf: null };
|
|
498
|
+
if (typeof options !== "object" || options === null || Array.isArray(options)) {
|
|
499
|
+
throw rangeError("invalid-argument", "the second argument must be an object of diagnose options");
|
|
500
|
+
}
|
|
501
|
+
const asOf = options.asOf;
|
|
502
|
+
if (asOf === undefined)
|
|
503
|
+
return { asOf: null };
|
|
504
|
+
if (!isValidDate(asOf)) {
|
|
505
|
+
throw rangeError("invalid-date", `asOf must be a date string "YYYY-MM-DD": ${JSON.stringify(asOf)}`);
|
|
506
|
+
}
|
|
507
|
+
return { asOf: toDayNumber(asOf) };
|
|
508
|
+
}
|
|
509
|
+
/** 基準日より前に終わった規則・日付を expired にする(暦日の大小比較だけで、祝日は引かない) */
|
|
510
|
+
function checkExpired(c, compiled, asOf) {
|
|
511
|
+
const ended = (path, last, what) => {
|
|
512
|
+
if (last < asOf) {
|
|
513
|
+
c.info("expired", path, `This ${what} ended on ${fromDayNumber(last)}, before ${fromDayNumber(asOf)}; it no longer affects results and can be removed if the past need not be reproduced`);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
for (const r of compiled.dates)
|
|
517
|
+
ended(r.path, r.to, "date");
|
|
518
|
+
for (const r of compiled.annual)
|
|
519
|
+
if (r.effectiveTo !== null)
|
|
520
|
+
ended(r.path, r.effectiveTo, "rule");
|
|
521
|
+
for (const r of compiled.recurring)
|
|
522
|
+
if (r.effectiveTo !== null)
|
|
523
|
+
ended(r.path, r.effectiveTo, "rule");
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* 判定に祝日を使わない設定(提供元がない、または holidayPolicy: "ignore" / holiday: "weekday" で祝日に従属する規則もない)の
|
|
527
|
+
* unconfirmedHolidays: "throw" は、結果に影響しないので redundant にする。dayInfo が holiday を付けるために祝日を引くので実行時には投げるが、
|
|
528
|
+
* 投げても結果が変わらない設定であることを知らせる
|
|
529
|
+
*/
|
|
530
|
+
function checkUnconfirmedOption(c, compiled, isCalendar) {
|
|
531
|
+
if (compiled.source.unconfirmedHolidays !== "throw")
|
|
532
|
+
return;
|
|
533
|
+
const noProvider = compiled.source.providers.length === 0;
|
|
534
|
+
const holidayUnused = compiled.holiday === "weekday" &&
|
|
535
|
+
!compiled.recurring.some((r) => r.holiday || r.dayAfterHoliday || r.dayBeforeHoliday || r.onHolidayRule === "after-holiday");
|
|
536
|
+
if (!noProvider && !holidayUnused)
|
|
537
|
+
return;
|
|
538
|
+
c.info("redundant", "unconfirmedHolidays", noProvider
|
|
539
|
+
? 'unconfirmedHolidays: "throw" has no effect: there is no holiday provider'
|
|
540
|
+
: `unconfirmedHolidays: "throw" has no effect on results: holidays are not used (${isCalendar ? 'holidayPolicy: "ignore"' : 'holiday: "weekday"'} and no holiday-based rule); dayInfo still throws when it looks up the holiday to report`);
|
|
541
|
+
}
|
|
542
|
+
function run(c, compiled, isCalendar, asOf) {
|
|
492
543
|
if (compiled && !c.hasErrors) {
|
|
544
|
+
if (asOf !== null)
|
|
545
|
+
checkExpired(c, compiled, asOf);
|
|
546
|
+
checkUnconfirmedOption(c, compiled, isCalendar);
|
|
493
547
|
const before = c.issues.length;
|
|
494
548
|
try {
|
|
495
549
|
analyze(c, compiled, isCalendar);
|
|
@@ -518,10 +572,11 @@ function run(c, compiled, isCalendar) {
|
|
|
518
572
|
* JavaScript から渡された型の合わない設定も受け付ける。
|
|
519
573
|
* @public
|
|
520
574
|
*/
|
|
521
|
-
export function diagnoseCalendar(options = {}) {
|
|
575
|
+
export function diagnoseCalendar(options = {}, diagnoseOptions) {
|
|
576
|
+
const { asOf } = compileDiagnoseOptions(diagnoseOptions);
|
|
522
577
|
const c = new IssueCollector();
|
|
523
578
|
const compiled = compileCalendarOptions(c, options);
|
|
524
|
-
return run(c, compiled?.schedule, true);
|
|
579
|
+
return run(c, compiled?.schedule, true, asOf);
|
|
525
580
|
}
|
|
526
581
|
/**
|
|
527
582
|
* スケジュールの設定を診断する。例外は投げず、見つけた問題を返す(問題がなければ空の配列)。
|
|
@@ -530,8 +585,9 @@ export function diagnoseCalendar(options = {}) {
|
|
|
530
585
|
* error があるときは、規則どうしの診断(shadowed・redundant など)は行わない。
|
|
531
586
|
* @public
|
|
532
587
|
*/
|
|
533
|
-
export function diagnoseSchedule(options) {
|
|
588
|
+
export function diagnoseSchedule(options, diagnoseOptions) {
|
|
589
|
+
const { asOf } = compileDiagnoseOptions(diagnoseOptions);
|
|
534
590
|
const c = new IssueCollector();
|
|
535
591
|
const compiled = compileScheduleOptions(c, options);
|
|
536
|
-
return run(c, compiled, false);
|
|
592
|
+
return run(c, compiled, false, asOf);
|
|
537
593
|
}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -34,6 +34,8 @@ export type KnownErrorCode =
|
|
|
34
34
|
| "time-zone-conflict"
|
|
35
35
|
/** 対応している年の範囲の外 */
|
|
36
36
|
| "out-of-range"
|
|
37
|
+
/** 判定が未確定の祝日(confirmed: false)に触れた(unconfirmedHolidays: "throw") */
|
|
38
|
+
| "unconfirmed-holiday"
|
|
37
39
|
/** 祝日の提供元の形式の誤り */
|
|
38
40
|
| "invalid-provider"
|
|
39
41
|
/** 祝日の提供元が返したデータの誤り */
|
package/dist/core/schedule.d.ts
CHANGED
|
@@ -252,6 +252,14 @@ export interface HolidaySourceOptions<Kind extends string = string> {
|
|
|
252
252
|
readonly timeZone?: string;
|
|
253
253
|
/** 祝日の提供元の対応年を外れた日付の扱い(既定: "throw") */
|
|
254
254
|
readonly outOfRange?: "throw" | "ignore";
|
|
255
|
+
/**
|
|
256
|
+
* 判定が未確定の祝日(提供元の confirmed: false。日本の春分の日・秋分の日の予測など)に触れたときの扱い(既定: "accept")。
|
|
257
|
+
* "throw" にすると、dayInfo・isBusinessDay に限らず、営業日の探索・調整・期日の計算の途中で評価した日や、祝日の翌日・祝前日の
|
|
258
|
+
* 規則が見る隣の日を含め、祝日を引いた日が未確定の祝日なら unconfirmed-holiday の RangeError を投げる。
|
|
259
|
+
* holidaysInYear・holidaysBetween は投げないので、影響する日の列挙に使える。
|
|
260
|
+
* 判定に祝日を使う設定(holidayPolicy が "ignore" でない、または祝日に従属する規則がある)でだけ意味がある
|
|
261
|
+
*/
|
|
262
|
+
readonly unconfirmedHolidays?: "accept" | "throw";
|
|
255
263
|
}
|
|
256
264
|
/**
|
|
257
265
|
* スケジュールの設定。
|
|
@@ -313,6 +321,8 @@ export interface HolidayLookup<Kind extends string = string> {
|
|
|
313
321
|
readonly providers: readonly HolidayProvider<Kind>[];
|
|
314
322
|
/** 祝日の提供元の対応年を外れた日付の扱い(設定の outOfRange) */
|
|
315
323
|
readonly outOfRange: "throw" | "ignore";
|
|
324
|
+
/** 未確定の祝日に触れたときの扱い(設定の unconfirmedHolidays) */
|
|
325
|
+
readonly unconfirmedHolidays: "accept" | "throw";
|
|
316
326
|
/** 入力をタイムゾーンでの暦日に変換する */
|
|
317
327
|
dateOf(input: DateInput): DateString;
|
|
318
328
|
/** 入力をタイムゾーンでの暦日と時刻に変換する */
|
|
@@ -432,6 +442,7 @@ export interface HolidaySource<Kind extends string> {
|
|
|
432
442
|
readonly providers: readonly HolidayProvider<Kind>[];
|
|
433
443
|
readonly timeZone: string;
|
|
434
444
|
readonly outOfRange: "throw" | "ignore";
|
|
445
|
+
readonly unconfirmedHolidays: "accept" | "throw";
|
|
435
446
|
}
|
|
436
447
|
/** @internal 祝日の提供元とタイムゾーンの設定を検証する */
|
|
437
448
|
export declare function compileHolidaySource<Kind extends string>(c: IssueCollector, options: Record<string, unknown>): HolidaySource<Kind>;
|
package/dist/core/schedule.js
CHANGED
|
@@ -494,10 +494,15 @@ export function compileHolidaySource(c, options) {
|
|
|
494
494
|
if (outOfRange !== "throw" && outOfRange !== "ignore") {
|
|
495
495
|
c.error("invalid-option", "outOfRange", 'must be "throw" or "ignore"');
|
|
496
496
|
}
|
|
497
|
+
const unconfirmed = options["unconfirmedHolidays"] ?? "accept";
|
|
498
|
+
if (unconfirmed !== "accept" && unconfirmed !== "throw") {
|
|
499
|
+
c.error("invalid-option", "unconfirmedHolidays", 'must be "accept" or "throw"');
|
|
500
|
+
}
|
|
497
501
|
return {
|
|
498
502
|
providers: Object.freeze(providers),
|
|
499
503
|
timeZone,
|
|
500
504
|
outOfRange: outOfRange === "ignore" ? "ignore" : "throw",
|
|
505
|
+
unconfirmedHolidays: unconfirmed === "throw" ? "throw" : "accept",
|
|
501
506
|
};
|
|
502
507
|
}
|
|
503
508
|
// ------------------------------------------------------------
|
|
@@ -570,7 +575,7 @@ function checkNames(names) {
|
|
|
570
575
|
}
|
|
571
576
|
/** @internal 祝日を調べる機能を作る(設定は検証済みであること) */
|
|
572
577
|
export function createHolidayLookup(source) {
|
|
573
|
-
const { providers, timeZone, outOfRange } = source;
|
|
578
|
+
const { providers, timeZone, outOfRange, unconfirmedHolidays } = source;
|
|
574
579
|
const yearCache = new Map();
|
|
575
580
|
function holidayMap(year) {
|
|
576
581
|
let map = yearCache.get(year);
|
|
@@ -596,7 +601,20 @@ export function createHolidayLookup(source) {
|
|
|
596
601
|
function holidayOn(date) {
|
|
597
602
|
if (providers.length === 0)
|
|
598
603
|
return undefined;
|
|
599
|
-
|
|
604
|
+
const h = holidayMap(parseDate(date).year).get(date);
|
|
605
|
+
// 判定に使う祝日が未確定なら止める(holidaysInYear・holidaysBetween はこの経路を通らないので投げない)
|
|
606
|
+
if (h !== undefined && unconfirmedHolidays === "throw" && !h.confirmed) {
|
|
607
|
+
// どの提供元の予測かを添える(提供元の confirmedThrough は、利用者が再計算の時期を知る手がかり)
|
|
608
|
+
const year = parseDate(date).year;
|
|
609
|
+
const provider = providers.find((p) => year >= p.supportedYears.from &&
|
|
610
|
+
year <= p.supportedYears.to &&
|
|
611
|
+
loadProviderYear(p, year).some((x) => x.date === date && !x.confirmed));
|
|
612
|
+
const through = provider?.confirmedThrough === undefined
|
|
613
|
+
? ""
|
|
614
|
+
: ` (${provider.id} is confirmed through ${provider.confirmedThrough})`;
|
|
615
|
+
throw rangeError("unconfirmed-holiday", `${date} ${h.name} is not yet confirmed${through}; the result would depend on a predicted holiday`);
|
|
616
|
+
}
|
|
617
|
+
return h;
|
|
600
618
|
}
|
|
601
619
|
const dateOf = (input) => toCivil(input, timeZone).date;
|
|
602
620
|
function holidaysInYear(year) {
|
|
@@ -608,6 +626,7 @@ export function createHolidayLookup(source) {
|
|
|
608
626
|
timeZone,
|
|
609
627
|
providers,
|
|
610
628
|
outOfRange,
|
|
629
|
+
unconfirmedHolidays,
|
|
611
630
|
holidayOn,
|
|
612
631
|
dateOf,
|
|
613
632
|
civilOf: ((input) => toDateTimeParts(input, timeZone)),
|
|
@@ -635,6 +654,7 @@ const SCHEDULE_OPTION_KEYS = [
|
|
|
635
654
|
"holidays",
|
|
636
655
|
"timeZone",
|
|
637
656
|
"outOfRange",
|
|
657
|
+
"unconfirmedHolidays",
|
|
638
658
|
"weekly",
|
|
639
659
|
"holiday",
|
|
640
660
|
"annual",
|
|
@@ -722,8 +742,11 @@ export function createResolver(compiled, lookup) {
|
|
|
722
742
|
try {
|
|
723
743
|
return lookup.holidayOn(date);
|
|
724
744
|
}
|
|
725
|
-
catch {
|
|
726
|
-
|
|
745
|
+
catch (error) {
|
|
746
|
+
// 飲み込むのは対応年の外だけ。未確定の祝日(unconfirmed-holiday)などはそのまま投げる
|
|
747
|
+
if (error?.code === "out-of-range")
|
|
748
|
+
return undefined;
|
|
749
|
+
throw error;
|
|
727
750
|
}
|
|
728
751
|
}
|
|
729
752
|
const isHolidaySafe = (date) => holidayOfSafe(date) !== undefined;
|
|
@@ -831,6 +854,7 @@ export function buildSchedule(compiled) {
|
|
|
831
854
|
timeZone: lookup.timeZone,
|
|
832
855
|
providers: lookup.providers,
|
|
833
856
|
outOfRange: lookup.outOfRange,
|
|
857
|
+
unconfirmedHolidays: lookup.unconfirmedHolidays,
|
|
834
858
|
dateOf: lookup.dateOf,
|
|
835
859
|
civilOf: lookup.civilOf,
|
|
836
860
|
instantOf: lookup.instantOf,
|
package/dist/diagnose/index.d.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* 営業日カレンダー・スケジュールの設定を調べ、誤り・使われない規則・打ち間違いなどを返す。
|
|
5
5
|
* 開発やテストで使う道具なので、アプリの本体のバンドルに入らないようサブパスに分けている。
|
|
6
6
|
*/
|
|
7
|
-
export { diagnoseCalendar, diagnoseSchedule, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type KnownDiagnosticCode, } from "../core/diagnose.ts";
|
|
7
|
+
export { diagnoseCalendar, diagnoseSchedule, type DiagnoseOptions, type Diagnostic, type DiagnosticCode, type DiagnosticSeverity, type KnownDiagnosticCode, } from "../core/diagnose.ts";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* シンガポールの祝日(public holidays。MOM が年ごとに告示する日付を data.gov.sg のデータで全日照合)。
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { createCalendar } from "bizdays-toolkit";
|
|
6
|
+
* import { sg } from "bizdays-toolkit/sg";
|
|
7
|
+
* const calendar = createCalendar({ holidays: sg, closedWeekdays: [0, 6] });
|
|
8
|
+
*/
|
|
9
|
+
import type { Holiday, HolidayProvider } from "../core/types.ts";
|
|
10
|
+
import { type SgHolidayKind } from "./rules.ts";
|
|
11
|
+
export type { KnownSgHolidayKind, SgHolidayKind } from "./rules.ts";
|
|
12
|
+
/**
|
|
13
|
+
* シンガポールの祝日。
|
|
14
|
+
* @public
|
|
15
|
+
*/
|
|
16
|
+
export type SgHoliday = Holiday<SgHolidayKind>;
|
|
17
|
+
/**
|
|
18
|
+
* シンガポールの祝日の提供元。対応年は MOM が告示した年(2020 年〜)だけで、それより後の年は予測せず out-of-range
|
|
19
|
+
* (旧正月・Hari Raya・Vesak Day・Deepavali は規則で計算できないため)。日曜日に当たる祝日の振替(kind: "substitute")は
|
|
20
|
+
* Holidays Act の規則で計算する。
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export declare const sg: HolidayProvider<SgHolidayKind>;
|
package/dist/sg/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* シンガポールの祝日(public holidays。MOM が年ごとに告示する日付を data.gov.sg のデータで全日照合)。
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* import { createCalendar } from "bizdays-toolkit";
|
|
6
|
+
* import { sg } from "bizdays-toolkit/sg";
|
|
7
|
+
* const calendar = createCalendar({ holidays: sg, closedWeekdays: [0, 6] });
|
|
8
|
+
*/
|
|
9
|
+
import { CONFIRMED_THROUGH, DATA_VERSION, SUPPORTED_YEARS, computeSgHolidays, } from "./rules.js";
|
|
10
|
+
const cache = new Map();
|
|
11
|
+
/**
|
|
12
|
+
* シンガポールの祝日の提供元。対応年は MOM が告示した年(2020 年〜)だけで、それより後の年は予測せず out-of-range
|
|
13
|
+
* (旧正月・Hari Raya・Vesak Day・Deepavali は規則で計算できないため)。日曜日に当たる祝日の振替(kind: "substitute")は
|
|
14
|
+
* Holidays Act の規則で計算する。
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export const sg = Object.freeze({
|
|
18
|
+
id: "SG",
|
|
19
|
+
timeZone: "Asia/Singapore",
|
|
20
|
+
supportedYears: SUPPORTED_YEARS,
|
|
21
|
+
dataVersion: DATA_VERSION,
|
|
22
|
+
confirmedThrough: CONFIRMED_THROUGH,
|
|
23
|
+
holidaysInYear(year) {
|
|
24
|
+
let list = cache.get(year);
|
|
25
|
+
if (!list) {
|
|
26
|
+
list = Object.freeze(computeSgHolidays(year));
|
|
27
|
+
cache.set(year, list);
|
|
28
|
+
}
|
|
29
|
+
return list;
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* シンガポールの祝日(public holidays)の表と振替の規則。
|
|
3
|
+
*
|
|
4
|
+
* 旧正月・Hari Raya・Vesak Day・Deepavali は太陰暦・イスラム暦・ヒンドゥー暦で決まり、規則では計算できない。
|
|
5
|
+
* 日本・英国と違い、年ごとに MOM(Ministry of Manpower)が官報で告示した日付を正として表で持つ。
|
|
6
|
+
* 振替だけは Holidays Act(1998 年版)第 4 条の規則「日曜日に当たる祝日は、その翌日のうちそれ自体が祝日でない
|
|
7
|
+
* 最初の日を祝日とする」で計算し、表には書かない。土曜日に当たる祝日は振替にならない(雇用主が休みか手当を与える)。
|
|
8
|
+
*
|
|
9
|
+
* 名称は MOM の報道発表の綴り(アポストロフィは ’)。data.gov.sg のコレクション 691(MOM)のデータで
|
|
10
|
+
* 全日照合している(test/fixtures/datagovsg-public-holidays.json)。data.gov.sg の 2022 年分は MOM の改定後の告示と
|
|
11
|
+
* 食い違う(scripts/verify-datagovsg.ts の KNOWN_DIFFERENCES)ため、告示を正としている。
|
|
12
|
+
*/
|
|
13
|
+
import type { Holiday } from "../core/types.ts";
|
|
14
|
+
/**
|
|
15
|
+
* シンガポールの祝日の種別(既知の値)。
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export type KnownSgHolidayKind =
|
|
19
|
+
/** 毎年の祝日(Holidays Act の別表と、年ごとに告示される日付) */
|
|
20
|
+
"regular"
|
|
21
|
+
/** 日曜日に当たった祝日の振替(Holidays Act 第 4 条) */
|
|
22
|
+
| "substitute"
|
|
23
|
+
/** 告示による臨時の祝日(Polling Day など) */
|
|
24
|
+
| "special";
|
|
25
|
+
/**
|
|
26
|
+
* シンガポールの祝日の種別。将来の版で値が増えることがあるので、分岐では「その他」も扱うこと。
|
|
27
|
+
* すべての値を網羅したことを型で確かめたい場合は KnownSgHolidayKind を使う。
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export type SgHolidayKind = KnownSgHolidayKind | (string & {});
|
|
31
|
+
/** @internal 対応年(表のある年。それより後は予測できないので out-of-range) */
|
|
32
|
+
export declare const SUPPORTED_YEARS: Readonly<{
|
|
33
|
+
from: 2020;
|
|
34
|
+
to: 2027;
|
|
35
|
+
}>;
|
|
36
|
+
/** @internal MOM が日付を告示している最後の年(対応年の終わりと同じ。表の年はすべて確定) */
|
|
37
|
+
export declare const CONFIRMED_THROUGH = 2027;
|
|
38
|
+
/** @internal 反映済みの data.gov.sg のコレクション 691 の更新年月(2027 年分の公開) */
|
|
39
|
+
export declare const DATA_VERSION = "2026-07";
|
|
40
|
+
/** @internal その年の祝日(表と振替の規則から。日付順) */
|
|
41
|
+
export declare function computeSgHolidays(year: number): Holiday<SgHolidayKind>[];
|
package/dist/sg/rules.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* シンガポールの祝日(public holidays)の表と振替の規則。
|
|
3
|
+
*
|
|
4
|
+
* 旧正月・Hari Raya・Vesak Day・Deepavali は太陰暦・イスラム暦・ヒンドゥー暦で決まり、規則では計算できない。
|
|
5
|
+
* 日本・英国と違い、年ごとに MOM(Ministry of Manpower)が官報で告示した日付を正として表で持つ。
|
|
6
|
+
* 振替だけは Holidays Act(1998 年版)第 4 条の規則「日曜日に当たる祝日は、その翌日のうちそれ自体が祝日でない
|
|
7
|
+
* 最初の日を祝日とする」で計算し、表には書かない。土曜日に当たる祝日は振替にならない(雇用主が休みか手当を与える)。
|
|
8
|
+
*
|
|
9
|
+
* 名称は MOM の報道発表の綴り(アポストロフィは ’)。data.gov.sg のコレクション 691(MOM)のデータで
|
|
10
|
+
* 全日照合している(test/fixtures/datagovsg-public-holidays.json)。data.gov.sg の 2022 年分は MOM の改定後の告示と
|
|
11
|
+
* 食い違う(scripts/verify-datagovsg.ts の KNOWN_DIFFERENCES)ため、告示を正としている。
|
|
12
|
+
*/
|
|
13
|
+
import { addDays, formatDate, weekdayOf } from "../core/date.js";
|
|
14
|
+
import { rangeError } from "../core/errors.js";
|
|
15
|
+
/** @internal 対応年(表のある年。それより後は予測できないので out-of-range) */
|
|
16
|
+
export const SUPPORTED_YEARS = Object.freeze({ from: 2020, to: 2027 });
|
|
17
|
+
/** @internal MOM が日付を告示している最後の年(対応年の終わりと同じ。表の年はすべて確定) */
|
|
18
|
+
export const CONFIRMED_THROUGH = 2027;
|
|
19
|
+
/** @internal 反映済みの data.gov.sg のコレクション 691 の更新年月(2027 年分の公開) */
|
|
20
|
+
export const DATA_VERSION = "2026-07";
|
|
21
|
+
const NEW_YEAR = "New Year’s Day";
|
|
22
|
+
const CNY = "Chinese New Year";
|
|
23
|
+
const GOOD_FRIDAY = "Good Friday";
|
|
24
|
+
const LABOUR = "Labour Day";
|
|
25
|
+
const PUASA = "Hari Raya Puasa";
|
|
26
|
+
const VESAK = "Vesak Day";
|
|
27
|
+
const HAJI = "Hari Raya Haji";
|
|
28
|
+
const NATIONAL = "National Day";
|
|
29
|
+
const DEEPAVALI = "Deepavali";
|
|
30
|
+
const CHRISTMAS = "Christmas Day";
|
|
31
|
+
const POLLING = "Polling Day";
|
|
32
|
+
/** 年ごとに動く祝日(月日と名前)。固定日の祝日(1/1・5/1・8/9・12/25)は表に書かず、下で足す */
|
|
33
|
+
const MOVABLE = {
|
|
34
|
+
2020: [
|
|
35
|
+
["01-25", CNY],
|
|
36
|
+
["01-26", CNY],
|
|
37
|
+
["04-10", GOOD_FRIDAY],
|
|
38
|
+
["05-07", VESAK],
|
|
39
|
+
["05-24", PUASA],
|
|
40
|
+
["07-31", HAJI],
|
|
41
|
+
["11-14", DEEPAVALI],
|
|
42
|
+
],
|
|
43
|
+
2021: [
|
|
44
|
+
["02-12", CNY],
|
|
45
|
+
["02-13", CNY],
|
|
46
|
+
["04-02", GOOD_FRIDAY],
|
|
47
|
+
["05-13", PUASA],
|
|
48
|
+
["05-26", VESAK],
|
|
49
|
+
["07-20", HAJI],
|
|
50
|
+
["11-04", DEEPAVALI],
|
|
51
|
+
],
|
|
52
|
+
// 2022 年の Hari Raya Puasa・Haji は 2021-10-21 の MOM の報道発表で 5/3・7/10 に改定された(data.gov.sg は改定前の形)
|
|
53
|
+
2022: [
|
|
54
|
+
["02-01", CNY],
|
|
55
|
+
["02-02", CNY],
|
|
56
|
+
["04-15", GOOD_FRIDAY],
|
|
57
|
+
["05-03", PUASA],
|
|
58
|
+
["05-15", VESAK],
|
|
59
|
+
["07-10", HAJI],
|
|
60
|
+
["10-24", DEEPAVALI],
|
|
61
|
+
],
|
|
62
|
+
2023: [
|
|
63
|
+
["01-22", CNY],
|
|
64
|
+
["01-23", CNY],
|
|
65
|
+
["04-07", GOOD_FRIDAY],
|
|
66
|
+
["04-22", PUASA],
|
|
67
|
+
["06-02", VESAK],
|
|
68
|
+
["06-29", HAJI],
|
|
69
|
+
["11-12", DEEPAVALI],
|
|
70
|
+
],
|
|
71
|
+
2024: [
|
|
72
|
+
["02-10", CNY],
|
|
73
|
+
["02-11", CNY],
|
|
74
|
+
["03-29", GOOD_FRIDAY],
|
|
75
|
+
["04-10", PUASA],
|
|
76
|
+
["05-22", VESAK],
|
|
77
|
+
["06-17", HAJI],
|
|
78
|
+
["10-31", DEEPAVALI],
|
|
79
|
+
],
|
|
80
|
+
2025: [
|
|
81
|
+
["01-29", CNY],
|
|
82
|
+
["01-30", CNY],
|
|
83
|
+
["03-31", PUASA],
|
|
84
|
+
["04-18", GOOD_FRIDAY],
|
|
85
|
+
["05-12", VESAK],
|
|
86
|
+
["06-07", HAJI],
|
|
87
|
+
["10-20", DEEPAVALI],
|
|
88
|
+
],
|
|
89
|
+
2026: [
|
|
90
|
+
["02-17", CNY],
|
|
91
|
+
["02-18", CNY],
|
|
92
|
+
["03-21", PUASA],
|
|
93
|
+
["04-03", GOOD_FRIDAY],
|
|
94
|
+
["05-27", HAJI],
|
|
95
|
+
["05-31", VESAK],
|
|
96
|
+
["11-08", DEEPAVALI],
|
|
97
|
+
],
|
|
98
|
+
2027: [
|
|
99
|
+
["02-06", CNY],
|
|
100
|
+
["02-07", CNY],
|
|
101
|
+
["03-10", PUASA],
|
|
102
|
+
["03-26", GOOD_FRIDAY],
|
|
103
|
+
["05-17", HAJI],
|
|
104
|
+
["05-20", VESAK],
|
|
105
|
+
["10-28", DEEPAVALI],
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
/** 告示による臨時の祝日(総選挙・大統領選挙の投票日) */
|
|
109
|
+
const SPECIAL_DAYS = [
|
|
110
|
+
["2020-07-10", POLLING],
|
|
111
|
+
["2023-09-01", POLLING],
|
|
112
|
+
["2025-05-03", POLLING],
|
|
113
|
+
];
|
|
114
|
+
const FIXED = [
|
|
115
|
+
[1, 1, NEW_YEAR],
|
|
116
|
+
[5, 1, LABOUR],
|
|
117
|
+
[8, 9, NATIONAL],
|
|
118
|
+
[12, 25, CHRISTMAS],
|
|
119
|
+
];
|
|
120
|
+
/** @internal その年の祝日(表と振替の規則から。日付順) */
|
|
121
|
+
export function computeSgHolidays(year) {
|
|
122
|
+
const movable = MOVABLE[year];
|
|
123
|
+
if (movable === undefined) {
|
|
124
|
+
throw rangeError("out-of-range", `Singapore public holidays are available for ${SUPPORTED_YEARS.from}-${SUPPORTED_YEARS.to}: ${year}`);
|
|
125
|
+
}
|
|
126
|
+
const entries = [
|
|
127
|
+
...FIXED.map(([m, d, name]) => ({
|
|
128
|
+
date: formatDate(year, m, d),
|
|
129
|
+
name,
|
|
130
|
+
kind: "regular",
|
|
131
|
+
})),
|
|
132
|
+
...movable.map(([md, name]) => ({
|
|
133
|
+
date: `${year}-${md}`,
|
|
134
|
+
name,
|
|
135
|
+
kind: "regular",
|
|
136
|
+
})),
|
|
137
|
+
...SPECIAL_DAYS.filter(([date]) => date.startsWith(`${year}-`)).map(([date, name]) => ({
|
|
138
|
+
date,
|
|
139
|
+
name,
|
|
140
|
+
kind: "special",
|
|
141
|
+
})),
|
|
142
|
+
].sort((a, b) => (a.date < b.date ? -1 : 1));
|
|
143
|
+
// 日曜日に当たる祝日を日付順に振り替える(振替先は、それ自体が祝日でない翌日以降の最初の日)
|
|
144
|
+
const taken = new Set(entries.map((e) => e.date));
|
|
145
|
+
const sundays = entries.filter((e) => weekdayOf(e.date) === 0);
|
|
146
|
+
for (const e of sundays) {
|
|
147
|
+
let day = addDays(e.date, 1);
|
|
148
|
+
while (taken.has(day))
|
|
149
|
+
day = addDays(day, 1);
|
|
150
|
+
entries.push({ date: day, name: e.name, kind: "substitute" });
|
|
151
|
+
taken.add(day);
|
|
152
|
+
}
|
|
153
|
+
return entries
|
|
154
|
+
.sort((a, b) => (a.date < b.date ? -1 : 1))
|
|
155
|
+
.map((e) => Object.freeze({ date: e.date, name: e.name, nameEn: e.name, kind: e.kind, confirmed: true }));
|
|
156
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bizdays-toolkit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Holidays, business-day calendar and day-by-day schedules (e.g. store hours) with time zone support. Japanese holidays verified against the Cabinet Office data; UK bank holidays (England, Wales, Scotland, Northern Ireland) verified against GOV.UK. / 祝日と営業日のカレンダー(タイムゾーン対応・日本の祝日は内閣府、英国の bank holidays は GOV.UK のデータで全日照合)",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"description": "Holidays, business-day calendar and day-by-day schedules (e.g. store hours) with time zone support. Japanese holidays verified against the Cabinet Office data; UK bank holidays (England, Wales, Scotland, Northern Ireland) verified against GOV.UK; Singapore public holidays verified against data.gov.sg. / 祝日と営業日のカレンダー(タイムゾーン対応・日本の祝日は内閣府、英国の bank holidays は GOV.UK、シンガポールの祝日は data.gov.sg のデータで全日照合)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bank-holidays",
|
|
7
7
|
"bizdays",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"holiday",
|
|
12
12
|
"holidays",
|
|
13
13
|
"japan",
|
|
14
|
+
"singapore",
|
|
14
15
|
"uk",
|
|
15
16
|
"workday",
|
|
16
17
|
"営業日",
|
|
@@ -46,6 +47,10 @@
|
|
|
46
47
|
"types": "./dist/uk/index.d.ts",
|
|
47
48
|
"default": "./dist/uk/index.js"
|
|
48
49
|
},
|
|
50
|
+
"./sg": {
|
|
51
|
+
"types": "./dist/sg/index.d.ts",
|
|
52
|
+
"default": "./dist/sg/index.js"
|
|
53
|
+
},
|
|
49
54
|
"./diagnose": {
|
|
50
55
|
"types": "./dist/diagnose/index.d.ts",
|
|
51
56
|
"default": "./dist/diagnose/index.js"
|
|
@@ -69,6 +74,7 @@
|
|
|
69
74
|
"check": "node scripts/check-toolchain.ts && pnpm typecheck && pnpm lint && pnpm test && pnpm test:tz && pnpm build && pnpm test:compat && node scripts/check-readme-examples.ts && node scripts/check-consumer-types.ts && pnpm fmt:check && node scripts/check-package.ts && node scripts/check-size.ts && node scripts/api-report.ts",
|
|
70
75
|
"verify:cao": "node scripts/verify-cao.ts",
|
|
71
76
|
"verify:govuk": "node scripts/verify-govuk.ts",
|
|
77
|
+
"verify:datagovsg": "node scripts/verify-datagovsg.ts",
|
|
72
78
|
"prepublishOnly": "pnpm check",
|
|
73
79
|
"release-notes": "node scripts/release-notes.ts",
|
|
74
80
|
"api:update": "pnpm build && node scripts/api-report.ts --update"
|