ts-time-utils 4.1.0 → 4.4.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 +81 -31
- package/dist/{age.js → age.cjs} +14 -6
- package/dist/{calculate.js → calculate.cjs} +30 -18
- package/dist/{calendar.js → calendar.cjs} +80 -39
- package/dist/{calendars.js → calendars.cjs} +48 -23
- package/dist/{chain.js → chain.cjs} +41 -40
- package/dist/{compare.js → compare.cjs} +58 -28
- package/dist/constants.cjs +19 -0
- package/dist/{countdown.js → countdown.cjs} +16 -7
- package/dist/{cron.js → cron.cjs} +20 -9
- package/dist/{dateRange.js → dateRange.cjs} +42 -26
- package/dist/{duration.js → duration.cjs} +56 -44
- package/dist/esm/chain.js +0 -5
- package/dist/esm/naturalLanguage.d.ts +1 -3
- package/dist/esm/naturalLanguage.d.ts.map +1 -1
- package/dist/esm/naturalLanguage.js +9 -2
- package/dist/esm/plugins.d.ts +0 -6
- package/dist/esm/plugins.d.ts.map +1 -1
- package/dist/esm/plugins.js +36 -42
- package/dist/esm/recurrence.d.ts.map +1 -1
- package/dist/esm/recurrence.js +3 -5
- package/dist/esm/timezone.d.ts +6 -1
- package/dist/esm/timezone.d.ts.map +1 -1
- package/dist/esm/timezone.js +106 -66
- package/dist/esm/types.d.ts +0 -4
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/{finance.js → finance.cjs} +39 -22
- package/dist/{fiscal.js → fiscal.cjs} +36 -17
- package/dist/{format.js → format.cjs} +83 -70
- package/dist/{healthcare.js → healthcare.cjs} +37 -22
- package/dist/{holidays.js → holidays.cjs} +52 -25
- package/dist/index.cjs +595 -0
- package/dist/{interval.js → interval.cjs} +24 -11
- package/dist/{iterate.js → iterate.cjs} +84 -41
- package/dist/{locale.js → locale.cjs} +54 -26
- package/dist/{naturalLanguage.js → naturalLanguage.cjs} +36 -23
- package/dist/naturalLanguage.d.ts +1 -3
- package/dist/naturalLanguage.d.ts.map +1 -1
- package/dist/{parse.js → parse.cjs} +24 -11
- package/dist/{performance.js → performance.cjs} +23 -10
- package/dist/{plugins.js → plugins.cjs} +48 -47
- package/dist/plugins.d.ts +0 -6
- package/dist/plugins.d.ts.map +1 -1
- package/dist/{precision.js → precision.cjs} +74 -37
- package/dist/{rangePresets.js → rangePresets.cjs} +40 -19
- package/dist/{recurrence.js → recurrence.cjs} +27 -21
- package/dist/recurrence.d.ts.map +1 -1
- package/dist/{scheduling.js → scheduling.cjs} +46 -31
- package/dist/{serialize.js → serialize.cjs} +36 -17
- package/dist/{temporal.js → temporal.cjs} +28 -13
- package/dist/{timezone.js → timezone.cjs} +140 -82
- package/dist/timezone.d.ts +6 -1
- package/dist/timezone.d.ts.map +1 -1
- package/dist/{types.js → types.cjs} +9 -3
- package/dist/types.d.ts +0 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/{validate.js → validate.cjs} +54 -26
- package/dist/{workingHours.js → workingHours.cjs} +36 -17
- package/package.json +40 -37
- package/dist/constants.js +0 -16
- package/dist/index.js +0 -72
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Interval utilities: operations on time intervals [start, end)
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createInterval = createInterval;
|
|
7
|
+
exports.isValidInterval = isValidInterval;
|
|
8
|
+
exports.intervalDuration = intervalDuration;
|
|
9
|
+
exports.intervalContains = intervalContains;
|
|
10
|
+
exports.intervalsOverlap = intervalsOverlap;
|
|
11
|
+
exports.intervalIntersection = intervalIntersection;
|
|
12
|
+
exports.mergeIntervals = mergeIntervals;
|
|
13
|
+
exports.subtractInterval = subtractInterval;
|
|
14
|
+
exports.splitIntervalByDay = splitIntervalByDay;
|
|
15
|
+
exports.totalIntervalCoverage = totalIntervalCoverage;
|
|
16
|
+
exports.normalizeIntervals = normalizeIntervals;
|
|
4
17
|
/** Create an interval ensuring start <= end */
|
|
5
|
-
|
|
18
|
+
function createInterval(start, end) {
|
|
6
19
|
const s = new Date(start);
|
|
7
20
|
const e = new Date(end);
|
|
8
21
|
if (isNaN(s.getTime()) || isNaN(e.getTime()) || s > e)
|
|
@@ -10,30 +23,30 @@ export function createInterval(start, end) {
|
|
|
10
23
|
return { start: s, end: e };
|
|
11
24
|
}
|
|
12
25
|
/** Validate an object is a proper interval */
|
|
13
|
-
|
|
26
|
+
function isValidInterval(i) {
|
|
14
27
|
return !!i && i.start instanceof Date && i.end instanceof Date && !isNaN(i.start) && !isNaN(i.end) && i.start <= i.end;
|
|
15
28
|
}
|
|
16
29
|
/** Duration of interval in ms */
|
|
17
|
-
|
|
30
|
+
function intervalDuration(i) {
|
|
18
31
|
return i.end.getTime() - i.start.getTime();
|
|
19
32
|
}
|
|
20
33
|
/** Whether interval contains date (inclusive start, exclusive end) */
|
|
21
|
-
|
|
34
|
+
function intervalContains(i, date) {
|
|
22
35
|
const d = date instanceof Date ? date : new Date(date);
|
|
23
36
|
return d >= i.start && d < i.end;
|
|
24
37
|
}
|
|
25
38
|
/** Whether two intervals overlap */
|
|
26
|
-
|
|
39
|
+
function intervalsOverlap(a, b) {
|
|
27
40
|
return a.start < b.end && b.start < a.end;
|
|
28
41
|
}
|
|
29
42
|
/** Intersection of two intervals, or null */
|
|
30
|
-
|
|
43
|
+
function intervalIntersection(a, b) {
|
|
31
44
|
const start = a.start > b.start ? a.start : b.start;
|
|
32
45
|
const end = a.end < b.end ? a.end : b.end;
|
|
33
46
|
return start < end ? { start, end } : null;
|
|
34
47
|
}
|
|
35
48
|
/** Merge overlapping or touching intervals into a minimal set */
|
|
36
|
-
|
|
49
|
+
function mergeIntervals(intervals) {
|
|
37
50
|
if (intervals.length === 0)
|
|
38
51
|
return [];
|
|
39
52
|
const sorted = [...intervals].sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
@@ -54,7 +67,7 @@ export function mergeIntervals(intervals) {
|
|
|
54
67
|
return result;
|
|
55
68
|
}
|
|
56
69
|
/** Subtract interval b from a (can split into 0,1,2 intervals) */
|
|
57
|
-
|
|
70
|
+
function subtractInterval(a, b) {
|
|
58
71
|
if (!intervalsOverlap(a, b))
|
|
59
72
|
return [a];
|
|
60
73
|
const parts = [];
|
|
@@ -65,7 +78,7 @@ export function subtractInterval(a, b) {
|
|
|
65
78
|
return parts;
|
|
66
79
|
}
|
|
67
80
|
/** Split an interval into day-boundary intervals (UTC based) */
|
|
68
|
-
|
|
81
|
+
function splitIntervalByDay(i) {
|
|
69
82
|
const res = [];
|
|
70
83
|
let cursor = new Date(i.start);
|
|
71
84
|
while (cursor < i.end) {
|
|
@@ -77,10 +90,10 @@ export function splitIntervalByDay(i) {
|
|
|
77
90
|
return res;
|
|
78
91
|
}
|
|
79
92
|
/** Total covered duration of possibly overlapping intervals */
|
|
80
|
-
|
|
93
|
+
function totalIntervalCoverage(intervals) {
|
|
81
94
|
return mergeIntervals(intervals).reduce((sum, i) => sum + intervalDuration(i), 0);
|
|
82
95
|
}
|
|
83
96
|
/** Normalize array: filter invalid and merge */
|
|
84
|
-
|
|
97
|
+
function normalizeIntervals(intervals) {
|
|
85
98
|
return mergeIntervals(intervals.filter(isValidInterval));
|
|
86
99
|
}
|
|
@@ -1,6 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* @fileoverview Date iteration utilities for generating date sequences
|
|
3
4
|
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.eachDay = eachDay;
|
|
7
|
+
exports.eachWeekday = eachWeekday;
|
|
8
|
+
exports.eachWeekend = eachWeekend;
|
|
9
|
+
exports.eachWeek = eachWeek;
|
|
10
|
+
exports.eachMonth = eachMonth;
|
|
11
|
+
exports.eachQuarter = eachQuarter;
|
|
12
|
+
exports.eachYear = eachYear;
|
|
13
|
+
exports.eachHour = eachHour;
|
|
14
|
+
exports.eachMinute = eachMinute;
|
|
15
|
+
exports.eachDayOfWeek = eachDayOfWeek;
|
|
16
|
+
exports.eachInterval = eachInterval;
|
|
17
|
+
exports.countDays = countDays;
|
|
18
|
+
exports.countWeekdays = countWeekdays;
|
|
19
|
+
exports.countWeekendDays = countWeekendDays;
|
|
20
|
+
exports.countWeeks = countWeeks;
|
|
21
|
+
exports.countMonths = countMonths;
|
|
22
|
+
exports.iterateDates = iterateDates;
|
|
23
|
+
exports.iterateDays = iterateDays;
|
|
24
|
+
exports.iterateWeekdays = iterateWeekdays;
|
|
25
|
+
exports.iterateMonths = iterateMonths;
|
|
26
|
+
exports.filterDays = filterDays;
|
|
27
|
+
exports.eachMonthEnd = eachMonthEnd;
|
|
28
|
+
exports.eachNthDayOfMonth = eachNthDayOfMonth;
|
|
29
|
+
exports.eachWeekendOfMonth = eachWeekendOfMonth;
|
|
30
|
+
exports.eachWeekendOfYear = eachWeekendOfYear;
|
|
31
|
+
exports.previousDay = previousDay;
|
|
32
|
+
exports.nextDay = nextDay;
|
|
33
|
+
exports.previousSunday = previousSunday;
|
|
34
|
+
exports.previousMonday = previousMonday;
|
|
35
|
+
exports.previousTuesday = previousTuesday;
|
|
36
|
+
exports.previousWednesday = previousWednesday;
|
|
37
|
+
exports.previousThursday = previousThursday;
|
|
38
|
+
exports.previousFriday = previousFriday;
|
|
39
|
+
exports.previousSaturday = previousSaturday;
|
|
40
|
+
exports.nextSunday = nextSunday;
|
|
41
|
+
exports.nextMonday = nextMonday;
|
|
42
|
+
exports.nextTuesday = nextTuesday;
|
|
43
|
+
exports.nextWednesday = nextWednesday;
|
|
44
|
+
exports.nextThursday = nextThursday;
|
|
45
|
+
exports.nextFriday = nextFriday;
|
|
46
|
+
exports.nextSaturday = nextSaturday;
|
|
4
47
|
/**
|
|
5
48
|
* Generate an array of dates for each day in a range
|
|
6
49
|
* @param start - Start date (inclusive)
|
|
@@ -10,7 +53,7 @@
|
|
|
10
53
|
* eachDay(new Date('2024-01-01'), new Date('2024-01-05'))
|
|
11
54
|
* // [Jan 1, Jan 2, Jan 3, Jan 4, Jan 5]
|
|
12
55
|
*/
|
|
13
|
-
|
|
56
|
+
function eachDay(start, end) {
|
|
14
57
|
const result = [];
|
|
15
58
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
16
59
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -29,7 +72,7 @@ export function eachDay(start, end) {
|
|
|
29
72
|
* eachWeekday(new Date('2024-01-01'), new Date('2024-01-07'))
|
|
30
73
|
* // [Jan 1 (Mon), Jan 2 (Tue), Jan 3 (Wed), Jan 4 (Thu), Jan 5 (Fri)]
|
|
31
74
|
*/
|
|
32
|
-
|
|
75
|
+
function eachWeekday(start, end) {
|
|
33
76
|
const result = [];
|
|
34
77
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
35
78
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -48,7 +91,7 @@ export function eachWeekday(start, end) {
|
|
|
48
91
|
* @param end - End date (inclusive)
|
|
49
92
|
* @returns Array of weekend dates
|
|
50
93
|
*/
|
|
51
|
-
|
|
94
|
+
function eachWeekend(start, end) {
|
|
52
95
|
const result = [];
|
|
53
96
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
54
97
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -71,7 +114,7 @@ export function eachWeekend(start, end) {
|
|
|
71
114
|
* eachWeek(new Date('2024-01-01'), new Date('2024-01-31'))
|
|
72
115
|
* // [Jan 7, Jan 14, Jan 21, Jan 28] (Sundays)
|
|
73
116
|
*/
|
|
74
|
-
|
|
117
|
+
function eachWeek(start, end, weekStartsOn = 0) {
|
|
75
118
|
const result = [];
|
|
76
119
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
77
120
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -95,7 +138,7 @@ export function eachWeek(start, end, weekStartsOn = 0) {
|
|
|
95
138
|
* eachMonth(new Date('2024-01-15'), new Date('2024-04-15'))
|
|
96
139
|
* // [Feb 1, Mar 1, Apr 1]
|
|
97
140
|
*/
|
|
98
|
-
|
|
141
|
+
function eachMonth(start, end) {
|
|
99
142
|
const result = [];
|
|
100
143
|
const current = new Date(start.getFullYear(), start.getMonth() + 1, 1);
|
|
101
144
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -111,7 +154,7 @@ export function eachMonth(start, end) {
|
|
|
111
154
|
* @param end - End date (inclusive)
|
|
112
155
|
* @returns Array of quarter start dates
|
|
113
156
|
*/
|
|
114
|
-
|
|
157
|
+
function eachQuarter(start, end) {
|
|
115
158
|
const result = [];
|
|
116
159
|
// Start from beginning of next quarter after start date
|
|
117
160
|
const startMonth = start.getMonth();
|
|
@@ -130,7 +173,7 @@ export function eachQuarter(start, end) {
|
|
|
130
173
|
* @param end - End date (inclusive)
|
|
131
174
|
* @returns Array of year start dates
|
|
132
175
|
*/
|
|
133
|
-
|
|
176
|
+
function eachYear(start, end) {
|
|
134
177
|
const result = [];
|
|
135
178
|
const startYear = start.getMonth() === 0 && start.getDate() === 1
|
|
136
179
|
? start.getFullYear()
|
|
@@ -151,7 +194,7 @@ export function eachYear(start, end) {
|
|
|
151
194
|
* eachHour(new Date('2024-01-01T09:00'), new Date('2024-01-01T12:00'))
|
|
152
195
|
* // [9:00, 10:00, 11:00, 12:00]
|
|
153
196
|
*/
|
|
154
|
-
|
|
197
|
+
function eachHour(start, end, step = 1) {
|
|
155
198
|
const result = [];
|
|
156
199
|
const current = new Date(start);
|
|
157
200
|
current.setMinutes(0, 0, 0);
|
|
@@ -171,7 +214,7 @@ export function eachHour(start, end, step = 1) {
|
|
|
171
214
|
* eachMinute(new Date('2024-01-01T09:00'), new Date('2024-01-01T09:05'))
|
|
172
215
|
* // [9:00, 9:01, 9:02, 9:03, 9:04, 9:05]
|
|
173
216
|
*/
|
|
174
|
-
|
|
217
|
+
function eachMinute(start, end, step = 1) {
|
|
175
218
|
const result = [];
|
|
176
219
|
const current = new Date(start);
|
|
177
220
|
current.setSeconds(0, 0);
|
|
@@ -191,7 +234,7 @@ export function eachMinute(start, end, step = 1) {
|
|
|
191
234
|
* eachDayOfWeek(new Date('2024-01-01'), new Date('2024-01-31'), 1)
|
|
192
235
|
* // All Mondays in January 2024
|
|
193
236
|
*/
|
|
194
|
-
|
|
237
|
+
function eachDayOfWeek(start, end, dayOfWeek) {
|
|
195
238
|
const result = [];
|
|
196
239
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
197
240
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -215,7 +258,7 @@ export function eachDayOfWeek(start, end, dayOfWeek) {
|
|
|
215
258
|
* eachInterval(start, end, { weeks: 2 }) // Every 2 weeks
|
|
216
259
|
* eachInterval(start, end, { hours: 6 }) // Every 6 hours
|
|
217
260
|
*/
|
|
218
|
-
|
|
261
|
+
function eachInterval(start, end, interval) {
|
|
219
262
|
const result = [];
|
|
220
263
|
const current = new Date(start);
|
|
221
264
|
while (current <= end) {
|
|
@@ -250,7 +293,7 @@ export function eachInterval(start, end, interval) {
|
|
|
250
293
|
* @param end - End date (inclusive)
|
|
251
294
|
* @returns Number of days
|
|
252
295
|
*/
|
|
253
|
-
|
|
296
|
+
function countDays(start, end) {
|
|
254
297
|
const startDay = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
255
298
|
const endDay = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
256
299
|
return Math.round((endDay.getTime() - startDay.getTime()) / 86400000) + 1;
|
|
@@ -261,7 +304,7 @@ export function countDays(start, end) {
|
|
|
261
304
|
* @param end - End date (inclusive)
|
|
262
305
|
* @returns Number of weekdays
|
|
263
306
|
*/
|
|
264
|
-
|
|
307
|
+
function countWeekdays(start, end) {
|
|
265
308
|
return eachWeekday(start, end).length;
|
|
266
309
|
}
|
|
267
310
|
/**
|
|
@@ -270,7 +313,7 @@ export function countWeekdays(start, end) {
|
|
|
270
313
|
* @param end - End date (inclusive)
|
|
271
314
|
* @returns Number of weekend days
|
|
272
315
|
*/
|
|
273
|
-
|
|
316
|
+
function countWeekendDays(start, end) {
|
|
274
317
|
return eachWeekend(start, end).length;
|
|
275
318
|
}
|
|
276
319
|
/**
|
|
@@ -279,7 +322,7 @@ export function countWeekendDays(start, end) {
|
|
|
279
322
|
* @param end - End date (inclusive)
|
|
280
323
|
* @returns Number of weeks
|
|
281
324
|
*/
|
|
282
|
-
|
|
325
|
+
function countWeeks(start, end) {
|
|
283
326
|
const days = countDays(start, end);
|
|
284
327
|
return Math.ceil(days / 7);
|
|
285
328
|
}
|
|
@@ -289,7 +332,7 @@ export function countWeeks(start, end) {
|
|
|
289
332
|
* @param end - End date (inclusive)
|
|
290
333
|
* @returns Number of months (partial months count as 1)
|
|
291
334
|
*/
|
|
292
|
-
|
|
335
|
+
function countMonths(start, end) {
|
|
293
336
|
const yearDiff = end.getFullYear() - start.getFullYear();
|
|
294
337
|
const monthDiff = end.getMonth() - start.getMonth();
|
|
295
338
|
return yearDiff * 12 + monthDiff + 1;
|
|
@@ -301,7 +344,7 @@ export function countMonths(start, end) {
|
|
|
301
344
|
* @param step - Step function to advance the date
|
|
302
345
|
* @yields Date objects
|
|
303
346
|
*/
|
|
304
|
-
|
|
347
|
+
function* iterateDates(start, end, step = (d) => d.setDate(d.getDate() + 1)) {
|
|
305
348
|
const current = new Date(start);
|
|
306
349
|
while (current <= end) {
|
|
307
350
|
yield new Date(current);
|
|
@@ -314,7 +357,7 @@ export function* iterateDates(start, end, step = (d) => d.setDate(d.getDate() +
|
|
|
314
357
|
* @param end - End date
|
|
315
358
|
* @yields Each day in the range
|
|
316
359
|
*/
|
|
317
|
-
|
|
360
|
+
function* iterateDays(start, end) {
|
|
318
361
|
yield* iterateDates(start, end, (d) => d.setDate(d.getDate() + 1));
|
|
319
362
|
}
|
|
320
363
|
/**
|
|
@@ -323,7 +366,7 @@ export function* iterateDays(start, end) {
|
|
|
323
366
|
* @param end - End date
|
|
324
367
|
* @yields Each weekday in the range
|
|
325
368
|
*/
|
|
326
|
-
|
|
369
|
+
function* iterateWeekdays(start, end) {
|
|
327
370
|
const current = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
328
371
|
while (current <= end) {
|
|
329
372
|
const day = current.getDay();
|
|
@@ -339,7 +382,7 @@ export function* iterateWeekdays(start, end) {
|
|
|
339
382
|
* @param end - End date
|
|
340
383
|
* @yields First day of each month in the range
|
|
341
384
|
*/
|
|
342
|
-
|
|
385
|
+
function* iterateMonths(start, end) {
|
|
343
386
|
const current = new Date(start.getFullYear(), start.getMonth(), 1);
|
|
344
387
|
while (current <= end) {
|
|
345
388
|
yield new Date(current);
|
|
@@ -356,7 +399,7 @@ export function* iterateMonths(start, end) {
|
|
|
356
399
|
* // Get all 15th days of each month
|
|
357
400
|
* filterDays(start, end, d => d.getDate() === 15)
|
|
358
401
|
*/
|
|
359
|
-
|
|
402
|
+
function filterDays(start, end, filter) {
|
|
360
403
|
const result = [];
|
|
361
404
|
for (const date of iterateDays(start, end)) {
|
|
362
405
|
if (filter(date)) {
|
|
@@ -371,7 +414,7 @@ export function filterDays(start, end, filter) {
|
|
|
371
414
|
* @param end - End date
|
|
372
415
|
* @returns Array of last-of-month dates
|
|
373
416
|
*/
|
|
374
|
-
|
|
417
|
+
function eachMonthEnd(start, end) {
|
|
375
418
|
const result = [];
|
|
376
419
|
const current = new Date(start.getFullYear(), start.getMonth() + 1, 0);
|
|
377
420
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -392,7 +435,7 @@ export function eachMonthEnd(start, end) {
|
|
|
392
435
|
* eachNthDayOfMonth(start, end, 15) // 15th of each month
|
|
393
436
|
* eachNthDayOfMonth(start, end, 31) // Last day of short months, 31st otherwise
|
|
394
437
|
*/
|
|
395
|
-
|
|
438
|
+
function eachNthDayOfMonth(start, end, dayOfMonth) {
|
|
396
439
|
const result = [];
|
|
397
440
|
let current = new Date(start.getFullYear(), start.getMonth(), 1);
|
|
398
441
|
const endDate = new Date(end.getFullYear(), end.getMonth(), end.getDate());
|
|
@@ -413,7 +456,7 @@ export function eachNthDayOfMonth(start, end, dayOfMonth) {
|
|
|
413
456
|
* @param month - month (0-11)
|
|
414
457
|
* @returns Array of weekend dates
|
|
415
458
|
*/
|
|
416
|
-
|
|
459
|
+
function eachWeekendOfMonth(year, month) {
|
|
417
460
|
const result = [];
|
|
418
461
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
419
462
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
@@ -430,7 +473,7 @@ export function eachWeekendOfMonth(year, month) {
|
|
|
430
473
|
* @param year - year
|
|
431
474
|
* @returns Array of weekend dates
|
|
432
475
|
*/
|
|
433
|
-
|
|
476
|
+
function eachWeekendOfYear(year) {
|
|
434
477
|
const result = [];
|
|
435
478
|
for (let month = 0; month < 12; month++) {
|
|
436
479
|
result.push(...eachWeekendOfMonth(year, month));
|
|
@@ -443,7 +486,7 @@ export function eachWeekendOfYear(year) {
|
|
|
443
486
|
* @param dayOfWeek - target day (0=Sunday, 6=Saturday)
|
|
444
487
|
* @returns The previous occurrence (not including date itself)
|
|
445
488
|
*/
|
|
446
|
-
|
|
489
|
+
function previousDay(date, dayOfWeek) {
|
|
447
490
|
const result = new Date(date);
|
|
448
491
|
result.setHours(0, 0, 0, 0);
|
|
449
492
|
const currentDay = result.getDay();
|
|
@@ -457,7 +500,7 @@ export function previousDay(date, dayOfWeek) {
|
|
|
457
500
|
* @param dayOfWeek - target day (0=Sunday, 6=Saturday)
|
|
458
501
|
* @returns The next occurrence (not including date itself)
|
|
459
502
|
*/
|
|
460
|
-
|
|
503
|
+
function nextDay(date, dayOfWeek) {
|
|
461
504
|
const result = new Date(date);
|
|
462
505
|
result.setHours(0, 0, 0, 0);
|
|
463
506
|
const currentDay = result.getDay();
|
|
@@ -466,30 +509,30 @@ export function nextDay(date, dayOfWeek) {
|
|
|
466
509
|
return result;
|
|
467
510
|
}
|
|
468
511
|
/** Get the previous Sunday */
|
|
469
|
-
|
|
512
|
+
function previousSunday(date) { return previousDay(date, 0); }
|
|
470
513
|
/** Get the previous Monday */
|
|
471
|
-
|
|
514
|
+
function previousMonday(date) { return previousDay(date, 1); }
|
|
472
515
|
/** Get the previous Tuesday */
|
|
473
|
-
|
|
516
|
+
function previousTuesday(date) { return previousDay(date, 2); }
|
|
474
517
|
/** Get the previous Wednesday */
|
|
475
|
-
|
|
518
|
+
function previousWednesday(date) { return previousDay(date, 3); }
|
|
476
519
|
/** Get the previous Thursday */
|
|
477
|
-
|
|
520
|
+
function previousThursday(date) { return previousDay(date, 4); }
|
|
478
521
|
/** Get the previous Friday */
|
|
479
|
-
|
|
522
|
+
function previousFriday(date) { return previousDay(date, 5); }
|
|
480
523
|
/** Get the previous Saturday */
|
|
481
|
-
|
|
524
|
+
function previousSaturday(date) { return previousDay(date, 6); }
|
|
482
525
|
/** Get the next Sunday */
|
|
483
|
-
|
|
526
|
+
function nextSunday(date) { return nextDay(date, 0); }
|
|
484
527
|
/** Get the next Monday */
|
|
485
|
-
|
|
528
|
+
function nextMonday(date) { return nextDay(date, 1); }
|
|
486
529
|
/** Get the next Tuesday */
|
|
487
|
-
|
|
530
|
+
function nextTuesday(date) { return nextDay(date, 2); }
|
|
488
531
|
/** Get the next Wednesday */
|
|
489
|
-
|
|
532
|
+
function nextWednesday(date) { return nextDay(date, 3); }
|
|
490
533
|
/** Get the next Thursday */
|
|
491
|
-
|
|
534
|
+
function nextThursday(date) { return nextDay(date, 4); }
|
|
492
535
|
/** Get the next Friday */
|
|
493
|
-
|
|
536
|
+
function nextFriday(date) { return nextDay(date, 5); }
|
|
494
537
|
/** Get the next Saturday */
|
|
495
|
-
|
|
538
|
+
function nextSaturday(date) { return nextDay(date, 6); }
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerLocale = registerLocale;
|
|
4
|
+
exports.getLocaleConfig = getLocaleConfig;
|
|
5
|
+
exports.getSupportedLocales = getSupportedLocales;
|
|
6
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
7
|
+
exports.formatDateLocale = formatDateLocale;
|
|
8
|
+
exports.formatTimeLocale = formatTimeLocale;
|
|
9
|
+
exports.formatDateTimeLocale = formatDateTimeLocale;
|
|
10
|
+
exports.getMonthNames = getMonthNames;
|
|
11
|
+
exports.getDayNames = getDayNames;
|
|
12
|
+
exports.getFirstDayOfWeek = getFirstDayOfWeek;
|
|
13
|
+
exports.isLocaleSupported = isLocaleSupported;
|
|
14
|
+
exports.getBestMatchingLocale = getBestMatchingLocale;
|
|
15
|
+
exports.detectLocale = detectLocale;
|
|
16
|
+
exports.convertRelativeTime = convertRelativeTime;
|
|
17
|
+
exports.detectLocaleFromRelativeTime = detectLocaleFromRelativeTime;
|
|
18
|
+
exports.convertFormatPattern = convertFormatPattern;
|
|
19
|
+
exports.convertFormattedDate = convertFormattedDate;
|
|
20
|
+
exports.convertRelativeTimeArray = convertRelativeTimeArray;
|
|
21
|
+
exports.compareLocaleFormats = compareLocaleFormats;
|
|
22
|
+
exports.getWeekInfo = getWeekInfo;
|
|
23
|
+
exports.getLocaleWeekStartsOn = getLocaleWeekStartsOn;
|
|
24
|
+
exports.getLocaleWeekendDays = getLocaleWeekendDays;
|
|
25
|
+
exports.intlFormat = intlFormat;
|
|
26
|
+
exports.formatISODate = formatISODate;
|
|
27
|
+
exports.formatISOTime = formatISOTime;
|
|
28
|
+
exports.formatDistanceStrict = formatDistanceStrict;
|
|
1
29
|
/**
|
|
2
30
|
* Internationalization and localization utilities for time formatting
|
|
3
31
|
*/
|
|
@@ -423,7 +451,7 @@ const localeRegistry = new Map(Object.entries(DEFAULT_LOCALES));
|
|
|
423
451
|
/**
|
|
424
452
|
* Register a custom locale configuration
|
|
425
453
|
*/
|
|
426
|
-
|
|
454
|
+
function registerLocale(config) {
|
|
427
455
|
localeRegistry.set(config.locale, config);
|
|
428
456
|
// Also register base language if this is a region-specific locale
|
|
429
457
|
const baseLang = config.locale.split('-')[0];
|
|
@@ -434,7 +462,7 @@ export function registerLocale(config) {
|
|
|
434
462
|
/**
|
|
435
463
|
* Get locale configuration, with fallback to base language or English
|
|
436
464
|
*/
|
|
437
|
-
|
|
465
|
+
function getLocaleConfig(locale) {
|
|
438
466
|
// Try exact match first
|
|
439
467
|
if (localeRegistry.has(locale)) {
|
|
440
468
|
return localeRegistry.get(locale);
|
|
@@ -450,13 +478,13 @@ export function getLocaleConfig(locale) {
|
|
|
450
478
|
/**
|
|
451
479
|
* Get list of all registered locales
|
|
452
480
|
*/
|
|
453
|
-
|
|
481
|
+
function getSupportedLocales() {
|
|
454
482
|
return Array.from(localeRegistry.keys());
|
|
455
483
|
}
|
|
456
484
|
/**
|
|
457
485
|
* Format relative time in the specified locale
|
|
458
486
|
*/
|
|
459
|
-
|
|
487
|
+
function formatRelativeTime(date, options = {}) {
|
|
460
488
|
const { locale = 'en', maxUnit = 'years', minUnit = 'seconds', precision = 0, short = false, numeric = 'always', style = 'long' } = options;
|
|
461
489
|
const targetDate = normalizeDate(date);
|
|
462
490
|
if (!targetDate) {
|
|
@@ -530,7 +558,7 @@ export function formatRelativeTime(date, options = {}) {
|
|
|
530
558
|
/**
|
|
531
559
|
* Format date in locale-specific format
|
|
532
560
|
*/
|
|
533
|
-
|
|
561
|
+
function formatDateLocale(date, locale = 'en', style = 'medium') {
|
|
534
562
|
const targetDate = normalizeDate(date);
|
|
535
563
|
if (!targetDate) {
|
|
536
564
|
throw new Error('Invalid date provided for locale formatting');
|
|
@@ -542,7 +570,7 @@ export function formatDateLocale(date, locale = 'en', style = 'medium') {
|
|
|
542
570
|
/**
|
|
543
571
|
* Format time in locale-specific format
|
|
544
572
|
*/
|
|
545
|
-
|
|
573
|
+
function formatTimeLocale(date, locale = 'en', style = 'medium') {
|
|
546
574
|
const targetDate = normalizeDate(date);
|
|
547
575
|
if (!targetDate) {
|
|
548
576
|
throw new Error('Invalid date provided for time locale formatting');
|
|
@@ -554,7 +582,7 @@ export function formatTimeLocale(date, locale = 'en', style = 'medium') {
|
|
|
554
582
|
/**
|
|
555
583
|
* Format both date and time in locale-specific format
|
|
556
584
|
*/
|
|
557
|
-
|
|
585
|
+
function formatDateTimeLocale(date, locale = 'en', dateStyle = 'medium', timeStyle = 'medium') {
|
|
558
586
|
const dateStr = formatDateLocale(date, locale, dateStyle);
|
|
559
587
|
const timeStr = formatTimeLocale(date, locale, timeStyle);
|
|
560
588
|
// Simple concatenation - could be made more sophisticated per locale
|
|
@@ -563,7 +591,7 @@ export function formatDateTimeLocale(date, locale = 'en', dateStyle = 'medium',
|
|
|
563
591
|
/**
|
|
564
592
|
* Get localized month names
|
|
565
593
|
*/
|
|
566
|
-
|
|
594
|
+
function getMonthNames(locale = 'en', short = false) {
|
|
567
595
|
const config = getLocaleConfig(locale);
|
|
568
596
|
return short ?
|
|
569
597
|
(config.calendar?.monthNamesShort || config.calendar?.monthNames || []) :
|
|
@@ -572,7 +600,7 @@ export function getMonthNames(locale = 'en', short = false) {
|
|
|
572
600
|
/**
|
|
573
601
|
* Get localized day names
|
|
574
602
|
*/
|
|
575
|
-
|
|
603
|
+
function getDayNames(locale = 'en', short = false) {
|
|
576
604
|
const config = getLocaleConfig(locale);
|
|
577
605
|
return short ?
|
|
578
606
|
(config.calendar?.dayNamesShort || config.calendar?.dayNames || []) :
|
|
@@ -581,20 +609,20 @@ export function getDayNames(locale = 'en', short = false) {
|
|
|
581
609
|
/**
|
|
582
610
|
* Get the first day of week for a locale (0 = Sunday, 1 = Monday, etc.)
|
|
583
611
|
*/
|
|
584
|
-
|
|
612
|
+
function getFirstDayOfWeek(locale = 'en') {
|
|
585
613
|
const config = getLocaleConfig(locale);
|
|
586
614
|
return config.calendar?.weekStartsOn ?? 0;
|
|
587
615
|
}
|
|
588
616
|
/**
|
|
589
617
|
* Check if a locale is supported
|
|
590
618
|
*/
|
|
591
|
-
|
|
619
|
+
function isLocaleSupported(locale) {
|
|
592
620
|
return localeRegistry.has(locale) || localeRegistry.has(locale.split('-')[0]);
|
|
593
621
|
}
|
|
594
622
|
/**
|
|
595
623
|
* Get the best matching locale from a list of preferences
|
|
596
624
|
*/
|
|
597
|
-
|
|
625
|
+
function getBestMatchingLocale(preferences, fallback = 'en') {
|
|
598
626
|
for (const pref of preferences) {
|
|
599
627
|
// Try exact match first
|
|
600
628
|
if (isLocaleSupported(pref)) {
|
|
@@ -615,7 +643,7 @@ export function getBestMatchingLocale(preferences, fallback = 'en') {
|
|
|
615
643
|
/**
|
|
616
644
|
* Auto-detect locale from browser or system (if available)
|
|
617
645
|
*/
|
|
618
|
-
|
|
646
|
+
function detectLocale(fallback = 'en') {
|
|
619
647
|
// In browser environment
|
|
620
648
|
if (typeof navigator !== 'undefined' && navigator.languages) {
|
|
621
649
|
return getBestMatchingLocale(Array.from(navigator.languages), fallback);
|
|
@@ -770,7 +798,7 @@ function formatWithPattern(date, pattern, config) {
|
|
|
770
798
|
* Convert a relative time string from one locale to another
|
|
771
799
|
* Attempts to parse the relative time and reformat in target locale
|
|
772
800
|
*/
|
|
773
|
-
|
|
801
|
+
function convertRelativeTime(relativeTimeString, fromLocale, toLocale) {
|
|
774
802
|
if (fromLocale === toLocale) {
|
|
775
803
|
return relativeTimeString;
|
|
776
804
|
}
|
|
@@ -790,7 +818,7 @@ export function convertRelativeTime(relativeTimeString, fromLocale, toLocale) {
|
|
|
790
818
|
* Detect the locale of a formatted relative time string
|
|
791
819
|
* Returns the most likely locale or null if detection fails
|
|
792
820
|
*/
|
|
793
|
-
|
|
821
|
+
function detectLocaleFromRelativeTime(relativeTimeString) {
|
|
794
822
|
const supportedLocales = getSupportedLocales();
|
|
795
823
|
for (const locale of supportedLocales) {
|
|
796
824
|
if (parseRelativeTime(relativeTimeString, locale)) {
|
|
@@ -802,7 +830,7 @@ export function detectLocaleFromRelativeTime(relativeTimeString) {
|
|
|
802
830
|
/**
|
|
803
831
|
* Convert a date format pattern from one locale's convention to another
|
|
804
832
|
*/
|
|
805
|
-
|
|
833
|
+
function convertFormatPattern(pattern, fromLocale, toLocale, style) {
|
|
806
834
|
if (fromLocale === toLocale) {
|
|
807
835
|
return pattern;
|
|
808
836
|
}
|
|
@@ -853,7 +881,7 @@ export function convertFormatPattern(pattern, fromLocale, toLocale, style) {
|
|
|
853
881
|
* Convert a formatted date string from one locale to another
|
|
854
882
|
* Attempts to parse the date and reformat in target locale
|
|
855
883
|
*/
|
|
856
|
-
|
|
884
|
+
function convertFormattedDate(formattedDate, fromLocale, toLocale, targetStyle) {
|
|
857
885
|
if (fromLocale === toLocale) {
|
|
858
886
|
return formattedDate;
|
|
859
887
|
}
|
|
@@ -866,13 +894,13 @@ export function convertFormattedDate(formattedDate, fromLocale, toLocale, target
|
|
|
866
894
|
/**
|
|
867
895
|
* Bulk convert an array of relative time strings to a different locale
|
|
868
896
|
*/
|
|
869
|
-
|
|
897
|
+
function convertRelativeTimeArray(relativeTimeStrings, fromLocale, toLocale) {
|
|
870
898
|
return relativeTimeStrings.map(str => convertRelativeTime(str, fromLocale, toLocale));
|
|
871
899
|
}
|
|
872
900
|
/**
|
|
873
901
|
* Get format pattern differences between two locales
|
|
874
902
|
*/
|
|
875
|
-
|
|
903
|
+
function compareLocaleFormats(locale1, locale2) {
|
|
876
904
|
const config1 = getLocaleConfig(locale1);
|
|
877
905
|
const config2 = getLocaleConfig(locale2);
|
|
878
906
|
const result = {
|
|
@@ -1093,7 +1121,7 @@ function tryParseWithPattern(dateString, pattern, config) {
|
|
|
1093
1121
|
* @param locale - locale code
|
|
1094
1122
|
* @returns Object with firstDay, weekend days, and minimalDays
|
|
1095
1123
|
*/
|
|
1096
|
-
|
|
1124
|
+
function getWeekInfo(locale) {
|
|
1097
1125
|
const config = getLocaleConfig(locale);
|
|
1098
1126
|
const firstDay = config.calendar?.weekStartsOn ?? 0;
|
|
1099
1127
|
// Most locales use Saturday-Sunday weekend
|
|
@@ -1110,7 +1138,7 @@ export function getWeekInfo(locale) {
|
|
|
1110
1138
|
* @param locale - locale code
|
|
1111
1139
|
* @returns 0-6 (0 = Sunday, 1 = Monday, etc.)
|
|
1112
1140
|
*/
|
|
1113
|
-
|
|
1141
|
+
function getLocaleWeekStartsOn(locale) {
|
|
1114
1142
|
const config = getLocaleConfig(locale);
|
|
1115
1143
|
return config.calendar?.weekStartsOn ?? 0;
|
|
1116
1144
|
}
|
|
@@ -1119,7 +1147,7 @@ export function getLocaleWeekStartsOn(locale) {
|
|
|
1119
1147
|
* @param locale - locale code
|
|
1120
1148
|
* @returns Array of day numbers (0 = Sunday, 6 = Saturday)
|
|
1121
1149
|
*/
|
|
1122
|
-
|
|
1150
|
+
function getLocaleWeekendDays(locale) {
|
|
1123
1151
|
const middleEasternLocales = ['ar', 'fa', 'he', 'ur'];
|
|
1124
1152
|
const baseLang = locale.split('-')[0];
|
|
1125
1153
|
return middleEasternLocales.includes(baseLang) ? [5, 6] : [6, 0];
|
|
@@ -1130,14 +1158,14 @@ export function getLocaleWeekendDays(locale) {
|
|
|
1130
1158
|
* @param options - Intl.DateTimeFormatOptions
|
|
1131
1159
|
* @param locale - locale string (defaults to system locale)
|
|
1132
1160
|
*/
|
|
1133
|
-
|
|
1161
|
+
function intlFormat(date, options, locale) {
|
|
1134
1162
|
return new Intl.DateTimeFormat(locale, options).format(date);
|
|
1135
1163
|
}
|
|
1136
1164
|
/**
|
|
1137
1165
|
* Format only the date part in ISO format (YYYY-MM-DD)
|
|
1138
1166
|
* @param date - date to format
|
|
1139
1167
|
*/
|
|
1140
|
-
|
|
1168
|
+
function formatISODate(date) {
|
|
1141
1169
|
const year = date.getFullYear();
|
|
1142
1170
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
1143
1171
|
const day = String(date.getDate()).padStart(2, '0');
|
|
@@ -1148,7 +1176,7 @@ export function formatISODate(date) {
|
|
|
1148
1176
|
* @param date - date to format
|
|
1149
1177
|
* @param includeMs - include milliseconds
|
|
1150
1178
|
*/
|
|
1151
|
-
|
|
1179
|
+
function formatISOTime(date, includeMs = false) {
|
|
1152
1180
|
const hours = String(date.getHours()).padStart(2, '0');
|
|
1153
1181
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
1154
1182
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
@@ -1165,7 +1193,7 @@ export function formatISOTime(date, includeMs = false) {
|
|
|
1165
1193
|
* @param baseDate - the base date to compare against (defaults to now)
|
|
1166
1194
|
* @param options - formatting options
|
|
1167
1195
|
*/
|
|
1168
|
-
|
|
1196
|
+
function formatDistanceStrict(date, baseDate = new Date(), options = {}) {
|
|
1169
1197
|
const { locale = 'en', unit, roundingMethod = 'round', addSuffix = false } = options;
|
|
1170
1198
|
const config = getLocaleConfig(locale);
|
|
1171
1199
|
const diffMs = date.getTime() - baseDate.getTime();
|