@intech-software/chronera 0.1.3 → 0.1.5
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/dist/core/local-date.d.ts +1 -0
- package/dist/core/local-date.js +1 -0
- package/dist/core/local-date.js.map +1 -1
- package/dist/format/format-pattern.js +97 -2
- package/dist/format/format-pattern.js.map +1 -1
- package/dist/format/pattern-scanner.js +9 -0
- package/dist/format/pattern-scanner.js.map +1 -1
- package/dist/holidays/countries/ae.d.ts +6 -0
- package/dist/holidays/countries/ae.js +70 -0
- package/dist/holidays/countries/ae.js.map +1 -0
- package/dist/holidays/countries/au.d.ts +6 -0
- package/dist/holidays/countries/au.js +79 -0
- package/dist/holidays/countries/au.js.map +1 -0
- package/dist/holidays/countries/cn.d.ts +6 -0
- package/dist/holidays/countries/cn.js +57 -0
- package/dist/holidays/countries/cn.js.map +1 -0
- package/dist/holidays/countries/de.d.ts +6 -0
- package/dist/holidays/countries/de.js +81 -0
- package/dist/holidays/countries/de.js.map +1 -0
- package/dist/holidays/countries/fr.d.ts +6 -0
- package/dist/holidays/countries/fr.js +97 -0
- package/dist/holidays/countries/fr.js.map +1 -0
- package/dist/holidays/countries/gb.d.ts +6 -0
- package/dist/holidays/countries/gb.js +80 -0
- package/dist/holidays/countries/gb.js.map +1 -0
- package/dist/holidays/countries/hk.d.ts +6 -0
- package/dist/holidays/countries/hk.js +87 -0
- package/dist/holidays/countries/hk.js.map +1 -0
- package/dist/holidays/countries/in.d.ts +6 -0
- package/dist/holidays/countries/in.js +52 -0
- package/dist/holidays/countries/in.js.map +1 -0
- package/dist/holidays/countries/index.d.ts +18 -0
- package/dist/holidays/countries/index.js +34 -0
- package/dist/holidays/countries/index.js.map +1 -0
- package/dist/holidays/countries/ir.d.ts +7 -0
- package/dist/holidays/countries/ir.js +93 -0
- package/dist/holidays/countries/ir.js.map +1 -0
- package/dist/holidays/countries/jp.d.ts +6 -0
- package/dist/holidays/countries/jp.js +140 -0
- package/dist/holidays/countries/jp.js.map +1 -0
- package/dist/holidays/countries/sa.d.ts +7 -0
- package/dist/holidays/countries/sa.js +56 -0
- package/dist/holidays/countries/sa.js.map +1 -0
- package/dist/holidays/countries/sg.d.ts +6 -0
- package/dist/holidays/countries/sg.js +71 -0
- package/dist/holidays/countries/sg.js.map +1 -0
- package/dist/holidays/countries/th.d.ts +6 -0
- package/dist/holidays/countries/th.js +151 -0
- package/dist/holidays/countries/th.js.map +1 -0
- package/dist/holidays/countries/tw.d.ts +6 -0
- package/dist/holidays/countries/tw.js +57 -0
- package/dist/holidays/countries/tw.js.map +1 -0
- package/dist/holidays/countries/us.d.ts +6 -0
- package/dist/holidays/countries/us.js +112 -0
- package/dist/holidays/countries/us.js.map +1 -0
- package/dist/holidays/easter.d.ts +23 -0
- package/dist/holidays/easter.js +49 -0
- package/dist/holidays/easter.js.map +1 -0
- package/dist/holidays/index.d.ts +5 -0
- package/dist/holidays/index.js +6 -0
- package/dist/holidays/index.js.map +1 -0
- package/dist/holidays/registry.d.ts +14 -0
- package/dist/holidays/registry.js +79 -0
- package/dist/holidays/registry.js.map +1 -0
- package/dist/holidays/rules/easter-rule.d.ts +5 -0
- package/dist/holidays/rules/easter-rule.js +26 -0
- package/dist/holidays/rules/easter-rule.js.map +1 -0
- package/dist/holidays/rules/fixed-rule.d.ts +5 -0
- package/dist/holidays/rules/fixed-rule.js +72 -0
- package/dist/holidays/rules/fixed-rule.js.map +1 -0
- package/dist/holidays/rules/floating-rule.d.ts +6 -0
- package/dist/holidays/rules/floating-rule.js +53 -0
- package/dist/holidays/rules/floating-rule.js.map +1 -0
- package/dist/holidays/rules/hijri-rule.d.ts +6 -0
- package/dist/holidays/rules/hijri-rule.js +44 -0
- package/dist/holidays/rules/hijri-rule.js.map +1 -0
- package/dist/holidays/rules/index.d.ts +9 -0
- package/dist/holidays/rules/index.js +26 -0
- package/dist/holidays/rules/index.js.map +1 -0
- package/dist/holidays/types.d.ts +106 -0
- package/dist/holidays/types.js +2 -0
- package/dist/holidays/types.js.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/operations/business-days.d.ts +30 -14
- package/dist/operations/business-days.js +115 -37
- package/dist/operations/business-days.js.map +1 -1
- package/dist/operations/holidays.d.ts +15 -0
- package/dist/operations/holidays.js +36 -0
- package/dist/operations/holidays.js.map +1 -0
- package/dist/operations/timezone.d.ts +28 -0
- package/dist/operations/timezone.js +120 -0
- package/dist/operations/timezone.js.map +1 -0
- package/dist/public-types.d.ts +16 -0
- package/dist/public-types.js.map +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Official Federal Public Holidays for the United States 🇺🇸
|
|
3
|
+
* Includes all 11 Federal statutory holidays with Saturday-to-Friday and Sunday-to-Monday substitution.
|
|
4
|
+
*/
|
|
5
|
+
export const unitedStatesHolidays = {
|
|
6
|
+
country: "US",
|
|
7
|
+
countryName: "United States",
|
|
8
|
+
defaultWeekendDays: [6, 7],
|
|
9
|
+
rules: [
|
|
10
|
+
{
|
|
11
|
+
type: "fixed",
|
|
12
|
+
id: "us-new-year",
|
|
13
|
+
month: 1,
|
|
14
|
+
day: 1,
|
|
15
|
+
name: "New Year's Day",
|
|
16
|
+
nameEn: "New Year's Day",
|
|
17
|
+
observed: "sat-to-fri-sun-to-mon",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
type: "floating",
|
|
21
|
+
id: "us-mlk-day",
|
|
22
|
+
month: 1,
|
|
23
|
+
weekday: 1, // Monday
|
|
24
|
+
occurrence: 3, // 3rd Monday
|
|
25
|
+
name: "Martin Luther King Jr. Day",
|
|
26
|
+
nameEn: "Martin Luther King Jr. Day",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: "floating",
|
|
30
|
+
id: "us-presidents-day",
|
|
31
|
+
month: 2,
|
|
32
|
+
weekday: 1, // Monday
|
|
33
|
+
occurrence: 3, // 3rd Monday
|
|
34
|
+
name: "Washington's Birthday (Presidents' Day)",
|
|
35
|
+
nameEn: "Washington's Birthday (Presidents' Day)",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "floating",
|
|
39
|
+
id: "us-memorial-day",
|
|
40
|
+
month: 5,
|
|
41
|
+
weekday: 1, // Monday
|
|
42
|
+
occurrence: -1, // Last Monday of May
|
|
43
|
+
name: "Memorial Day",
|
|
44
|
+
nameEn: "Memorial Day",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "fixed",
|
|
48
|
+
id: "us-juneteenth",
|
|
49
|
+
month: 6,
|
|
50
|
+
day: 19,
|
|
51
|
+
name: "Juneteenth National Independence Day",
|
|
52
|
+
nameEn: "Juneteenth National Independence Day",
|
|
53
|
+
observed: "sat-to-fri-sun-to-mon",
|
|
54
|
+
validFromYear: 2021,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "fixed",
|
|
58
|
+
id: "us-independence-day",
|
|
59
|
+
month: 7,
|
|
60
|
+
day: 4,
|
|
61
|
+
name: "Independence Day",
|
|
62
|
+
nameEn: "Independence Day",
|
|
63
|
+
observed: "sat-to-fri-sun-to-mon",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: "floating",
|
|
67
|
+
id: "us-labor-day",
|
|
68
|
+
month: 9,
|
|
69
|
+
weekday: 1, // Monday
|
|
70
|
+
occurrence: 1, // 1st Monday
|
|
71
|
+
name: "Labor Day",
|
|
72
|
+
nameEn: "Labor Day",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
type: "floating",
|
|
76
|
+
id: "us-columbus-day",
|
|
77
|
+
month: 10,
|
|
78
|
+
weekday: 1, // Monday
|
|
79
|
+
occurrence: 2, // 2nd Monday
|
|
80
|
+
name: "Columbus Day / Indigenous Peoples' Day",
|
|
81
|
+
nameEn: "Columbus Day / Indigenous Peoples' Day",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: "fixed",
|
|
85
|
+
id: "us-veterans-day",
|
|
86
|
+
month: 11,
|
|
87
|
+
day: 11,
|
|
88
|
+
name: "Veterans Day",
|
|
89
|
+
nameEn: "Veterans Day",
|
|
90
|
+
observed: "sat-to-fri-sun-to-mon",
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "floating",
|
|
94
|
+
id: "us-thanksgiving",
|
|
95
|
+
month: 11,
|
|
96
|
+
weekday: 4, // Thursday
|
|
97
|
+
occurrence: 4, // 4th Thursday
|
|
98
|
+
name: "Thanksgiving Day",
|
|
99
|
+
nameEn: "Thanksgiving Day",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
type: "fixed",
|
|
103
|
+
id: "us-christmas",
|
|
104
|
+
month: 12,
|
|
105
|
+
day: 25,
|
|
106
|
+
name: "Christmas Day",
|
|
107
|
+
nameEn: "Christmas Day",
|
|
108
|
+
observed: "sat-to-fri-sun-to-mon",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
//# sourceMappingURL=us.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"us.js","sourceRoot":"","sources":["../../../src/holidays/countries/us.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HolidayCalendar } from \"../types.js\";\n\n/**\n * Official Federal Public Holidays for the United States 🇺🇸\n * Includes all 11 Federal statutory holidays with Saturday-to-Friday and Sunday-to-Monday substitution.\n */\nexport const unitedStatesHolidays: HolidayCalendar = {\n country: \"US\",\n countryName: \"United States\",\n defaultWeekendDays: [6, 7],\n rules: [\n {\n type: \"fixed\",\n id: \"us-new-year\",\n month: 1,\n day: 1,\n name: \"New Year's Day\",\n nameEn: \"New Year's Day\",\n observed: \"sat-to-fri-sun-to-mon\",\n },\n {\n type: \"floating\",\n id: \"us-mlk-day\",\n month: 1,\n weekday: 1, // Monday\n occurrence: 3, // 3rd Monday\n name: \"Martin Luther King Jr. Day\",\n nameEn: \"Martin Luther King Jr. Day\",\n },\n {\n type: \"floating\",\n id: \"us-presidents-day\",\n month: 2,\n weekday: 1, // Monday\n occurrence: 3, // 3rd Monday\n name: \"Washington's Birthday (Presidents' Day)\",\n nameEn: \"Washington's Birthday (Presidents' Day)\",\n },\n {\n type: \"floating\",\n id: \"us-memorial-day\",\n month: 5,\n weekday: 1, // Monday\n occurrence: -1, // Last Monday of May\n name: \"Memorial Day\",\n nameEn: \"Memorial Day\",\n },\n {\n type: \"fixed\",\n id: \"us-juneteenth\",\n month: 6,\n day: 19,\n name: \"Juneteenth National Independence Day\",\n nameEn: \"Juneteenth National Independence Day\",\n observed: \"sat-to-fri-sun-to-mon\",\n validFromYear: 2021,\n },\n {\n type: \"fixed\",\n id: \"us-independence-day\",\n month: 7,\n day: 4,\n name: \"Independence Day\",\n nameEn: \"Independence Day\",\n observed: \"sat-to-fri-sun-to-mon\",\n },\n {\n type: \"floating\",\n id: \"us-labor-day\",\n month: 9,\n weekday: 1, // Monday\n occurrence: 1, // 1st Monday\n name: \"Labor Day\",\n nameEn: \"Labor Day\",\n },\n {\n type: \"floating\",\n id: \"us-columbus-day\",\n month: 10,\n weekday: 1, // Monday\n occurrence: 2, // 2nd Monday\n name: \"Columbus Day / Indigenous Peoples' Day\",\n nameEn: \"Columbus Day / Indigenous Peoples' Day\",\n },\n {\n type: \"fixed\",\n id: \"us-veterans-day\",\n month: 11,\n day: 11,\n name: \"Veterans Day\",\n nameEn: \"Veterans Day\",\n observed: \"sat-to-fri-sun-to-mon\",\n },\n {\n type: \"floating\",\n id: \"us-thanksgiving\",\n month: 11,\n weekday: 4, // Thursday\n occurrence: 4, // 4th Thursday\n name: \"Thanksgiving Day\",\n nameEn: \"Thanksgiving Day\",\n },\n {\n type: \"fixed\",\n id: \"us-christmas\",\n month: 12,\n day: 25,\n name: \"Christmas Day\",\n nameEn: \"Christmas Day\",\n observed: \"sat-to-fri-sun-to-mon\",\n },\n ],\n};\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { LocalDate } from "../public-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Calculates Easter Sunday for any Gregorian year using the anonymous Meeus/Jones/Butcher algorithm.
|
|
4
|
+
* 100% deterministic integer arithmetic with zero external dependencies.
|
|
5
|
+
* Reference: Jean Meeus, Astronomical Algorithms (1991), p. 67.
|
|
6
|
+
*/
|
|
7
|
+
export declare function calculateEasterSunday(year: number): LocalDate;
|
|
8
|
+
/**
|
|
9
|
+
* Returns Good Friday for the specified year (Easter Sunday - 2 days).
|
|
10
|
+
*/
|
|
11
|
+
export declare function calculateGoodFriday(year: number): LocalDate;
|
|
12
|
+
/**
|
|
13
|
+
* Returns Easter Monday for the specified year (Easter Sunday + 1 day).
|
|
14
|
+
*/
|
|
15
|
+
export declare function calculateEasterMonday(year: number): LocalDate;
|
|
16
|
+
/**
|
|
17
|
+
* Returns Ascension Day for the specified year (Easter Sunday + 39 days).
|
|
18
|
+
*/
|
|
19
|
+
export declare function calculateAscensionDay(year: number): LocalDate;
|
|
20
|
+
/**
|
|
21
|
+
* Returns Whit Monday / Pentecost Monday for the specified year (Easter Sunday + 50 days).
|
|
22
|
+
*/
|
|
23
|
+
export declare function calculateWhitMonday(year: number): LocalDate;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { createLocalDate } from "../core/local-date.js";
|
|
2
|
+
import { addDays } from "../operations/convenience.js";
|
|
3
|
+
/**
|
|
4
|
+
* Calculates Easter Sunday for any Gregorian year using the anonymous Meeus/Jones/Butcher algorithm.
|
|
5
|
+
* 100% deterministic integer arithmetic with zero external dependencies.
|
|
6
|
+
* Reference: Jean Meeus, Astronomical Algorithms (1991), p. 67.
|
|
7
|
+
*/
|
|
8
|
+
export function calculateEasterSunday(year) {
|
|
9
|
+
const a = year % 19;
|
|
10
|
+
const b = Math.floor(year / 100);
|
|
11
|
+
const c = year % 100;
|
|
12
|
+
const d = Math.floor(b / 4);
|
|
13
|
+
const e = b % 4;
|
|
14
|
+
const f = Math.floor((b + 8) / 25);
|
|
15
|
+
const g = Math.floor((b - f + 1) / 3);
|
|
16
|
+
const h = (19 * a + b - d - g + 15) % 30;
|
|
17
|
+
const i = Math.floor(c / 4);
|
|
18
|
+
const k = c % 4;
|
|
19
|
+
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
|
20
|
+
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
21
|
+
const month = Math.floor((h + l - 7 * m + 114) / 31);
|
|
22
|
+
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
|
23
|
+
return createLocalDate(year, month, day);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns Good Friday for the specified year (Easter Sunday - 2 days).
|
|
27
|
+
*/
|
|
28
|
+
export function calculateGoodFriday(year) {
|
|
29
|
+
return addDays(calculateEasterSunday(year), -2);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Returns Easter Monday for the specified year (Easter Sunday + 1 day).
|
|
33
|
+
*/
|
|
34
|
+
export function calculateEasterMonday(year) {
|
|
35
|
+
return addDays(calculateEasterSunday(year), 1);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns Ascension Day for the specified year (Easter Sunday + 39 days).
|
|
39
|
+
*/
|
|
40
|
+
export function calculateAscensionDay(year) {
|
|
41
|
+
return addDays(calculateEasterSunday(year), 39);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Returns Whit Monday / Pentecost Monday for the specified year (Easter Sunday + 50 days).
|
|
45
|
+
*/
|
|
46
|
+
export function calculateWhitMonday(year) {
|
|
47
|
+
return addDays(calculateEasterSunday(year), 50);
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=easter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easter.js","sourceRoot":"","sources":["../../src/holidays/easter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAIvD;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;IACpB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;IACjC,MAAM,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC;IACrB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAE7C,OAAO,eAAe,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AAClD,CAAC","sourcesContent":["import { createLocalDate } from \"../core/local-date.js\";\nimport { addDays } from \"../operations/convenience.js\";\n\nimport type { LocalDate } from \"../public-types.js\";\n\n/**\n * Calculates Easter Sunday for any Gregorian year using the anonymous Meeus/Jones/Butcher algorithm.\n * 100% deterministic integer arithmetic with zero external dependencies.\n * Reference: Jean Meeus, Astronomical Algorithms (1991), p. 67.\n */\nexport function calculateEasterSunday(year: number): LocalDate {\n const a = year % 19;\n const b = Math.floor(year / 100);\n const c = year % 100;\n const d = Math.floor(b / 4);\n const e = b % 4;\n const f = Math.floor((b + 8) / 25);\n const g = Math.floor((b - f + 1) / 3);\n const h = (19 * a + b - d - g + 15) % 30;\n const i = Math.floor(c / 4);\n const k = c % 4;\n const l = (32 + 2 * e + 2 * i - h - k) % 7;\n const m = Math.floor((a + 11 * h + 22 * l) / 451);\n const month = Math.floor((h + l - 7 * m + 114) / 31);\n const day = ((h + l - 7 * m + 114) % 31) + 1;\n\n return createLocalDate(year, month, day);\n}\n\n/**\n * Returns Good Friday for the specified year (Easter Sunday - 2 days).\n */\nexport function calculateGoodFriday(year: number): LocalDate {\n return addDays(calculateEasterSunday(year), -2);\n}\n\n/**\n * Returns Easter Monday for the specified year (Easter Sunday + 1 day).\n */\nexport function calculateEasterMonday(year: number): LocalDate {\n return addDays(calculateEasterSunday(year), 1);\n}\n\n/**\n * Returns Ascension Day for the specified year (Easter Sunday + 39 days).\n */\nexport function calculateAscensionDay(year: number): LocalDate {\n return addDays(calculateEasterSunday(year), 39);\n}\n\n/**\n * Returns Whit Monday / Pentecost Monday for the specified year (Easter Sunday + 50 days).\n */\nexport function calculateWhitMonday(year: number): LocalDate {\n return addDays(calculateEasterSunday(year), 50);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/holidays/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,eAAe,CAAC","sourcesContent":["export * from \"./types.js\";\nexport * from \"./easter.js\";\nexport * from \"./rules/index.js\";\nexport * from \"./countries/index.js\";\nexport * from \"./registry.js\";\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CountryCode, HolidayCalendar, PublicHoliday, HolidayOptions } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Registers a custom or corporate holiday calendar.
|
|
4
|
+
*/
|
|
5
|
+
export declare function registerHolidayCalendar(calendar: HolidayCalendar): void;
|
|
6
|
+
/**
|
|
7
|
+
* Retrieves a holiday calendar by country code.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getHolidayCalendar(countryCodeOrCalendar: CountryCode | string | HolidayCalendar): HolidayCalendar;
|
|
10
|
+
/**
|
|
11
|
+
* Resolves all public holidays for a given country and Gregorian year.
|
|
12
|
+
* Uses bounded LRU caching for microsecond deterministic lookups.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveAnnualHolidays(country: CountryCode | string | HolidayCalendar, year: number, options?: HolidayOptions): readonly PublicHoliday[];
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { BoundedLRU } from "../runtime/bounded-lru.js";
|
|
2
|
+
import { BUILT_IN_HOLIDAYS } from "./countries/index.js";
|
|
3
|
+
import { evaluateRule } from "./rules/index.js";
|
|
4
|
+
import { ChroneraError } from "../errors/errors.js";
|
|
5
|
+
const holidayCache = new BoundedLRU(128);
|
|
6
|
+
const customCalendars = new Map();
|
|
7
|
+
/**
|
|
8
|
+
* Registers a custom or corporate holiday calendar.
|
|
9
|
+
*/
|
|
10
|
+
export function registerHolidayCalendar(calendar) {
|
|
11
|
+
customCalendars.set(calendar.country.toUpperCase(), calendar);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Retrieves a holiday calendar by country code.
|
|
15
|
+
*/
|
|
16
|
+
export function getHolidayCalendar(countryCodeOrCalendar) {
|
|
17
|
+
if (typeof countryCodeOrCalendar === "object" &&
|
|
18
|
+
countryCodeOrCalendar !== null) {
|
|
19
|
+
return countryCodeOrCalendar;
|
|
20
|
+
}
|
|
21
|
+
const code = countryCodeOrCalendar.toUpperCase();
|
|
22
|
+
const calendar = customCalendars.get(code) ?? BUILT_IN_HOLIDAYS[code];
|
|
23
|
+
if (!calendar) {
|
|
24
|
+
throw new ChroneraError("CHRONERA_INVALID_LOCALE", `Holiday calendar for country code "${countryCodeOrCalendar}" is not supported. Supported codes: ${Object.keys(BUILT_IN_HOLIDAYS).join(", ")}.`);
|
|
25
|
+
}
|
|
26
|
+
return calendar;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves all public holidays for a given country and Gregorian year.
|
|
30
|
+
* Uses bounded LRU caching for microsecond deterministic lookups.
|
|
31
|
+
*/
|
|
32
|
+
export function resolveAnnualHolidays(country, year, options) {
|
|
33
|
+
const calendar = getHolidayCalendar(country);
|
|
34
|
+
const includeObserved = options?.includeObserved ?? true;
|
|
35
|
+
const cacheKey = `${calendar.country}:${year}:${includeObserved}`;
|
|
36
|
+
let holidays = holidayCache.get(cacheKey);
|
|
37
|
+
if (!holidays) {
|
|
38
|
+
const list = [];
|
|
39
|
+
for (const rule of calendar.rules) {
|
|
40
|
+
const evaluated = evaluateRule(rule, year, calendar.country, includeObserved);
|
|
41
|
+
for (const h of evaluated) {
|
|
42
|
+
list.push(h);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Sort chronologically by date
|
|
46
|
+
list.sort((a, b) => {
|
|
47
|
+
if (a.date.year !== b.date.year)
|
|
48
|
+
return a.date.year - b.date.year;
|
|
49
|
+
if (a.date.month !== b.date.month)
|
|
50
|
+
return a.date.month - b.date.month;
|
|
51
|
+
return a.date.day - b.date.day;
|
|
52
|
+
});
|
|
53
|
+
holidays = Object.freeze(list);
|
|
54
|
+
holidayCache.set(cacheKey, holidays);
|
|
55
|
+
}
|
|
56
|
+
if (options?.additionalHolidays && options.additionalHolidays.length > 0) {
|
|
57
|
+
const combined = [...holidays];
|
|
58
|
+
for (const [idx, addDate] of options.additionalHolidays.entries()) {
|
|
59
|
+
combined.push({
|
|
60
|
+
id: `custom-additional-${idx + 1}`,
|
|
61
|
+
date: addDate,
|
|
62
|
+
name: "วันหยุดพิเศษ / Additional Holiday",
|
|
63
|
+
nameEn: "Additional Holiday",
|
|
64
|
+
country: calendar.country,
|
|
65
|
+
isObserved: false,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
combined.sort((a, b) => {
|
|
69
|
+
if (a.date.year !== b.date.year)
|
|
70
|
+
return a.date.year - b.date.year;
|
|
71
|
+
if (a.date.month !== b.date.month)
|
|
72
|
+
return a.date.month - b.date.month;
|
|
73
|
+
return a.date.day - b.date.day;
|
|
74
|
+
});
|
|
75
|
+
return Object.freeze(combined);
|
|
76
|
+
}
|
|
77
|
+
return holidays;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/holidays/registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { BoundedLRU } from \"../runtime/bounded-lru.js\";\nimport { BUILT_IN_HOLIDAYS } from \"./countries/index.js\";\nimport { evaluateRule } from \"./rules/index.js\";\nimport { ChroneraError } from \"../errors/errors.js\";\n\nimport type {\n CountryCode,\n HolidayCalendar,\n PublicHoliday,\n HolidayOptions,\n} from \"./types.js\";\n\nconst holidayCache = new BoundedLRU<readonly PublicHoliday[]>(128);\nconst customCalendars = new Map<string, HolidayCalendar>();\n\n/**\n * Registers a custom or corporate holiday calendar.\n */\nexport function registerHolidayCalendar(calendar: HolidayCalendar): void {\n customCalendars.set(calendar.country.toUpperCase(), calendar);\n}\n\n/**\n * Retrieves a holiday calendar by country code.\n */\nexport function getHolidayCalendar(\n countryCodeOrCalendar: CountryCode | string | HolidayCalendar,\n): HolidayCalendar {\n if (\n typeof countryCodeOrCalendar === \"object\" &&\n countryCodeOrCalendar !== null\n ) {\n return countryCodeOrCalendar;\n }\n\n const code = countryCodeOrCalendar.toUpperCase() as CountryCode;\n const calendar = customCalendars.get(code) ?? BUILT_IN_HOLIDAYS[code];\n\n if (!calendar) {\n throw new ChroneraError(\n \"CHRONERA_INVALID_LOCALE\",\n `Holiday calendar for country code \"${countryCodeOrCalendar}\" is not supported. Supported codes: ${Object.keys(BUILT_IN_HOLIDAYS).join(\", \")}.`,\n );\n }\n\n return calendar;\n}\n\n/**\n * Resolves all public holidays for a given country and Gregorian year.\n * Uses bounded LRU caching for microsecond deterministic lookups.\n */\nexport function resolveAnnualHolidays(\n country: CountryCode | string | HolidayCalendar,\n year: number,\n options?: HolidayOptions,\n): readonly PublicHoliday[] {\n const calendar = getHolidayCalendar(country);\n const includeObserved = options?.includeObserved ?? true;\n const cacheKey = `${calendar.country}:${year}:${includeObserved}`;\n\n let holidays = holidayCache.get(cacheKey);\n\n if (!holidays) {\n const list: PublicHoliday[] = [];\n for (const rule of calendar.rules) {\n const evaluated = evaluateRule(\n rule,\n year,\n calendar.country,\n includeObserved,\n );\n for (const h of evaluated) {\n list.push(h);\n }\n }\n\n // Sort chronologically by date\n list.sort((a, b) => {\n if (a.date.year !== b.date.year) return a.date.year - b.date.year;\n if (a.date.month !== b.date.month) return a.date.month - b.date.month;\n return a.date.day - b.date.day;\n });\n\n holidays = Object.freeze(list);\n holidayCache.set(cacheKey, holidays);\n }\n\n if (options?.additionalHolidays && options.additionalHolidays.length > 0) {\n const combined = [...holidays];\n for (const [idx, addDate] of options.additionalHolidays.entries()) {\n combined.push({\n id: `custom-additional-${idx + 1}`,\n date: addDate,\n name: \"วันหยุดพิเศษ / Additional Holiday\",\n nameEn: \"Additional Holiday\",\n country: calendar.country,\n isObserved: false,\n });\n }\n combined.sort((a, b) => {\n if (a.date.year !== b.date.year) return a.date.year - b.date.year;\n if (a.date.month !== b.date.month) return a.date.month - b.date.month;\n return a.date.day - b.date.day;\n });\n return Object.freeze(combined);\n }\n\n return holidays;\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EasterHolidayRule, PublicHoliday, CountryCode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates an Easter cycle holiday rule (Good Friday, Easter Monday, Ascension Day, etc.).
|
|
4
|
+
*/
|
|
5
|
+
export declare function evaluateEasterRule(rule: EasterHolidayRule, year: number, country: CountryCode | (string & {})): readonly PublicHoliday[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { calculateEasterSunday } from "../easter.js";
|
|
2
|
+
import { addDays } from "../../operations/convenience.js";
|
|
3
|
+
/**
|
|
4
|
+
* Evaluates an Easter cycle holiday rule (Good Friday, Easter Monday, Ascension Day, etc.).
|
|
5
|
+
*/
|
|
6
|
+
export function evaluateEasterRule(rule, year, country) {
|
|
7
|
+
if (rule.validFromYear && year < rule.validFromYear)
|
|
8
|
+
return [];
|
|
9
|
+
if (rule.validUntilYear && year > rule.validUntilYear)
|
|
10
|
+
return [];
|
|
11
|
+
const easterSunday = calculateEasterSunday(year);
|
|
12
|
+
const date = rule.offsetDays === 0
|
|
13
|
+
? easterSunday
|
|
14
|
+
: addDays(easterSunday, rule.offsetDays);
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
id: rule.id,
|
|
18
|
+
date,
|
|
19
|
+
name: rule.name,
|
|
20
|
+
nameEn: rule.nameEn,
|
|
21
|
+
country,
|
|
22
|
+
isObserved: false,
|
|
23
|
+
},
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=easter-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easter-rule.js","sourceRoot":"","sources":["../../../src/holidays/rules/easter-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAQ1D;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAuB,EACvB,IAAY,EACZ,OAAoC;IAEpC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc;QAAE,OAAO,EAAE,CAAC;IAEjE,MAAM,YAAY,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,IAAI,GACR,IAAI,CAAC,UAAU,KAAK,CAAC;QACnB,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IAE7C,OAAO;QACL;YACE,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI;YACJ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO;YACP,UAAU,EAAE,KAAK;SAClB;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { calculateEasterSunday } from \"../easter.js\";\nimport { addDays } from \"../../operations/convenience.js\";\n\nimport type {\n EasterHolidayRule,\n PublicHoliday,\n CountryCode,\n} from \"../types.js\";\n\n/**\n * Evaluates an Easter cycle holiday rule (Good Friday, Easter Monday, Ascension Day, etc.).\n */\nexport function evaluateEasterRule(\n rule: EasterHolidayRule,\n year: number,\n country: CountryCode | (string & {}),\n): readonly PublicHoliday[] {\n if (rule.validFromYear && year < rule.validFromYear) return [];\n if (rule.validUntilYear && year > rule.validUntilYear) return [];\n\n const easterSunday = calculateEasterSunday(year);\n const date =\n rule.offsetDays === 0\n ? easterSunday\n : addDays(easterSunday, rule.offsetDays);\n\n return [\n {\n id: rule.id,\n date,\n name: rule.name,\n nameEn: rule.nameEn,\n country,\n isObserved: false,\n },\n ];\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FixedHolidayRule, PublicHoliday, CountryCode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates a fixed solar holiday rule for a given year.
|
|
4
|
+
*/
|
|
5
|
+
export declare function evaluateFixedRule(rule: FixedHolidayRule, year: number, country: CountryCode | (string & {}), includeObserved?: boolean): readonly PublicHoliday[];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { createLocalDate } from "../../core/local-date.js";
|
|
2
|
+
import { getIsoDayOfWeek } from "../../core/iso-week.js";
|
|
3
|
+
import { addDays, getAbsoluteDay } from "../../operations/convenience.js";
|
|
4
|
+
/**
|
|
5
|
+
* Applies legal substitution roll rules when a holiday lands on a weekend.
|
|
6
|
+
*/
|
|
7
|
+
function applyObservedRoll(date, rule) {
|
|
8
|
+
const roll = rule.observed ?? "none";
|
|
9
|
+
if (roll === "none") {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const abs = getAbsoluteDay(date);
|
|
13
|
+
const dow = getIsoDayOfWeek(abs); // 1 = Mon ... 6 = Sat, 7 = Sun
|
|
14
|
+
if (roll === "sunday-to-monday" && dow === 7) {
|
|
15
|
+
return addDays(date, 1);
|
|
16
|
+
}
|
|
17
|
+
if (roll === "weekend-to-monday") {
|
|
18
|
+
if (dow === 6)
|
|
19
|
+
return addDays(date, 2);
|
|
20
|
+
if (dow === 7)
|
|
21
|
+
return addDays(date, 1);
|
|
22
|
+
}
|
|
23
|
+
if (roll === "sat-to-fri-sun-to-mon") {
|
|
24
|
+
if (dow === 6)
|
|
25
|
+
return addDays(date, -1);
|
|
26
|
+
if (dow === 7)
|
|
27
|
+
return addDays(date, 1);
|
|
28
|
+
}
|
|
29
|
+
if (roll === "iran-roll") {
|
|
30
|
+
// Iran weekend is Thursday (4) & Friday (5)
|
|
31
|
+
if (dow === 4 || dow === 5) {
|
|
32
|
+
return addDays(date, dow === 4 ? 2 : 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Evaluates a fixed solar holiday rule for a given year.
|
|
39
|
+
*/
|
|
40
|
+
export function evaluateFixedRule(rule, year, country, includeObserved = true) {
|
|
41
|
+
if (rule.validFromYear && year < rule.validFromYear)
|
|
42
|
+
return [];
|
|
43
|
+
if (rule.validUntilYear && year > rule.validUntilYear)
|
|
44
|
+
return [];
|
|
45
|
+
const originalDate = createLocalDate(year, rule.month, rule.day);
|
|
46
|
+
const results = [
|
|
47
|
+
{
|
|
48
|
+
id: rule.id,
|
|
49
|
+
date: originalDate,
|
|
50
|
+
name: rule.name,
|
|
51
|
+
nameEn: rule.nameEn,
|
|
52
|
+
country,
|
|
53
|
+
isObserved: false,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
56
|
+
if (includeObserved) {
|
|
57
|
+
const observedDate = applyObservedRoll(originalDate, rule);
|
|
58
|
+
if (observedDate) {
|
|
59
|
+
results.push({
|
|
60
|
+
id: `${rule.id}-observed`,
|
|
61
|
+
date: observedDate,
|
|
62
|
+
name: `${rule.name} (ชดเชย / Observed)`,
|
|
63
|
+
nameEn: `${rule.nameEn} (Observed)`,
|
|
64
|
+
country,
|
|
65
|
+
isObserved: true,
|
|
66
|
+
originalDate,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return results;
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=fixed-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixed-rule.js","sourceRoot":"","sources":["../../../src/holidays/rules/fixed-rule.ts"],"names":[],"mappings":"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","sourcesContent":["import { createLocalDate } from \"../../core/local-date.js\";\nimport { getIsoDayOfWeek } from \"../../core/iso-week.js\";\nimport { addDays, getAbsoluteDay } from \"../../operations/convenience.js\";\n\nimport type { FixedHolidayRule, PublicHoliday, CountryCode } from \"../types.js\";\nimport type { LocalDate } from \"../../public-types.js\";\n\n/**\n * Applies legal substitution roll rules when a holiday lands on a weekend.\n */\nfunction applyObservedRoll(\n date: LocalDate,\n rule: FixedHolidayRule,\n): LocalDate | null {\n const roll = rule.observed ?? \"none\";\n if (roll === \"none\") {\n return null;\n }\n\n const abs = getAbsoluteDay(date);\n const dow = getIsoDayOfWeek(abs); // 1 = Mon ... 6 = Sat, 7 = Sun\n\n if (roll === \"sunday-to-monday\" && dow === 7) {\n return addDays(date, 1);\n }\n\n if (roll === \"weekend-to-monday\") {\n if (dow === 6) return addDays(date, 2);\n if (dow === 7) return addDays(date, 1);\n }\n\n if (roll === \"sat-to-fri-sun-to-mon\") {\n if (dow === 6) return addDays(date, -1);\n if (dow === 7) return addDays(date, 1);\n }\n\n if (roll === \"iran-roll\") {\n // Iran weekend is Thursday (4) & Friday (5)\n if (dow === 4 || dow === 5) {\n return addDays(date, dow === 4 ? 2 : 1);\n }\n }\n\n return null;\n}\n\n/**\n * Evaluates a fixed solar holiday rule for a given year.\n */\nexport function evaluateFixedRule(\n rule: FixedHolidayRule,\n year: number,\n country: CountryCode | (string & {}),\n includeObserved = true,\n): readonly PublicHoliday[] {\n if (rule.validFromYear && year < rule.validFromYear) return [];\n if (rule.validUntilYear && year > rule.validUntilYear) return [];\n\n const originalDate = createLocalDate(year, rule.month, rule.day);\n const results: PublicHoliday[] = [\n {\n id: rule.id,\n date: originalDate,\n name: rule.name,\n nameEn: rule.nameEn,\n country,\n isObserved: false,\n },\n ];\n\n if (includeObserved) {\n const observedDate = applyObservedRoll(originalDate, rule);\n if (observedDate) {\n results.push({\n id: `${rule.id}-observed`,\n date: observedDate,\n name: `${rule.name} (ชดเชย / Observed)`,\n nameEn: `${rule.nameEn} (Observed)`,\n country,\n isObserved: true,\n originalDate,\n });\n }\n }\n\n return results;\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FloatingHolidayRule, PublicHoliday, CountryCode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates a floating weekday rule for a given year.
|
|
4
|
+
* e.g., 4th Thursday of November (Thanksgiving), 2nd Monday of January (Coming of Age Day).
|
|
5
|
+
*/
|
|
6
|
+
export declare function evaluateFloatingRule(rule: FloatingHolidayRule, year: number, country: CountryCode | (string & {})): readonly PublicHoliday[];
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createLocalDate } from "../../core/local-date.js";
|
|
2
|
+
import { getIsoDayOfWeek } from "../../core/iso-week.js";
|
|
3
|
+
import { getAbsoluteDay } from "../../operations/convenience.js";
|
|
4
|
+
function getGregorianDaysInMonth(year, month) {
|
|
5
|
+
if (month === 2) {
|
|
6
|
+
const isLeap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
7
|
+
return isLeap ? 29 : 28;
|
|
8
|
+
}
|
|
9
|
+
return month === 4 || month === 6 || month === 9 || month === 11 ? 30 : 31;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Evaluates a floating weekday rule for a given year.
|
|
13
|
+
* e.g., 4th Thursday of November (Thanksgiving), 2nd Monday of January (Coming of Age Day).
|
|
14
|
+
*/
|
|
15
|
+
export function evaluateFloatingRule(rule, year, country) {
|
|
16
|
+
if (rule.validFromYear && year < rule.validFromYear)
|
|
17
|
+
return [];
|
|
18
|
+
if (rule.validUntilYear && year > rule.validUntilYear)
|
|
19
|
+
return [];
|
|
20
|
+
const targetWeekday = rule.weekday; // 1 = Mon ... 7 = Sun
|
|
21
|
+
let targetDay;
|
|
22
|
+
if (rule.occurrence === -1) {
|
|
23
|
+
// Last occurrence in the month
|
|
24
|
+
const totalDays = getGregorianDaysInMonth(year, rule.month);
|
|
25
|
+
const lastDate = createLocalDate(year, rule.month, totalDays);
|
|
26
|
+
const lastDow = getIsoDayOfWeek(getAbsoluteDay(lastDate));
|
|
27
|
+
const diff = (lastDow - targetWeekday + 7) % 7;
|
|
28
|
+
targetDay = totalDays - diff;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
// 1st, 2nd, 3rd, 4th, or 5th occurrence
|
|
32
|
+
const firstDate = createLocalDate(year, rule.month, 1);
|
|
33
|
+
const firstDow = getIsoDayOfWeek(getAbsoluteDay(firstDate));
|
|
34
|
+
const firstOccurrenceDay = 1 + ((targetWeekday - firstDow + 7) % 7);
|
|
35
|
+
targetDay = firstOccurrenceDay + (rule.occurrence - 1) * 7;
|
|
36
|
+
const totalDays = getGregorianDaysInMonth(year, rule.month);
|
|
37
|
+
if (targetDay > totalDays) {
|
|
38
|
+
return []; // Month doesn't have a 5th occurrence
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const date = createLocalDate(year, rule.month, targetDay);
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
id: rule.id,
|
|
45
|
+
date,
|
|
46
|
+
name: rule.name,
|
|
47
|
+
nameEn: rule.nameEn,
|
|
48
|
+
country,
|
|
49
|
+
isObserved: false,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=floating-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floating-rule.js","sourceRoot":"","sources":["../../../src/holidays/rules/floating-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAQjE,SAAS,uBAAuB,CAAC,IAAY,EAAE,KAAa;IAC1D,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,MAAM,MAAM,GAAG,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,IAAI,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC;QACxE,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,IAAyB,EACzB,IAAY,EACZ,OAAoC;IAEpC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc;QAAE,OAAO,EAAE,CAAC;IAEjE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,sBAAsB;IAC1D,IAAI,SAAiB,CAAC;IAEtB,IAAI,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3B,+BAA+B;QAC/B,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/C,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,wCAAwC;QACxC,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,eAAe,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5D,MAAM,kBAAkB,GAAG,CAAC,GAAG,CAAC,CAAC,aAAa,GAAG,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,SAAS,GAAG,kBAAkB,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAE3D,MAAM,SAAS,GAAG,uBAAuB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,SAAS,GAAG,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC,CAAC,sCAAsC;QACnD,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IAC1D,OAAO;QACL;YACE,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI;YACJ,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO;YACP,UAAU,EAAE,KAAK;SAClB;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { createLocalDate } from \"../../core/local-date.js\";\nimport { getIsoDayOfWeek } from \"../../core/iso-week.js\";\nimport { getAbsoluteDay } from \"../../operations/convenience.js\";\n\nimport type {\n FloatingHolidayRule,\n PublicHoliday,\n CountryCode,\n} from \"../types.js\";\n\nfunction getGregorianDaysInMonth(year: number, month: number): number {\n if (month === 2) {\n const isLeap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\n return isLeap ? 29 : 28;\n }\n return month === 4 || month === 6 || month === 9 || month === 11 ? 30 : 31;\n}\n\n/**\n * Evaluates a floating weekday rule for a given year.\n * e.g., 4th Thursday of November (Thanksgiving), 2nd Monday of January (Coming of Age Day).\n */\nexport function evaluateFloatingRule(\n rule: FloatingHolidayRule,\n year: number,\n country: CountryCode | (string & {}),\n): readonly PublicHoliday[] {\n if (rule.validFromYear && year < rule.validFromYear) return [];\n if (rule.validUntilYear && year > rule.validUntilYear) return [];\n\n const targetWeekday = rule.weekday; // 1 = Mon ... 7 = Sun\n let targetDay: number;\n\n if (rule.occurrence === -1) {\n // Last occurrence in the month\n const totalDays = getGregorianDaysInMonth(year, rule.month);\n const lastDate = createLocalDate(year, rule.month, totalDays);\n const lastDow = getIsoDayOfWeek(getAbsoluteDay(lastDate));\n const diff = (lastDow - targetWeekday + 7) % 7;\n targetDay = totalDays - diff;\n } else {\n // 1st, 2nd, 3rd, 4th, or 5th occurrence\n const firstDate = createLocalDate(year, rule.month, 1);\n const firstDow = getIsoDayOfWeek(getAbsoluteDay(firstDate));\n const firstOccurrenceDay = 1 + ((targetWeekday - firstDow + 7) % 7);\n targetDay = firstOccurrenceDay + (rule.occurrence - 1) * 7;\n\n const totalDays = getGregorianDaysInMonth(year, rule.month);\n if (targetDay > totalDays) {\n return []; // Month doesn't have a 5th occurrence\n }\n }\n\n const date = createLocalDate(year, rule.month, targetDay);\n return [\n {\n id: rule.id,\n date,\n name: rule.name,\n nameEn: rule.nameEn,\n country,\n isObserved: false,\n },\n ];\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HijriHolidayRule, PublicHoliday, CountryCode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Evaluates an Islamic Lunar Hijri holiday rule for a given Gregorian solar year.
|
|
4
|
+
* Handles single or multi-day statutory festivals (e.g. Eid al-Fitr, Eid al-Adha).
|
|
5
|
+
*/
|
|
6
|
+
export declare function evaluateHijriRule(rule: HijriHolidayRule, year: number, country: CountryCode | (string & {})): readonly PublicHoliday[];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { islamicCivilToAbsoluteDay, islamicCivilFromAbsoluteDay, } from "../../calendar/hijri/civil-adapter.js";
|
|
2
|
+
import { absoluteDayFromGregorianFields } from "../../core/absolute-day.js";
|
|
3
|
+
import { gregorianFromAbsoluteDay } from "../../calendar/gregory/absolute-day.js";
|
|
4
|
+
import { localDate } from "../../core/local-date.js";
|
|
5
|
+
import { addDays } from "../../operations/convenience.js";
|
|
6
|
+
/**
|
|
7
|
+
* Evaluates an Islamic Lunar Hijri holiday rule for a given Gregorian solar year.
|
|
8
|
+
* Handles single or multi-day statutory festivals (e.g. Eid al-Fitr, Eid al-Adha).
|
|
9
|
+
*/
|
|
10
|
+
export function evaluateHijriRule(rule, year, country) {
|
|
11
|
+
if (rule.validFromYear && year < rule.validFromYear)
|
|
12
|
+
return [];
|
|
13
|
+
if (rule.validUntilYear && year > rule.validUntilYear)
|
|
14
|
+
return [];
|
|
15
|
+
const startAbs = absoluteDayFromGregorianFields(year, 1, 1);
|
|
16
|
+
const endAbs = absoluteDayFromGregorianFields(year, 12, 31);
|
|
17
|
+
const startHijri = islamicCivilFromAbsoluteDay(startAbs);
|
|
18
|
+
const endHijri = islamicCivilFromAbsoluteDay(endAbs);
|
|
19
|
+
const duration = rule.durationDays ?? 1;
|
|
20
|
+
const results = [];
|
|
21
|
+
for (let hYear = startHijri.year - 1; hYear <= endHijri.year + 1; hYear++) {
|
|
22
|
+
const baseAbs = islamicCivilToAbsoluteDay(hYear, rule.hijriMonth, rule.hijriDay);
|
|
23
|
+
const gFields = gregorianFromAbsoluteDay(baseAbs);
|
|
24
|
+
const baseDate = localDate(gFields.year, gFields.month, gFields.day);
|
|
25
|
+
for (let dayOffset = 0; dayOffset < duration; dayOffset++) {
|
|
26
|
+
const date = dayOffset === 0 ? baseDate : addDays(baseDate, dayOffset);
|
|
27
|
+
if (date.year === year) {
|
|
28
|
+
const idSuffix = duration > 1 ? `-day-${dayOffset + 1}` : "";
|
|
29
|
+
const nameSuffix = duration > 1 ? ` (วันที่ ${dayOffset + 1})` : "";
|
|
30
|
+
const nameEnSuffix = duration > 1 ? ` (Day ${dayOffset + 1})` : "";
|
|
31
|
+
results.push({
|
|
32
|
+
id: `${rule.id}${idSuffix}`,
|
|
33
|
+
date,
|
|
34
|
+
name: `${rule.name}${nameSuffix}`,
|
|
35
|
+
nameEn: `${rule.nameEn}${nameEnSuffix}`,
|
|
36
|
+
country,
|
|
37
|
+
isObserved: false,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=hijri-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hijri-rule.js","sourceRoot":"","sources":["../../../src/holidays/rules/hijri-rule.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,iCAAiC,CAAC;AAI1D;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAsB,EACtB,IAAY,EACZ,OAAoC;IAEpC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,GAAG,IAAI,CAAC,aAAa;QAAE,OAAO,EAAE,CAAC;IAC/D,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,GAAG,IAAI,CAAC,cAAc;QAAE,OAAO,EAAE,CAAC;IAEjE,MAAM,QAAQ,GAAG,8BAA8B,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,MAAM,GAAG,8BAA8B,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAE5D,MAAM,UAAU,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;IACxC,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,KAAK,IAAI,KAAK,GAAG,UAAU,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1E,MAAM,OAAO,GAAG,yBAAyB,CACvC,KAAK,EACL,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,QAAQ,CACd,CAAC;QACF,MAAM,OAAO,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;QAErE,KAAK,IAAI,SAAS,GAAG,CAAC,EAAE,SAAS,GAAG,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAC;YAC1D,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YACvE,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBACvB,MAAM,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7D,MAAM,UAAU,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpE,MAAM,YAAY,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAEnE,OAAO,CAAC,IAAI,CAAC;oBACX,EAAE,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,QAAQ,EAAE;oBAC3B,IAAI;oBACJ,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,GAAG,UAAU,EAAE;oBACjC,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE;oBACvC,OAAO;oBACP,UAAU,EAAE,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import {\n islamicCivilToAbsoluteDay,\n islamicCivilFromAbsoluteDay,\n} from \"../../calendar/hijri/civil-adapter.js\";\nimport { absoluteDayFromGregorianFields } from \"../../core/absolute-day.js\";\nimport { gregorianFromAbsoluteDay } from \"../../calendar/gregory/absolute-day.js\";\nimport { localDate } from \"../../core/local-date.js\";\nimport { addDays } from \"../../operations/convenience.js\";\n\nimport type { HijriHolidayRule, PublicHoliday, CountryCode } from \"../types.js\";\n\n/**\n * Evaluates an Islamic Lunar Hijri holiday rule for a given Gregorian solar year.\n * Handles single or multi-day statutory festivals (e.g. Eid al-Fitr, Eid al-Adha).\n */\nexport function evaluateHijriRule(\n rule: HijriHolidayRule,\n year: number,\n country: CountryCode | (string & {}),\n): readonly PublicHoliday[] {\n if (rule.validFromYear && year < rule.validFromYear) return [];\n if (rule.validUntilYear && year > rule.validUntilYear) return [];\n\n const startAbs = absoluteDayFromGregorianFields(year, 1, 1);\n const endAbs = absoluteDayFromGregorianFields(year, 12, 31);\n\n const startHijri = islamicCivilFromAbsoluteDay(startAbs);\n const endHijri = islamicCivilFromAbsoluteDay(endAbs);\n\n const duration = rule.durationDays ?? 1;\n const results: PublicHoliday[] = [];\n\n for (let hYear = startHijri.year - 1; hYear <= endHijri.year + 1; hYear++) {\n const baseAbs = islamicCivilToAbsoluteDay(\n hYear,\n rule.hijriMonth,\n rule.hijriDay,\n );\n const gFields = gregorianFromAbsoluteDay(baseAbs);\n const baseDate = localDate(gFields.year, gFields.month, gFields.day);\n\n for (let dayOffset = 0; dayOffset < duration; dayOffset++) {\n const date = dayOffset === 0 ? baseDate : addDays(baseDate, dayOffset);\n if (date.year === year) {\n const idSuffix = duration > 1 ? `-day-${dayOffset + 1}` : \"\";\n const nameSuffix = duration > 1 ? ` (วันที่ ${dayOffset + 1})` : \"\";\n const nameEnSuffix = duration > 1 ? ` (Day ${dayOffset + 1})` : \"\";\n\n results.push({\n id: `${rule.id}${idSuffix}`,\n date,\n name: `${rule.name}${nameSuffix}`,\n nameEn: `${rule.nameEn}${nameEnSuffix}`,\n country,\n isObserved: false,\n });\n }\n }\n }\n\n return results;\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HolidayRule, PublicHoliday, CountryCode } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Dispatches and evaluates any HolidayRule for a specified Gregorian year.
|
|
4
|
+
*/
|
|
5
|
+
export declare function evaluateRule(rule: HolidayRule, year: number, country: CountryCode | (string & {}), includeObserved?: boolean): readonly PublicHoliday[];
|
|
6
|
+
export * from "./fixed-rule.js";
|
|
7
|
+
export * from "./floating-rule.js";
|
|
8
|
+
export * from "./easter-rule.js";
|
|
9
|
+
export * from "./hijri-rule.js";
|