ts-time-utils 1.1.0 → 3.0.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/README.md +567 -12
- package/dist/calculate.d.ts +7 -2
- package/dist/calculate.d.ts.map +1 -1
- package/dist/calculate.js +13 -3
- package/dist/calendar.d.ts +103 -0
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +224 -0
- package/dist/chain.d.ts +269 -0
- package/dist/chain.d.ts.map +1 -0
- package/dist/chain.js +422 -0
- package/dist/compare.d.ts +217 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/compare.js +417 -0
- package/dist/cron.d.ts +82 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +294 -0
- package/dist/esm/calculate.d.ts +7 -2
- package/dist/esm/calculate.d.ts.map +1 -1
- package/dist/esm/calculate.js +13 -3
- package/dist/esm/calendar.d.ts +103 -0
- package/dist/esm/calendar.d.ts.map +1 -1
- package/dist/esm/calendar.js +224 -0
- package/dist/esm/chain.d.ts +269 -0
- package/dist/esm/chain.d.ts.map +1 -0
- package/dist/esm/chain.js +422 -0
- package/dist/esm/compare.d.ts +217 -0
- package/dist/esm/compare.d.ts.map +1 -0
- package/dist/esm/compare.js +417 -0
- package/dist/esm/cron.d.ts +82 -0
- package/dist/esm/cron.d.ts.map +1 -0
- package/dist/esm/cron.js +294 -0
- package/dist/esm/fiscal.d.ts +195 -0
- package/dist/esm/fiscal.d.ts.map +1 -0
- package/dist/esm/fiscal.js +295 -0
- package/dist/esm/format.d.ts +65 -0
- package/dist/esm/format.d.ts.map +1 -1
- package/dist/esm/format.js +202 -0
- package/dist/esm/holidays.d.ts +62 -0
- package/dist/esm/holidays.d.ts.map +1 -0
- package/dist/esm/holidays.js +793 -0
- package/dist/esm/index.d.ts +18 -6
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +20 -6
- package/dist/esm/iterate.d.ts +212 -0
- package/dist/esm/iterate.d.ts.map +1 -0
- package/dist/esm/iterate.js +409 -0
- package/dist/esm/parse.d.ts +45 -0
- package/dist/esm/parse.d.ts.map +1 -1
- package/dist/esm/parse.js +207 -0
- package/dist/esm/plugins.d.ts +129 -0
- package/dist/esm/plugins.d.ts.map +1 -0
- package/dist/esm/plugins.js +173 -0
- package/dist/esm/timezone.d.ts +52 -0
- package/dist/esm/timezone.d.ts.map +1 -1
- package/dist/esm/timezone.js +171 -0
- package/dist/esm/validate.d.ts +51 -0
- package/dist/esm/validate.d.ts.map +1 -1
- package/dist/esm/validate.js +92 -0
- package/dist/esm/workingHours.d.ts +70 -0
- package/dist/esm/workingHours.d.ts.map +1 -1
- package/dist/esm/workingHours.js +161 -0
- package/dist/fiscal.d.ts +195 -0
- package/dist/fiscal.d.ts.map +1 -0
- package/dist/fiscal.js +295 -0
- package/dist/format.d.ts +65 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +202 -0
- package/dist/holidays.d.ts +62 -0
- package/dist/holidays.d.ts.map +1 -0
- package/dist/holidays.js +793 -0
- package/dist/index.d.ts +18 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -6
- package/dist/iterate.d.ts +212 -0
- package/dist/iterate.d.ts.map +1 -0
- package/dist/iterate.js +409 -0
- package/dist/parse.d.ts +45 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +207 -0
- package/dist/plugins.d.ts +129 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +173 -0
- package/dist/timezone.d.ts +52 -0
- package/dist/timezone.d.ts.map +1 -1
- package/dist/timezone.js +171 -0
- package/dist/validate.d.ts +51 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +92 -0
- package/dist/workingHours.d.ts +70 -0
- package/dist/workingHours.d.ts.map +1 -1
- package/dist/workingHours.js +161 -0
- package/package.json +40 -1
|
@@ -0,0 +1,793 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview International holiday utilities
|
|
3
|
+
* Calculate holidays for multiple countries including fixed, movable, and lunar-based holidays
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Calculate Easter Sunday using the Anonymous Gregorian algorithm
|
|
7
|
+
* @param year - The year
|
|
8
|
+
* @returns Date of Easter Sunday
|
|
9
|
+
*/
|
|
10
|
+
function getEasterSunday(year) {
|
|
11
|
+
const a = year % 19;
|
|
12
|
+
const b = Math.floor(year / 100);
|
|
13
|
+
const c = year % 100;
|
|
14
|
+
const d = Math.floor(b / 4);
|
|
15
|
+
const e = b % 4;
|
|
16
|
+
const f = Math.floor((b + 8) / 25);
|
|
17
|
+
const g = Math.floor((b - f + 1) / 3);
|
|
18
|
+
const h = (19 * a + b - d - g + 15) % 30;
|
|
19
|
+
const i = Math.floor(c / 4);
|
|
20
|
+
const k = c % 4;
|
|
21
|
+
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
|
22
|
+
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
23
|
+
const month = Math.floor((h + l - 7 * m + 114) / 31);
|
|
24
|
+
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
|
25
|
+
return new Date(year, month - 1, day);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get nth occurrence of a weekday in a month
|
|
29
|
+
*/
|
|
30
|
+
function getNthWeekdayOfMonth(year, month, dayOfWeek, n) {
|
|
31
|
+
const firstDay = new Date(year, month, 1);
|
|
32
|
+
const firstWeekday = firstDay.getDay();
|
|
33
|
+
let dayOffset = dayOfWeek - firstWeekday;
|
|
34
|
+
if (dayOffset < 0)
|
|
35
|
+
dayOffset += 7;
|
|
36
|
+
const date = 1 + dayOffset + (n - 1) * 7;
|
|
37
|
+
return new Date(year, month, date);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get last occurrence of a weekday in a month
|
|
41
|
+
*/
|
|
42
|
+
function getLastWeekdayOfMonth(year, month, dayOfWeek) {
|
|
43
|
+
const lastDay = new Date(year, month + 1, 0);
|
|
44
|
+
const lastDate = lastDay.getDate();
|
|
45
|
+
const lastWeekday = lastDay.getDay();
|
|
46
|
+
let diff = lastWeekday - dayOfWeek;
|
|
47
|
+
if (diff < 0)
|
|
48
|
+
diff += 7;
|
|
49
|
+
return new Date(year, month, lastDate - diff);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Adjust date if it falls on a weekend (move to Monday)
|
|
53
|
+
*/
|
|
54
|
+
function adjustForWeekend(date) {
|
|
55
|
+
const day = date.getDay();
|
|
56
|
+
if (day === 0) { // Sunday
|
|
57
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 1);
|
|
58
|
+
}
|
|
59
|
+
else if (day === 6) { // Saturday
|
|
60
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate() + 2);
|
|
61
|
+
}
|
|
62
|
+
return date;
|
|
63
|
+
}
|
|
64
|
+
// ============================================================================
|
|
65
|
+
// UK HOLIDAYS
|
|
66
|
+
// ============================================================================
|
|
67
|
+
export function getUKHolidays(year) {
|
|
68
|
+
const holidays = [];
|
|
69
|
+
// New Year's Day (or substitute)
|
|
70
|
+
holidays.push({
|
|
71
|
+
name: "New Year's Day",
|
|
72
|
+
date: adjustForWeekend(new Date(year, 0, 1)),
|
|
73
|
+
countryCode: 'UK',
|
|
74
|
+
type: 'bank'
|
|
75
|
+
});
|
|
76
|
+
// Good Friday (Easter - 2 days)
|
|
77
|
+
const easter = getEasterSunday(year);
|
|
78
|
+
holidays.push({
|
|
79
|
+
name: 'Good Friday',
|
|
80
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
81
|
+
countryCode: 'UK',
|
|
82
|
+
type: 'bank'
|
|
83
|
+
});
|
|
84
|
+
// Easter Monday (Easter + 1 day)
|
|
85
|
+
holidays.push({
|
|
86
|
+
name: 'Easter Monday',
|
|
87
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 1),
|
|
88
|
+
countryCode: 'UK',
|
|
89
|
+
type: 'bank'
|
|
90
|
+
});
|
|
91
|
+
// Early May Bank Holiday (first Monday in May)
|
|
92
|
+
holidays.push({
|
|
93
|
+
name: 'Early May Bank Holiday',
|
|
94
|
+
date: getNthWeekdayOfMonth(year, 4, 1, 1),
|
|
95
|
+
countryCode: 'UK',
|
|
96
|
+
type: 'bank'
|
|
97
|
+
});
|
|
98
|
+
// Spring Bank Holiday (last Monday in May)
|
|
99
|
+
holidays.push({
|
|
100
|
+
name: 'Spring Bank Holiday',
|
|
101
|
+
date: getLastWeekdayOfMonth(year, 4, 1),
|
|
102
|
+
countryCode: 'UK',
|
|
103
|
+
type: 'bank'
|
|
104
|
+
});
|
|
105
|
+
// Summer Bank Holiday (last Monday in August)
|
|
106
|
+
holidays.push({
|
|
107
|
+
name: 'Summer Bank Holiday',
|
|
108
|
+
date: getLastWeekdayOfMonth(year, 7, 1),
|
|
109
|
+
countryCode: 'UK',
|
|
110
|
+
type: 'bank'
|
|
111
|
+
});
|
|
112
|
+
// Christmas Day
|
|
113
|
+
holidays.push({
|
|
114
|
+
name: 'Christmas Day',
|
|
115
|
+
date: adjustForWeekend(new Date(year, 11, 25)),
|
|
116
|
+
countryCode: 'UK',
|
|
117
|
+
type: 'bank'
|
|
118
|
+
});
|
|
119
|
+
// Boxing Day
|
|
120
|
+
const christmas = new Date(year, 11, 25);
|
|
121
|
+
let boxingDay = new Date(year, 11, 26);
|
|
122
|
+
if (christmas.getDay() === 6) { // Christmas on Saturday
|
|
123
|
+
boxingDay = new Date(year, 11, 28); // Monday
|
|
124
|
+
}
|
|
125
|
+
else if (christmas.getDay() === 0) { // Christmas on Sunday
|
|
126
|
+
boxingDay = new Date(year, 11, 27); // Tuesday (Monday is Christmas substitute)
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
boxingDay = adjustForWeekend(boxingDay);
|
|
130
|
+
}
|
|
131
|
+
holidays.push({
|
|
132
|
+
name: 'Boxing Day',
|
|
133
|
+
date: boxingDay,
|
|
134
|
+
countryCode: 'UK',
|
|
135
|
+
type: 'bank'
|
|
136
|
+
});
|
|
137
|
+
return holidays;
|
|
138
|
+
}
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// NETHERLANDS HOLIDAYS
|
|
141
|
+
// ============================================================================
|
|
142
|
+
export function getNetherlandsHolidays(year) {
|
|
143
|
+
const holidays = [];
|
|
144
|
+
const easter = getEasterSunday(year);
|
|
145
|
+
// New Year's Day
|
|
146
|
+
holidays.push({
|
|
147
|
+
name: "New Year's Day",
|
|
148
|
+
date: new Date(year, 0, 1),
|
|
149
|
+
countryCode: 'NL',
|
|
150
|
+
type: 'public'
|
|
151
|
+
});
|
|
152
|
+
// Good Friday
|
|
153
|
+
holidays.push({
|
|
154
|
+
name: 'Good Friday',
|
|
155
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
156
|
+
countryCode: 'NL',
|
|
157
|
+
type: 'observance'
|
|
158
|
+
});
|
|
159
|
+
// Easter Sunday
|
|
160
|
+
holidays.push({
|
|
161
|
+
name: 'Easter Sunday',
|
|
162
|
+
date: easter,
|
|
163
|
+
countryCode: 'NL',
|
|
164
|
+
type: 'public'
|
|
165
|
+
});
|
|
166
|
+
// Easter Monday
|
|
167
|
+
holidays.push({
|
|
168
|
+
name: 'Easter Monday',
|
|
169
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 1),
|
|
170
|
+
countryCode: 'NL',
|
|
171
|
+
type: 'public'
|
|
172
|
+
});
|
|
173
|
+
// King's Day (April 27, or 26 if 27th is Sunday)
|
|
174
|
+
const kingsDay = new Date(year, 3, 27);
|
|
175
|
+
if (kingsDay.getDay() === 0) {
|
|
176
|
+
holidays.push({
|
|
177
|
+
name: "King's Day",
|
|
178
|
+
date: new Date(year, 3, 26),
|
|
179
|
+
countryCode: 'NL',
|
|
180
|
+
type: 'public'
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
holidays.push({
|
|
185
|
+
name: "King's Day",
|
|
186
|
+
date: kingsDay,
|
|
187
|
+
countryCode: 'NL',
|
|
188
|
+
type: 'public'
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
// Liberation Day (May 5)
|
|
192
|
+
holidays.push({
|
|
193
|
+
name: 'Liberation Day',
|
|
194
|
+
date: new Date(year, 4, 5),
|
|
195
|
+
countryCode: 'NL',
|
|
196
|
+
type: 'public'
|
|
197
|
+
});
|
|
198
|
+
// Ascension Day (Easter + 39 days)
|
|
199
|
+
holidays.push({
|
|
200
|
+
name: 'Ascension Day',
|
|
201
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 39),
|
|
202
|
+
countryCode: 'NL',
|
|
203
|
+
type: 'public'
|
|
204
|
+
});
|
|
205
|
+
// Whit Sunday (Easter + 49 days)
|
|
206
|
+
holidays.push({
|
|
207
|
+
name: 'Whit Sunday',
|
|
208
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 49),
|
|
209
|
+
countryCode: 'NL',
|
|
210
|
+
type: 'public'
|
|
211
|
+
});
|
|
212
|
+
// Whit Monday (Easter + 50 days)
|
|
213
|
+
holidays.push({
|
|
214
|
+
name: 'Whit Monday',
|
|
215
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 50),
|
|
216
|
+
countryCode: 'NL',
|
|
217
|
+
type: 'public'
|
|
218
|
+
});
|
|
219
|
+
// Christmas Day
|
|
220
|
+
holidays.push({
|
|
221
|
+
name: 'Christmas Day',
|
|
222
|
+
date: new Date(year, 11, 25),
|
|
223
|
+
countryCode: 'NL',
|
|
224
|
+
type: 'public'
|
|
225
|
+
});
|
|
226
|
+
// Boxing Day
|
|
227
|
+
holidays.push({
|
|
228
|
+
name: 'Boxing Day',
|
|
229
|
+
date: new Date(year, 11, 26),
|
|
230
|
+
countryCode: 'NL',
|
|
231
|
+
type: 'public'
|
|
232
|
+
});
|
|
233
|
+
return holidays;
|
|
234
|
+
}
|
|
235
|
+
// ============================================================================
|
|
236
|
+
// GERMANY HOLIDAYS
|
|
237
|
+
// ============================================================================
|
|
238
|
+
export function getGermanyHolidays(year) {
|
|
239
|
+
const holidays = [];
|
|
240
|
+
const easter = getEasterSunday(year);
|
|
241
|
+
// New Year's Day
|
|
242
|
+
holidays.push({
|
|
243
|
+
name: "New Year's Day",
|
|
244
|
+
date: new Date(year, 0, 1),
|
|
245
|
+
countryCode: 'DE',
|
|
246
|
+
type: 'public'
|
|
247
|
+
});
|
|
248
|
+
// Good Friday
|
|
249
|
+
holidays.push({
|
|
250
|
+
name: 'Good Friday',
|
|
251
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
252
|
+
countryCode: 'DE',
|
|
253
|
+
type: 'public'
|
|
254
|
+
});
|
|
255
|
+
// Easter Monday
|
|
256
|
+
holidays.push({
|
|
257
|
+
name: 'Easter Monday',
|
|
258
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 1),
|
|
259
|
+
countryCode: 'DE',
|
|
260
|
+
type: 'public'
|
|
261
|
+
});
|
|
262
|
+
// Labour Day
|
|
263
|
+
holidays.push({
|
|
264
|
+
name: 'Labour Day',
|
|
265
|
+
date: new Date(year, 4, 1),
|
|
266
|
+
countryCode: 'DE',
|
|
267
|
+
type: 'public'
|
|
268
|
+
});
|
|
269
|
+
// Ascension Day
|
|
270
|
+
holidays.push({
|
|
271
|
+
name: 'Ascension Day',
|
|
272
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 39),
|
|
273
|
+
countryCode: 'DE',
|
|
274
|
+
type: 'public'
|
|
275
|
+
});
|
|
276
|
+
// Whit Monday
|
|
277
|
+
holidays.push({
|
|
278
|
+
name: 'Whit Monday',
|
|
279
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 50),
|
|
280
|
+
countryCode: 'DE',
|
|
281
|
+
type: 'public'
|
|
282
|
+
});
|
|
283
|
+
// German Unity Day
|
|
284
|
+
holidays.push({
|
|
285
|
+
name: 'German Unity Day',
|
|
286
|
+
date: new Date(year, 9, 3),
|
|
287
|
+
countryCode: 'DE',
|
|
288
|
+
type: 'public'
|
|
289
|
+
});
|
|
290
|
+
// Christmas Day
|
|
291
|
+
holidays.push({
|
|
292
|
+
name: 'Christmas Day',
|
|
293
|
+
date: new Date(year, 11, 25),
|
|
294
|
+
countryCode: 'DE',
|
|
295
|
+
type: 'public'
|
|
296
|
+
});
|
|
297
|
+
// Boxing Day
|
|
298
|
+
holidays.push({
|
|
299
|
+
name: 'Boxing Day',
|
|
300
|
+
date: new Date(year, 11, 26),
|
|
301
|
+
countryCode: 'DE',
|
|
302
|
+
type: 'public'
|
|
303
|
+
});
|
|
304
|
+
return holidays;
|
|
305
|
+
}
|
|
306
|
+
// ============================================================================
|
|
307
|
+
// CANADA HOLIDAYS
|
|
308
|
+
// ============================================================================
|
|
309
|
+
export function getCanadaHolidays(year) {
|
|
310
|
+
const holidays = [];
|
|
311
|
+
const easter = getEasterSunday(year);
|
|
312
|
+
// New Year's Day
|
|
313
|
+
holidays.push({
|
|
314
|
+
name: "New Year's Day",
|
|
315
|
+
date: adjustForWeekend(new Date(year, 0, 1)),
|
|
316
|
+
countryCode: 'CA',
|
|
317
|
+
type: 'public'
|
|
318
|
+
});
|
|
319
|
+
// Good Friday
|
|
320
|
+
holidays.push({
|
|
321
|
+
name: 'Good Friday',
|
|
322
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
323
|
+
countryCode: 'CA',
|
|
324
|
+
type: 'public'
|
|
325
|
+
});
|
|
326
|
+
// Victoria Day (Monday before May 25)
|
|
327
|
+
const may24 = new Date(year, 4, 24);
|
|
328
|
+
const victoriaDay = new Date(year, 4, 24 - ((may24.getDay() + 6) % 7));
|
|
329
|
+
holidays.push({
|
|
330
|
+
name: 'Victoria Day',
|
|
331
|
+
date: victoriaDay,
|
|
332
|
+
countryCode: 'CA',
|
|
333
|
+
type: 'public'
|
|
334
|
+
});
|
|
335
|
+
// Canada Day (July 1, or substitute)
|
|
336
|
+
holidays.push({
|
|
337
|
+
name: 'Canada Day',
|
|
338
|
+
date: adjustForWeekend(new Date(year, 6, 1)),
|
|
339
|
+
countryCode: 'CA',
|
|
340
|
+
type: 'public'
|
|
341
|
+
});
|
|
342
|
+
// Labour Day (first Monday in September)
|
|
343
|
+
holidays.push({
|
|
344
|
+
name: 'Labour Day',
|
|
345
|
+
date: getNthWeekdayOfMonth(year, 8, 1, 1),
|
|
346
|
+
countryCode: 'CA',
|
|
347
|
+
type: 'public'
|
|
348
|
+
});
|
|
349
|
+
// Thanksgiving (second Monday in October)
|
|
350
|
+
holidays.push({
|
|
351
|
+
name: 'Thanksgiving',
|
|
352
|
+
date: getNthWeekdayOfMonth(year, 9, 1, 2),
|
|
353
|
+
countryCode: 'CA',
|
|
354
|
+
type: 'public'
|
|
355
|
+
});
|
|
356
|
+
// Remembrance Day
|
|
357
|
+
holidays.push({
|
|
358
|
+
name: 'Remembrance Day',
|
|
359
|
+
date: new Date(year, 10, 11),
|
|
360
|
+
countryCode: 'CA',
|
|
361
|
+
type: 'public'
|
|
362
|
+
});
|
|
363
|
+
// Christmas Day
|
|
364
|
+
holidays.push({
|
|
365
|
+
name: 'Christmas Day',
|
|
366
|
+
date: adjustForWeekend(new Date(year, 11, 25)),
|
|
367
|
+
countryCode: 'CA',
|
|
368
|
+
type: 'public'
|
|
369
|
+
});
|
|
370
|
+
// Boxing Day
|
|
371
|
+
holidays.push({
|
|
372
|
+
name: 'Boxing Day',
|
|
373
|
+
date: adjustForWeekend(new Date(year, 11, 26)),
|
|
374
|
+
countryCode: 'CA',
|
|
375
|
+
type: 'public'
|
|
376
|
+
});
|
|
377
|
+
return holidays;
|
|
378
|
+
}
|
|
379
|
+
// ============================================================================
|
|
380
|
+
// AUSTRALIA HOLIDAYS
|
|
381
|
+
// ============================================================================
|
|
382
|
+
export function getAustraliaHolidays(year) {
|
|
383
|
+
const holidays = [];
|
|
384
|
+
const easter = getEasterSunday(year);
|
|
385
|
+
// New Year's Day
|
|
386
|
+
holidays.push({
|
|
387
|
+
name: "New Year's Day",
|
|
388
|
+
date: adjustForWeekend(new Date(year, 0, 1)),
|
|
389
|
+
countryCode: 'AU',
|
|
390
|
+
type: 'public'
|
|
391
|
+
});
|
|
392
|
+
// Australia Day (January 26)
|
|
393
|
+
holidays.push({
|
|
394
|
+
name: 'Australia Day',
|
|
395
|
+
date: adjustForWeekend(new Date(year, 0, 26)),
|
|
396
|
+
countryCode: 'AU',
|
|
397
|
+
type: 'public'
|
|
398
|
+
});
|
|
399
|
+
// Good Friday
|
|
400
|
+
holidays.push({
|
|
401
|
+
name: 'Good Friday',
|
|
402
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
403
|
+
countryCode: 'AU',
|
|
404
|
+
type: 'public'
|
|
405
|
+
});
|
|
406
|
+
// Easter Saturday
|
|
407
|
+
holidays.push({
|
|
408
|
+
name: 'Easter Saturday',
|
|
409
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 1),
|
|
410
|
+
countryCode: 'AU',
|
|
411
|
+
type: 'public'
|
|
412
|
+
});
|
|
413
|
+
// Easter Monday
|
|
414
|
+
holidays.push({
|
|
415
|
+
name: 'Easter Monday',
|
|
416
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 1),
|
|
417
|
+
countryCode: 'AU',
|
|
418
|
+
type: 'public'
|
|
419
|
+
});
|
|
420
|
+
// Anzac Day (April 25)
|
|
421
|
+
holidays.push({
|
|
422
|
+
name: 'Anzac Day',
|
|
423
|
+
date: new Date(year, 3, 25),
|
|
424
|
+
countryCode: 'AU',
|
|
425
|
+
type: 'public'
|
|
426
|
+
});
|
|
427
|
+
// Queen's Birthday (second Monday in June)
|
|
428
|
+
holidays.push({
|
|
429
|
+
name: "Queen's Birthday",
|
|
430
|
+
date: getNthWeekdayOfMonth(year, 5, 1, 2),
|
|
431
|
+
countryCode: 'AU',
|
|
432
|
+
type: 'public'
|
|
433
|
+
});
|
|
434
|
+
// Christmas Day
|
|
435
|
+
holidays.push({
|
|
436
|
+
name: 'Christmas Day',
|
|
437
|
+
date: adjustForWeekend(new Date(year, 11, 25)),
|
|
438
|
+
countryCode: 'AU',
|
|
439
|
+
type: 'public'
|
|
440
|
+
});
|
|
441
|
+
// Boxing Day
|
|
442
|
+
holidays.push({
|
|
443
|
+
name: 'Boxing Day',
|
|
444
|
+
date: adjustForWeekend(new Date(year, 11, 26)),
|
|
445
|
+
countryCode: 'AU',
|
|
446
|
+
type: 'public'
|
|
447
|
+
});
|
|
448
|
+
return holidays;
|
|
449
|
+
}
|
|
450
|
+
// ============================================================================
|
|
451
|
+
// ITALY HOLIDAYS
|
|
452
|
+
// ============================================================================
|
|
453
|
+
export function getItalyHolidays(year) {
|
|
454
|
+
const holidays = [];
|
|
455
|
+
const easter = getEasterSunday(year);
|
|
456
|
+
// New Year's Day
|
|
457
|
+
holidays.push({
|
|
458
|
+
name: "New Year's Day",
|
|
459
|
+
date: new Date(year, 0, 1),
|
|
460
|
+
countryCode: 'IT',
|
|
461
|
+
type: 'public'
|
|
462
|
+
});
|
|
463
|
+
// Epiphany
|
|
464
|
+
holidays.push({
|
|
465
|
+
name: 'Epiphany',
|
|
466
|
+
date: new Date(year, 0, 6),
|
|
467
|
+
countryCode: 'IT',
|
|
468
|
+
type: 'public'
|
|
469
|
+
});
|
|
470
|
+
// Easter Monday
|
|
471
|
+
holidays.push({
|
|
472
|
+
name: 'Easter Monday',
|
|
473
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() + 1),
|
|
474
|
+
countryCode: 'IT',
|
|
475
|
+
type: 'public'
|
|
476
|
+
});
|
|
477
|
+
// Liberation Day
|
|
478
|
+
holidays.push({
|
|
479
|
+
name: 'Liberation Day',
|
|
480
|
+
date: new Date(year, 3, 25),
|
|
481
|
+
countryCode: 'IT',
|
|
482
|
+
type: 'public'
|
|
483
|
+
});
|
|
484
|
+
// Labour Day
|
|
485
|
+
holidays.push({
|
|
486
|
+
name: 'Labour Day',
|
|
487
|
+
date: new Date(year, 4, 1),
|
|
488
|
+
countryCode: 'IT',
|
|
489
|
+
type: 'public'
|
|
490
|
+
});
|
|
491
|
+
// Republic Day
|
|
492
|
+
holidays.push({
|
|
493
|
+
name: 'Republic Day',
|
|
494
|
+
date: new Date(year, 5, 2),
|
|
495
|
+
countryCode: 'IT',
|
|
496
|
+
type: 'public'
|
|
497
|
+
});
|
|
498
|
+
// Assumption of Mary
|
|
499
|
+
holidays.push({
|
|
500
|
+
name: 'Assumption of Mary',
|
|
501
|
+
date: new Date(year, 7, 15),
|
|
502
|
+
countryCode: 'IT',
|
|
503
|
+
type: 'public'
|
|
504
|
+
});
|
|
505
|
+
// All Saints' Day
|
|
506
|
+
holidays.push({
|
|
507
|
+
name: "All Saints' Day",
|
|
508
|
+
date: new Date(year, 10, 1),
|
|
509
|
+
countryCode: 'IT',
|
|
510
|
+
type: 'public'
|
|
511
|
+
});
|
|
512
|
+
// Immaculate Conception
|
|
513
|
+
holidays.push({
|
|
514
|
+
name: 'Immaculate Conception',
|
|
515
|
+
date: new Date(year, 11, 8),
|
|
516
|
+
countryCode: 'IT',
|
|
517
|
+
type: 'public'
|
|
518
|
+
});
|
|
519
|
+
// Christmas Day
|
|
520
|
+
holidays.push({
|
|
521
|
+
name: 'Christmas Day',
|
|
522
|
+
date: new Date(year, 11, 25),
|
|
523
|
+
countryCode: 'IT',
|
|
524
|
+
type: 'public'
|
|
525
|
+
});
|
|
526
|
+
// St. Stephen's Day
|
|
527
|
+
holidays.push({
|
|
528
|
+
name: "St. Stephen's Day",
|
|
529
|
+
date: new Date(year, 11, 26),
|
|
530
|
+
countryCode: 'IT',
|
|
531
|
+
type: 'public'
|
|
532
|
+
});
|
|
533
|
+
return holidays;
|
|
534
|
+
}
|
|
535
|
+
// ============================================================================
|
|
536
|
+
// SPAIN HOLIDAYS
|
|
537
|
+
// ============================================================================
|
|
538
|
+
export function getSpainHolidays(year) {
|
|
539
|
+
const holidays = [];
|
|
540
|
+
const easter = getEasterSunday(year);
|
|
541
|
+
// New Year's Day
|
|
542
|
+
holidays.push({
|
|
543
|
+
name: "New Year's Day",
|
|
544
|
+
date: new Date(year, 0, 1),
|
|
545
|
+
countryCode: 'ES',
|
|
546
|
+
type: 'public'
|
|
547
|
+
});
|
|
548
|
+
// Epiphany
|
|
549
|
+
holidays.push({
|
|
550
|
+
name: 'Epiphany',
|
|
551
|
+
date: new Date(year, 0, 6),
|
|
552
|
+
countryCode: 'ES',
|
|
553
|
+
type: 'public'
|
|
554
|
+
});
|
|
555
|
+
// Good Friday
|
|
556
|
+
holidays.push({
|
|
557
|
+
name: 'Good Friday',
|
|
558
|
+
date: new Date(easter.getFullYear(), easter.getMonth(), easter.getDate() - 2),
|
|
559
|
+
countryCode: 'ES',
|
|
560
|
+
type: 'public'
|
|
561
|
+
});
|
|
562
|
+
// Labour Day
|
|
563
|
+
holidays.push({
|
|
564
|
+
name: 'Labour Day',
|
|
565
|
+
date: new Date(year, 4, 1),
|
|
566
|
+
countryCode: 'ES',
|
|
567
|
+
type: 'public'
|
|
568
|
+
});
|
|
569
|
+
// Assumption of Mary
|
|
570
|
+
holidays.push({
|
|
571
|
+
name: 'Assumption of Mary',
|
|
572
|
+
date: new Date(year, 7, 15),
|
|
573
|
+
countryCode: 'ES',
|
|
574
|
+
type: 'public'
|
|
575
|
+
});
|
|
576
|
+
// National Day of Spain
|
|
577
|
+
holidays.push({
|
|
578
|
+
name: 'National Day of Spain',
|
|
579
|
+
date: new Date(year, 9, 12),
|
|
580
|
+
countryCode: 'ES',
|
|
581
|
+
type: 'public'
|
|
582
|
+
});
|
|
583
|
+
// All Saints' Day
|
|
584
|
+
holidays.push({
|
|
585
|
+
name: "All Saints' Day",
|
|
586
|
+
date: new Date(year, 10, 1),
|
|
587
|
+
countryCode: 'ES',
|
|
588
|
+
type: 'public'
|
|
589
|
+
});
|
|
590
|
+
// Constitution Day
|
|
591
|
+
holidays.push({
|
|
592
|
+
name: 'Constitution Day',
|
|
593
|
+
date: new Date(year, 11, 6),
|
|
594
|
+
countryCode: 'ES',
|
|
595
|
+
type: 'public'
|
|
596
|
+
});
|
|
597
|
+
// Immaculate Conception
|
|
598
|
+
holidays.push({
|
|
599
|
+
name: 'Immaculate Conception',
|
|
600
|
+
date: new Date(year, 11, 8),
|
|
601
|
+
countryCode: 'ES',
|
|
602
|
+
type: 'public'
|
|
603
|
+
});
|
|
604
|
+
// Christmas Day
|
|
605
|
+
holidays.push({
|
|
606
|
+
name: 'Christmas Day',
|
|
607
|
+
date: new Date(year, 11, 25),
|
|
608
|
+
countryCode: 'ES',
|
|
609
|
+
type: 'public'
|
|
610
|
+
});
|
|
611
|
+
return holidays;
|
|
612
|
+
}
|
|
613
|
+
// ============================================================================
|
|
614
|
+
// CHINA HOLIDAYS (Simplified - some are lunar calendar based)
|
|
615
|
+
// ============================================================================
|
|
616
|
+
export function getChinaHolidays(year) {
|
|
617
|
+
const holidays = [];
|
|
618
|
+
// New Year's Day
|
|
619
|
+
holidays.push({
|
|
620
|
+
name: "New Year's Day",
|
|
621
|
+
date: new Date(year, 0, 1),
|
|
622
|
+
countryCode: 'CN',
|
|
623
|
+
type: 'public'
|
|
624
|
+
});
|
|
625
|
+
// Note: Spring Festival (Chinese New Year) is lunar calendar based
|
|
626
|
+
// This is a simplified version - actual dates vary by year
|
|
627
|
+
// Would need a lunar calendar library for accurate dates
|
|
628
|
+
// Tomb Sweeping Day (April 4 or 5)
|
|
629
|
+
holidays.push({
|
|
630
|
+
name: 'Tomb Sweeping Day',
|
|
631
|
+
date: new Date(year, 3, 4),
|
|
632
|
+
countryCode: 'CN',
|
|
633
|
+
type: 'public'
|
|
634
|
+
});
|
|
635
|
+
// Labour Day
|
|
636
|
+
holidays.push({
|
|
637
|
+
name: 'Labour Day',
|
|
638
|
+
date: new Date(year, 4, 1),
|
|
639
|
+
countryCode: 'CN',
|
|
640
|
+
type: 'public'
|
|
641
|
+
});
|
|
642
|
+
// Dragon Boat Festival (lunar calendar - approximate)
|
|
643
|
+
// Note: Actual date varies, this is simplified
|
|
644
|
+
// Mid-Autumn Festival (lunar calendar - approximate)
|
|
645
|
+
// Note: Actual date varies, this is simplified
|
|
646
|
+
// National Day
|
|
647
|
+
holidays.push({
|
|
648
|
+
name: 'National Day',
|
|
649
|
+
date: new Date(year, 9, 1),
|
|
650
|
+
countryCode: 'CN',
|
|
651
|
+
type: 'public'
|
|
652
|
+
});
|
|
653
|
+
return holidays;
|
|
654
|
+
}
|
|
655
|
+
// ============================================================================
|
|
656
|
+
// INDIA HOLIDAYS (Simplified - many are lunar calendar based)
|
|
657
|
+
// ============================================================================
|
|
658
|
+
export function getIndiaHolidays(year) {
|
|
659
|
+
const holidays = [];
|
|
660
|
+
// Republic Day
|
|
661
|
+
holidays.push({
|
|
662
|
+
name: 'Republic Day',
|
|
663
|
+
date: new Date(year, 0, 26),
|
|
664
|
+
countryCode: 'IN',
|
|
665
|
+
type: 'public'
|
|
666
|
+
});
|
|
667
|
+
// Independence Day
|
|
668
|
+
holidays.push({
|
|
669
|
+
name: 'Independence Day',
|
|
670
|
+
date: new Date(year, 7, 15),
|
|
671
|
+
countryCode: 'IN',
|
|
672
|
+
type: 'public'
|
|
673
|
+
});
|
|
674
|
+
// Gandhi Jayanti
|
|
675
|
+
holidays.push({
|
|
676
|
+
name: 'Gandhi Jayanti',
|
|
677
|
+
date: new Date(year, 9, 2),
|
|
678
|
+
countryCode: 'IN',
|
|
679
|
+
type: 'public'
|
|
680
|
+
});
|
|
681
|
+
// Note: Diwali, Holi, Eid, etc. are lunar calendar based
|
|
682
|
+
// Would need a lunar calendar library for accurate dates
|
|
683
|
+
return holidays;
|
|
684
|
+
}
|
|
685
|
+
// ============================================================================
|
|
686
|
+
// UNIFIED API
|
|
687
|
+
// ============================================================================
|
|
688
|
+
/**
|
|
689
|
+
* Get holidays for a specific country and year
|
|
690
|
+
* @param year - The year
|
|
691
|
+
* @param countryCode - ISO country code
|
|
692
|
+
* @returns Array of holidays
|
|
693
|
+
*/
|
|
694
|
+
export function getHolidays(year, countryCode) {
|
|
695
|
+
switch (countryCode) {
|
|
696
|
+
case 'UK':
|
|
697
|
+
return getUKHolidays(year);
|
|
698
|
+
case 'NL':
|
|
699
|
+
return getNetherlandsHolidays(year);
|
|
700
|
+
case 'DE':
|
|
701
|
+
return getGermanyHolidays(year);
|
|
702
|
+
case 'CA':
|
|
703
|
+
return getCanadaHolidays(year);
|
|
704
|
+
case 'AU':
|
|
705
|
+
return getAustraliaHolidays(year);
|
|
706
|
+
case 'IT':
|
|
707
|
+
return getItalyHolidays(year);
|
|
708
|
+
case 'ES':
|
|
709
|
+
return getSpainHolidays(year);
|
|
710
|
+
case 'CN':
|
|
711
|
+
return getChinaHolidays(year);
|
|
712
|
+
case 'IN':
|
|
713
|
+
return getIndiaHolidays(year);
|
|
714
|
+
case 'US':
|
|
715
|
+
// Import from existing calendar module
|
|
716
|
+
return [];
|
|
717
|
+
default:
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
/**
|
|
722
|
+
* Check if a date is a holiday in a specific country
|
|
723
|
+
* @param date - The date to check
|
|
724
|
+
* @param countryCode - ISO country code
|
|
725
|
+
* @returns True if date is a holiday
|
|
726
|
+
*/
|
|
727
|
+
export function isHoliday(date, countryCode) {
|
|
728
|
+
const holidays = getHolidays(date.getFullYear(), countryCode);
|
|
729
|
+
// Normalize to local date components for comparison
|
|
730
|
+
const targetYear = date.getFullYear();
|
|
731
|
+
const targetMonth = date.getMonth();
|
|
732
|
+
const targetDay = date.getDate();
|
|
733
|
+
return holidays.some(h => h.date.getFullYear() === targetYear &&
|
|
734
|
+
h.date.getMonth() === targetMonth &&
|
|
735
|
+
h.date.getDate() === targetDay);
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Get the holiday name for a specific date and country
|
|
739
|
+
* @param date - The date to check
|
|
740
|
+
* @param countryCode - ISO country code
|
|
741
|
+
* @returns Holiday name or null if not a holiday
|
|
742
|
+
*/
|
|
743
|
+
export function getHolidayName(date, countryCode) {
|
|
744
|
+
const holidays = getHolidays(date.getFullYear(), countryCode);
|
|
745
|
+
// Normalize to local date components for comparison
|
|
746
|
+
const targetYear = date.getFullYear();
|
|
747
|
+
const targetMonth = date.getMonth();
|
|
748
|
+
const targetDay = date.getDate();
|
|
749
|
+
const holiday = holidays.find(h => h.date.getFullYear() === targetYear &&
|
|
750
|
+
h.date.getMonth() === targetMonth &&
|
|
751
|
+
h.date.getDate() === targetDay);
|
|
752
|
+
return holiday ? holiday.name : null;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Get next holiday from a given date
|
|
756
|
+
* @param date - The reference date
|
|
757
|
+
* @param countryCode - ISO country code
|
|
758
|
+
* @returns Next holiday or null
|
|
759
|
+
*/
|
|
760
|
+
export function getNextHoliday(date, countryCode) {
|
|
761
|
+
const year = date.getFullYear();
|
|
762
|
+
let holidays = getHolidays(year, countryCode);
|
|
763
|
+
// Also get next year's holidays
|
|
764
|
+
holidays = [...holidays, ...getHolidays(year + 1, countryCode)];
|
|
765
|
+
const future = holidays
|
|
766
|
+
.filter(h => h.date > date)
|
|
767
|
+
.sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
768
|
+
return future[0] || null;
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Get upcoming holidays within N days
|
|
772
|
+
* @param date - The reference date
|
|
773
|
+
* @param days - Number of days to look ahead
|
|
774
|
+
* @param countryCode - ISO country code
|
|
775
|
+
* @returns Array of upcoming holidays
|
|
776
|
+
*/
|
|
777
|
+
export function getUpcomingHolidays(date, days, countryCode) {
|
|
778
|
+
const year = date.getFullYear();
|
|
779
|
+
let holidays = getHolidays(year, countryCode);
|
|
780
|
+
// Also get next year's holidays
|
|
781
|
+
holidays = [...holidays, ...getHolidays(year + 1, countryCode)];
|
|
782
|
+
const maxDate = new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
783
|
+
return holidays
|
|
784
|
+
.filter(h => h.date > date && h.date <= maxDate)
|
|
785
|
+
.sort((a, b) => a.date.getTime() - b.date.getTime());
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Get all supported country codes
|
|
789
|
+
* @returns Array of country codes
|
|
790
|
+
*/
|
|
791
|
+
export function getSupportedCountries() {
|
|
792
|
+
return ['UK', 'NL', 'DE', 'CA', 'AU', 'IT', 'ES', 'CN', 'IN', 'US'];
|
|
793
|
+
}
|