@intech-software/chronera 0.1.4 → 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/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 +6 -2
- package/dist/index.js +4 -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/package.json +10 -1
|
@@ -1,28 +1,82 @@
|
|
|
1
1
|
import { getIsoDayOfWeek } from "../core/iso-week.js";
|
|
2
|
+
import { localDate } from "../core/local-date.js";
|
|
3
|
+
import { gregorianFromAbsoluteDay } from "../calendar/gregory/absolute-day.js";
|
|
2
4
|
import { ChroneraError } from "../errors/errors.js";
|
|
3
5
|
import { addDays, getAbsoluteDay } from "./convenience.js";
|
|
6
|
+
import { isPublicHoliday } from "./holidays.js";
|
|
7
|
+
import { getHolidayCalendar } from "../holidays/registry.js";
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
6
|
-
* Works across all calendars (Gregorian, Thai Buddhist, Japanese, Hijri, etc.).
|
|
9
|
+
* Checks whether a given absolute day is a weekend according to options or country defaults.
|
|
7
10
|
*/
|
|
8
|
-
|
|
9
|
-
const abs = getAbsoluteDay(date);
|
|
11
|
+
function isWeekendForOptions(abs, options) {
|
|
10
12
|
const dow = getIsoDayOfWeek(abs);
|
|
13
|
+
if (options?.weekendDays && options.weekendDays.length > 0) {
|
|
14
|
+
return options.weekendDays.includes(dow);
|
|
15
|
+
}
|
|
16
|
+
if (typeof options?.holidays === "string" ||
|
|
17
|
+
(typeof options?.holidays === "object" &&
|
|
18
|
+
options?.holidays !== null &&
|
|
19
|
+
"country" in options.holidays)) {
|
|
20
|
+
try {
|
|
21
|
+
const cal = getHolidayCalendar(options.holidays);
|
|
22
|
+
if (cal.defaultWeekendDays) {
|
|
23
|
+
return cal.defaultWeekendDays.includes(dow);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Fallback to standard Saturday & Sunday
|
|
28
|
+
}
|
|
29
|
+
}
|
|
11
30
|
return dow === 6 || dow === 7;
|
|
12
31
|
}
|
|
13
32
|
/**
|
|
14
|
-
* Returns true if the specified
|
|
15
|
-
|
|
33
|
+
* Returns true if the specified absolute day is a non-working day (weekend or holiday).
|
|
34
|
+
*/
|
|
35
|
+
function isNonWorkingDay(abs, options) {
|
|
36
|
+
if (isWeekendForOptions(abs, options)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
const holidays = options?.holidays;
|
|
40
|
+
if (!holidays) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const gFields = gregorianFromAbsoluteDay(abs);
|
|
44
|
+
const gDate = localDate(gFields.year, gFields.month, gFields.day);
|
|
45
|
+
if (typeof holidays === "function") {
|
|
46
|
+
return holidays(gDate);
|
|
47
|
+
}
|
|
48
|
+
if (typeof holidays === "string" || "rules" in holidays) {
|
|
49
|
+
return isPublicHoliday(gDate, holidays);
|
|
50
|
+
}
|
|
51
|
+
return holidays.some((hDate) => getAbsoluteDay(hDate) === abs);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Returns true if the specified date falls on a weekend.
|
|
55
|
+
* Supports custom weekend definitions per country (e.g. Thursday & Friday for Iran).
|
|
56
|
+
*/
|
|
57
|
+
export function isWeekend(date, options) {
|
|
58
|
+
const abs = getAbsoluteDay(date);
|
|
59
|
+
return isWeekendForOptions(abs, options);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Returns true if the specified date falls on a weekday.
|
|
63
|
+
*/
|
|
64
|
+
export function isWeekday(date, options) {
|
|
65
|
+
return !isWeekend(date, options);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Returns true if the specified date is a business day (neither weekend nor public holiday).
|
|
16
69
|
*/
|
|
17
|
-
export function
|
|
18
|
-
|
|
70
|
+
export function isBusinessDay(date, options) {
|
|
71
|
+
const abs = getAbsoluteDay(date);
|
|
72
|
+
return !isNonWorkingDay(abs, options);
|
|
19
73
|
}
|
|
20
74
|
/**
|
|
21
|
-
* Adds business days to a LocalDate or CalendarDate, skipping
|
|
75
|
+
* Adds business days to a LocalDate or CalendarDate, skipping weekends and optionally public holidays.
|
|
22
76
|
* Supports positive, negative, and zero day additions.
|
|
23
|
-
* Uses O(1) mathematical week advancement
|
|
77
|
+
* Uses O(1) mathematical week advancement when no holidays are provided, or iterative evaluation with holiday constraints.
|
|
24
78
|
*/
|
|
25
|
-
export function addBusinessDays(date, amount) {
|
|
79
|
+
export function addBusinessDays(date, amount, options) {
|
|
26
80
|
if (!Number.isFinite(amount)) {
|
|
27
81
|
throw new ChroneraError("CHRONERA_OUT_OF_RANGE", "Amount must be a finite integer.");
|
|
28
82
|
}
|
|
@@ -34,17 +88,31 @@ export function addBusinessDays(date, amount) {
|
|
|
34
88
|
let currentAbs = startAbs;
|
|
35
89
|
let remaining = intAmount;
|
|
36
90
|
const step = remaining > 0 ? 1 : -1;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
91
|
+
// Fast-path: no holidays or custom weekends
|
|
92
|
+
const hasHolidays = Boolean(options?.holidays);
|
|
93
|
+
const hasCustomWeekends = Boolean(options?.weekendDays);
|
|
94
|
+
if (!hasHolidays && !hasCustomWeekends) {
|
|
95
|
+
while (remaining !== 0) {
|
|
96
|
+
const currentDow = getIsoDayOfWeek(currentAbs);
|
|
97
|
+
if (currentDow !== 6 && currentDow !== 7 && Math.abs(remaining) >= 5) {
|
|
98
|
+
const fullWeeks = Math.trunc(remaining / 5);
|
|
99
|
+
currentAbs += fullWeeks * 7;
|
|
100
|
+
remaining %= 5;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
currentAbs += step;
|
|
104
|
+
const dow = getIsoDayOfWeek(currentAbs);
|
|
105
|
+
if (dow !== 6 && dow !== 7) {
|
|
106
|
+
remaining -= step;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
43
109
|
}
|
|
44
|
-
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Exact evaluation with holiday and custom weekend constraints
|
|
113
|
+
while (remaining !== 0) {
|
|
45
114
|
currentAbs += step;
|
|
46
|
-
|
|
47
|
-
if (dow !== 6 && dow !== 7) {
|
|
115
|
+
if (!isNonWorkingDay(currentAbs, options)) {
|
|
48
116
|
remaining -= step;
|
|
49
117
|
}
|
|
50
118
|
}
|
|
@@ -53,39 +121,49 @@ export function addBusinessDays(date, amount) {
|
|
|
53
121
|
return addDays(date, deltaDays);
|
|
54
122
|
}
|
|
55
123
|
/**
|
|
56
|
-
* Subtracts business days from a LocalDate or CalendarDate, skipping weekends.
|
|
124
|
+
* Subtracts business days from a LocalDate or CalendarDate, skipping weekends and optional holidays.
|
|
57
125
|
*/
|
|
58
|
-
export function subtractBusinessDays(date, amount) {
|
|
59
|
-
return addBusinessDays(date, -amount);
|
|
126
|
+
export function subtractBusinessDays(date, amount, options) {
|
|
127
|
+
return addBusinessDays(date, -amount, options);
|
|
60
128
|
}
|
|
61
129
|
/**
|
|
62
130
|
* Returns the signed count of business days between two dates (left - right).
|
|
63
131
|
* Positive if left is after right, negative if left is before right, 0 if identical.
|
|
64
|
-
* Works across all calendar systems with O(1) mathematical week acceleration.
|
|
65
132
|
*/
|
|
66
|
-
export function diffInBusinessDays(left, right) {
|
|
133
|
+
export function diffInBusinessDays(left, right, options) {
|
|
67
134
|
const absLeft = getAbsoluteDay(left);
|
|
68
135
|
const absRight = getAbsoluteDay(right);
|
|
69
136
|
if (absLeft === absRight) {
|
|
70
137
|
return 0;
|
|
71
138
|
}
|
|
72
139
|
if (absLeft < absRight) {
|
|
73
|
-
return -diffInBusinessDays(right, left);
|
|
140
|
+
return -diffInBusinessDays(right, left, options);
|
|
74
141
|
}
|
|
75
142
|
let count = 0;
|
|
76
143
|
let current = absRight;
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
144
|
+
const hasHolidays = Boolean(options?.holidays);
|
|
145
|
+
const hasCustomWeekends = Boolean(options?.weekendDays);
|
|
146
|
+
if (!hasHolidays && !hasCustomWeekends) {
|
|
147
|
+
// Fast-path O(1) acceleration: any consecutive 7 calendar days contains exactly 5 business days
|
|
148
|
+
const fullWeeks = Math.floor((absLeft - current) / 7);
|
|
149
|
+
if (fullWeeks > 0) {
|
|
150
|
+
count += fullWeeks * 5;
|
|
151
|
+
current += fullWeeks * 7;
|
|
152
|
+
}
|
|
153
|
+
while (current < absLeft) {
|
|
154
|
+
current++;
|
|
155
|
+
const dow = getIsoDayOfWeek(current);
|
|
156
|
+
if (dow !== 6 && dow !== 7) {
|
|
157
|
+
count++;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
82
160
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
161
|
+
else {
|
|
162
|
+
while (current < absLeft) {
|
|
163
|
+
current++;
|
|
164
|
+
if (!isNonWorkingDay(current, options)) {
|
|
165
|
+
count++;
|
|
166
|
+
}
|
|
89
167
|
}
|
|
90
168
|
}
|
|
91
169
|
return count;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-days.js","sourceRoot":"","sources":["../../src/operations/business-days.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIsoDayOfWeek } from \"../core/iso-week.js\";\nimport { ChroneraError } from \"../errors/errors.js\";\nimport { addDays, getAbsoluteDay } from \"./convenience.js\";\n\nimport type { DateOrCalendarDate } from \"../public-types.js\";\n\n/**\n * Returns true if the specified date falls on a weekend (Saturday or Sunday).\n * Works across all calendars (Gregorian, Thai Buddhist, Japanese, Hijri, etc.).\n */\nexport function isWeekend(date: DateOrCalendarDate): boolean {\n const abs = getAbsoluteDay(date);\n const dow = getIsoDayOfWeek(abs);\n return dow === 6 || dow === 7;\n}\n\n/**\n * Returns true if the specified date falls on a weekday (Monday through Friday).\n * Works across all calendars (Gregorian, Thai Buddhist, Japanese, Hijri, etc.).\n */\nexport function isWeekday(date: DateOrCalendarDate): boolean {\n return !isWeekend(date);\n}\n\n/**\n * Adds business days to a LocalDate or CalendarDate, skipping Saturdays and Sundays.\n * Supports positive, negative, and zero day additions.\n * Uses O(1) mathematical week advancement for large intervals while preserving exact calendar semantics.\n */\nexport function addBusinessDays<T extends DateOrCalendarDate>(\n date: T,\n amount: number,\n): T {\n if (!Number.isFinite(amount)) {\n throw new ChroneraError(\n \"CHRONERA_OUT_OF_RANGE\",\n \"Amount must be a finite integer.\",\n );\n }\n\n const intAmount = Math.trunc(amount);\n if (intAmount === 0) {\n return date;\n }\n\n const startAbs = getAbsoluteDay(date);\n let currentAbs = startAbs;\n let remaining = intAmount;\n const step = remaining > 0 ? 1 : -1;\n\n while (remaining !== 0) {\n const currentDow = getIsoDayOfWeek(currentAbs);\n if (currentDow !== 6 && currentDow !== 7 && Math.abs(remaining) >= 5) {\n const fullWeeks = Math.trunc(remaining / 5);\n currentAbs += fullWeeks * 7;\n remaining %= 5;\n } else {\n currentAbs += step;\n const dow = getIsoDayOfWeek(currentAbs);\n if (dow !== 6 && dow !== 7) {\n remaining -= step;\n }\n }\n }\n\n const deltaDays = currentAbs - startAbs;\n return addDays(date, deltaDays);\n}\n\n/**\n * Subtracts business days from a LocalDate or CalendarDate, skipping weekends.\n */\nexport function subtractBusinessDays<T extends DateOrCalendarDate>(\n date: T,\n amount: number,\n): T {\n return addBusinessDays(date, -amount);\n}\n\n/**\n * Returns the signed count of business days between two dates (left - right).\n * Positive if left is after right, negative if left is before right, 0 if identical.\n * Works across all calendar systems with O(1) mathematical week acceleration.\n */\nexport function diffInBusinessDays(\n left: DateOrCalendarDate,\n right: DateOrCalendarDate,\n): number {\n const absLeft = getAbsoluteDay(left);\n const absRight = getAbsoluteDay(right);\n\n if (absLeft === absRight) {\n return 0;\n }\n\n if (absLeft < absRight) {\n return -diffInBusinessDays(right, left);\n }\n\n let count = 0;\n let current = absRight;\n\n // O(1) acceleration: any consecutive 7 calendar days contains exactly 5 business days\n const fullWeeks = Math.floor((absLeft - current) / 7);\n if (fullWeeks > 0) {\n count += fullWeeks * 5;\n current += fullWeeks * 7;\n }\n\n // Step through remainder (at most 6 days)\n while (current < absLeft) {\n current++;\n const dow = getIsoDayOfWeek(current);\n if (dow !== 6 && dow !== 7) {\n count++;\n }\n }\n\n return count;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"business-days.js","sourceRoot":"","sources":["../../src/operations/business-days.ts"],"names":[],"mappings":"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","sourcesContent":["import { getIsoDayOfWeek } from \"../core/iso-week.js\";\nimport { localDate } from \"../core/local-date.js\";\nimport { gregorianFromAbsoluteDay } from \"../calendar/gregory/absolute-day.js\";\nimport { ChroneraError } from \"../errors/errors.js\";\nimport { addDays, getAbsoluteDay } from \"./convenience.js\";\nimport { isPublicHoliday } from \"./holidays.js\";\nimport { getHolidayCalendar } from \"../holidays/registry.js\";\n\nimport type { CountryCode, HolidayCalendar } from \"../holidays/types.js\";\nimport type { DateOrCalendarDate, LocalDate } from \"../public-types.js\";\n\n/**\n * Options for business days arithmetic and queries.\n */\nexport interface BusinessDaysOptions {\n /**\n * Country code (e.g. \"TH\", \"JP\", \"US\") or custom HolidayCalendar or holiday date list or holiday predicate.\n */\n readonly holidays?:\n | CountryCode\n | string\n | HolidayCalendar\n | readonly DateOrCalendarDate[]\n | ((date: LocalDate) => boolean);\n /**\n * Custom weekend days (defaults to [6, 7], or [4, 5] if country is Iran, etc.).\n */\n readonly weekendDays?: readonly number[];\n}\n\n/**\n * Checks whether a given absolute day is a weekend according to options or country defaults.\n */\nfunction isWeekendForOptions(\n abs: number,\n options?: BusinessDaysOptions,\n): boolean {\n const dow = getIsoDayOfWeek(abs);\n if (options?.weekendDays && options.weekendDays.length > 0) {\n return options.weekendDays.includes(dow);\n }\n\n if (\n typeof options?.holidays === \"string\" ||\n (typeof options?.holidays === \"object\" &&\n options?.holidays !== null &&\n \"country\" in options.holidays)\n ) {\n try {\n const cal = getHolidayCalendar(options.holidays);\n if (cal.defaultWeekendDays) {\n return cal.defaultWeekendDays.includes(dow);\n }\n } catch {\n // Fallback to standard Saturday & Sunday\n }\n }\n\n return dow === 6 || dow === 7;\n}\n\n/**\n * Returns true if the specified absolute day is a non-working day (weekend or holiday).\n */\nfunction isNonWorkingDay(abs: number, options?: BusinessDaysOptions): boolean {\n if (isWeekendForOptions(abs, options)) {\n return true;\n }\n\n const holidays = options?.holidays;\n if (!holidays) {\n return false;\n }\n\n const gFields = gregorianFromAbsoluteDay(abs);\n const gDate = localDate(gFields.year, gFields.month, gFields.day);\n\n if (typeof holidays === \"function\") {\n return holidays(gDate);\n }\n\n if (typeof holidays === \"string\" || \"rules\" in holidays) {\n return isPublicHoliday(gDate, holidays);\n }\n\n return holidays.some((hDate) => getAbsoluteDay(hDate) === abs);\n}\n\n/**\n * Returns true if the specified date falls on a weekend.\n * Supports custom weekend definitions per country (e.g. Thursday & Friday for Iran).\n */\nexport function isWeekend(\n date: DateOrCalendarDate,\n options?: Pick<BusinessDaysOptions, \"weekendDays\" | \"holidays\">,\n): boolean {\n const abs = getAbsoluteDay(date);\n return isWeekendForOptions(abs, options);\n}\n\n/**\n * Returns true if the specified date falls on a weekday.\n */\nexport function isWeekday(\n date: DateOrCalendarDate,\n options?: Pick<BusinessDaysOptions, \"weekendDays\" | \"holidays\">,\n): boolean {\n return !isWeekend(date, options);\n}\n\n/**\n * Returns true if the specified date is a business day (neither weekend nor public holiday).\n */\nexport function isBusinessDay(\n date: DateOrCalendarDate,\n options?: BusinessDaysOptions,\n): boolean {\n const abs = getAbsoluteDay(date);\n return !isNonWorkingDay(abs, options);\n}\n\n/**\n * Adds business days to a LocalDate or CalendarDate, skipping weekends and optionally public holidays.\n * Supports positive, negative, and zero day additions.\n * Uses O(1) mathematical week advancement when no holidays are provided, or iterative evaluation with holiday constraints.\n */\nexport function addBusinessDays<T extends DateOrCalendarDate>(\n date: T,\n amount: number,\n options?: BusinessDaysOptions,\n): T {\n if (!Number.isFinite(amount)) {\n throw new ChroneraError(\n \"CHRONERA_OUT_OF_RANGE\",\n \"Amount must be a finite integer.\",\n );\n }\n\n const intAmount = Math.trunc(amount);\n if (intAmount === 0) {\n return date;\n }\n\n const startAbs = getAbsoluteDay(date);\n let currentAbs = startAbs;\n let remaining = intAmount;\n const step = remaining > 0 ? 1 : -1;\n\n // Fast-path: no holidays or custom weekends\n const hasHolidays = Boolean(options?.holidays);\n const hasCustomWeekends = Boolean(options?.weekendDays);\n\n if (!hasHolidays && !hasCustomWeekends) {\n while (remaining !== 0) {\n const currentDow = getIsoDayOfWeek(currentAbs);\n if (currentDow !== 6 && currentDow !== 7 && Math.abs(remaining) >= 5) {\n const fullWeeks = Math.trunc(remaining / 5);\n currentAbs += fullWeeks * 7;\n remaining %= 5;\n } else {\n currentAbs += step;\n const dow = getIsoDayOfWeek(currentAbs);\n if (dow !== 6 && dow !== 7) {\n remaining -= step;\n }\n }\n }\n } else {\n // Exact evaluation with holiday and custom weekend constraints\n while (remaining !== 0) {\n currentAbs += step;\n if (!isNonWorkingDay(currentAbs, options)) {\n remaining -= step;\n }\n }\n }\n\n const deltaDays = currentAbs - startAbs;\n return addDays(date, deltaDays);\n}\n\n/**\n * Subtracts business days from a LocalDate or CalendarDate, skipping weekends and optional holidays.\n */\nexport function subtractBusinessDays<T extends DateOrCalendarDate>(\n date: T,\n amount: number,\n options?: BusinessDaysOptions,\n): T {\n return addBusinessDays(date, -amount, options);\n}\n\n/**\n * Returns the signed count of business days between two dates (left - right).\n * Positive if left is after right, negative if left is before right, 0 if identical.\n */\nexport function diffInBusinessDays(\n left: DateOrCalendarDate,\n right: DateOrCalendarDate,\n options?: BusinessDaysOptions,\n): number {\n const absLeft = getAbsoluteDay(left);\n const absRight = getAbsoluteDay(right);\n\n if (absLeft === absRight) {\n return 0;\n }\n\n if (absLeft < absRight) {\n return -diffInBusinessDays(right, left, options);\n }\n\n let count = 0;\n let current = absRight;\n\n const hasHolidays = Boolean(options?.holidays);\n const hasCustomWeekends = Boolean(options?.weekendDays);\n\n if (!hasHolidays && !hasCustomWeekends) {\n // Fast-path O(1) acceleration: any consecutive 7 calendar days contains exactly 5 business days\n const fullWeeks = Math.floor((absLeft - current) / 7);\n if (fullWeeks > 0) {\n count += fullWeeks * 5;\n current += fullWeeks * 7;\n }\n\n while (current < absLeft) {\n current++;\n const dow = getIsoDayOfWeek(current);\n if (dow !== 6 && dow !== 7) {\n count++;\n }\n }\n } else {\n while (current < absLeft) {\n current++;\n if (!isNonWorkingDay(current, options)) {\n count++;\n }\n }\n }\n\n return count;\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CountryCode, HolidayCalendar, HolidayOptions, PublicHoliday } from "../holidays/types.js";
|
|
2
|
+
import type { DateOrCalendarDate } from "../public-types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if the specified date is an official public holiday in the given country.
|
|
5
|
+
* Supports both Gregorian LocalDate and any cultural CalendarDate (Thai Buddhist, Japanese Reiwa, Hijri, etc.).
|
|
6
|
+
*/
|
|
7
|
+
export declare function isPublicHoliday(date: DateOrCalendarDate, country: CountryCode | string | HolidayCalendar, options?: HolidayOptions): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Returns all public holidays for a given year in the specified country.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getPublicHolidays(year: number, country: CountryCode | string | HolidayCalendar, options?: HolidayOptions): readonly PublicHoliday[];
|
|
12
|
+
/**
|
|
13
|
+
* Returns the public holiday details if the specified date is a holiday, or undefined otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getHolidayDetails(date: DateOrCalendarDate, country: CountryCode | string | HolidayCalendar, options?: HolidayOptions): PublicHoliday | undefined;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { gregorianFromAbsoluteDay } from "../calendar/gregory/absolute-day.js";
|
|
2
|
+
import { localDate } from "../core/local-date.js";
|
|
3
|
+
import { getAbsoluteDay } from "./convenience.js";
|
|
4
|
+
import { resolveAnnualHolidays } from "../holidays/registry.js";
|
|
5
|
+
function toGregorianLocalDate(date) {
|
|
6
|
+
if (date.kind === "local-date") {
|
|
7
|
+
return date;
|
|
8
|
+
}
|
|
9
|
+
const abs = getAbsoluteDay(date);
|
|
10
|
+
const fields = gregorianFromAbsoluteDay(abs);
|
|
11
|
+
return localDate(fields.year, fields.month, fields.day);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns true if the specified date is an official public holiday in the given country.
|
|
15
|
+
* Supports both Gregorian LocalDate and any cultural CalendarDate (Thai Buddhist, Japanese Reiwa, Hijri, etc.).
|
|
16
|
+
*/
|
|
17
|
+
export function isPublicHoliday(date, country, options) {
|
|
18
|
+
const gDate = toGregorianLocalDate(date);
|
|
19
|
+
const annualHolidays = resolveAnnualHolidays(country, gDate.year, options);
|
|
20
|
+
return annualHolidays.some((h) => h.date.month === gDate.month && h.date.day === gDate.day);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Returns all public holidays for a given year in the specified country.
|
|
24
|
+
*/
|
|
25
|
+
export function getPublicHolidays(year, country, options) {
|
|
26
|
+
return resolveAnnualHolidays(country, year, options);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns the public holiday details if the specified date is a holiday, or undefined otherwise.
|
|
30
|
+
*/
|
|
31
|
+
export function getHolidayDetails(date, country, options) {
|
|
32
|
+
const gDate = toGregorianLocalDate(date);
|
|
33
|
+
const annualHolidays = resolveAnnualHolidays(country, gDate.year, options);
|
|
34
|
+
return annualHolidays.find((h) => h.date.month === gDate.month && h.date.day === gDate.day);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=holidays.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holidays.js","sourceRoot":"","sources":["../../src/operations/holidays.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAUhE,SAAS,oBAAoB,CAAC,IAAwB;IACpD,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,IAAwB,EACxB,OAA+C,EAC/C,OAAwB;IAExB,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3E,OAAO,cAAc,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAChE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,OAA+C,EAC/C,OAAwB;IAExB,OAAO,qBAAqB,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAwB,EACxB,OAA+C,EAC/C,OAAwB;IAExB,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE3E,OAAO,cAAc,CAAC,IAAI,CACxB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,CAChE,CAAC;AACJ,CAAC","sourcesContent":["import { gregorianFromAbsoluteDay } from \"../calendar/gregory/absolute-day.js\";\nimport { localDate } from \"../core/local-date.js\";\nimport { getAbsoluteDay } from \"./convenience.js\";\nimport { resolveAnnualHolidays } from \"../holidays/registry.js\";\n\nimport type {\n CountryCode,\n HolidayCalendar,\n HolidayOptions,\n PublicHoliday,\n} from \"../holidays/types.js\";\nimport type { DateOrCalendarDate, LocalDate } from \"../public-types.js\";\n\nfunction toGregorianLocalDate(date: DateOrCalendarDate): LocalDate {\n if (date.kind === \"local-date\") {\n return date;\n }\n const abs = getAbsoluteDay(date);\n const fields = gregorianFromAbsoluteDay(abs);\n return localDate(fields.year, fields.month, fields.day);\n}\n\n/**\n * Returns true if the specified date is an official public holiday in the given country.\n * Supports both Gregorian LocalDate and any cultural CalendarDate (Thai Buddhist, Japanese Reiwa, Hijri, etc.).\n */\nexport function isPublicHoliday(\n date: DateOrCalendarDate,\n country: CountryCode | string | HolidayCalendar,\n options?: HolidayOptions,\n): boolean {\n const gDate = toGregorianLocalDate(date);\n const annualHolidays = resolveAnnualHolidays(country, gDate.year, options);\n\n return annualHolidays.some(\n (h) => h.date.month === gDate.month && h.date.day === gDate.day,\n );\n}\n\n/**\n * Returns all public holidays for a given year in the specified country.\n */\nexport function getPublicHolidays(\n year: number,\n country: CountryCode | string | HolidayCalendar,\n options?: HolidayOptions,\n): readonly PublicHoliday[] {\n return resolveAnnualHolidays(country, year, options);\n}\n\n/**\n * Returns the public holiday details if the specified date is a holiday, or undefined otherwise.\n */\nexport function getHolidayDetails(\n date: DateOrCalendarDate,\n country: CountryCode | string | HolidayCalendar,\n options?: HolidayOptions,\n): PublicHoliday | undefined {\n const gDate = toGregorianLocalDate(date);\n const annualHolidays = resolveAnnualHolidays(country, gDate.year, options);\n\n return annualHolidays.find(\n (h) => h.date.month === gDate.month && h.date.day === gDate.day,\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intech-software/chronera",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A universal, type-safe date, time, calendar, era, locale, and timezone toolkit for JavaScript and TypeScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"date",
|
|
@@ -53,6 +53,10 @@
|
|
|
53
53
|
"./parse": {
|
|
54
54
|
"types": "./dist/parse/index.d.ts",
|
|
55
55
|
"import": "./dist/parse/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./holidays": {
|
|
58
|
+
"types": "./dist/holidays/index.d.ts",
|
|
59
|
+
"import": "./dist/holidays/index.js"
|
|
56
60
|
}
|
|
57
61
|
},
|
|
58
62
|
"files": [
|
|
@@ -98,6 +102,11 @@
|
|
|
98
102
|
"name": "Parse (@intech-software/chronera/parse)",
|
|
99
103
|
"path": "dist/parse/index.js",
|
|
100
104
|
"limit": "10 KB"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"name": "Holidays (@intech-software/chronera/holidays)",
|
|
108
|
+
"path": "dist/holidays/index.js",
|
|
109
|
+
"limit": "10 KB"
|
|
101
110
|
}
|
|
102
111
|
],
|
|
103
112
|
"publishConfig": {
|