@timestamp-js/core 0.1.0-rc.2 → 0.1.0-rc.3
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 +1 -1
- package/dist/calendar.d.ts +50 -0
- package/dist/calendar.d.ts.map +1 -1
- package/dist/calendar.js +45 -0
- package/dist/calendar.js.map +1 -1
- package/dist/index.d.ts +451 -68
- package/dist/index.d.ts.map +1 -1
- package/dist/index.global.js +404 -117
- package/dist/index.global.min.js +1 -1
- package/dist/index.js +634 -167
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
|
-
import { formatCalendarDate, gregorianCalendar } from './calendar.js';
|
|
2
|
-
export {
|
|
1
|
+
import { formatCalendarDate as formatCalendarDateImpl, getCalendarDirection as getCalendarDirectionImpl, getCalendarLocale as getCalendarLocaleImpl, getCalendarWeekdays as getCalendarWeekdaysImpl, gregorianCalendar, isCalendarRTL as isCalendarRTLImpl, } from './calendar.js';
|
|
2
|
+
export { gregorianCalendar } from './calendar.js';
|
|
3
|
+
/**
|
|
4
|
+
* Formats calendar fields using Timestamp's fixed `YYYY-MM-DD` date format.
|
|
5
|
+
*
|
|
6
|
+
* @param date Plain calendar date fields.
|
|
7
|
+
* @returns Date string in `YYYY-MM-DD` form.
|
|
8
|
+
* @category calendar
|
|
9
|
+
*/
|
|
10
|
+
export function formatCalendarDate(date) {
|
|
11
|
+
return formatCalendarDateImpl(date);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns the recommended locale for a calendar system.
|
|
15
|
+
*
|
|
16
|
+
* Calendar adapters can use this to publish their normal display locale. Callers can still pass
|
|
17
|
+
* an explicit locale when an application needs a different language or numbering presentation.
|
|
18
|
+
*
|
|
19
|
+
* @param {CalendarSystem=} calendar Calendar system to read. Defaults to Gregorian.
|
|
20
|
+
* @returns {string} BCP 47 locale, defaulting to `en-US`.
|
|
21
|
+
* @category calendar
|
|
22
|
+
*/
|
|
23
|
+
export function getCalendarLocale(calendar = gregorianCalendar) {
|
|
24
|
+
return getCalendarLocaleImpl(calendar);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns the recommended text direction for a calendar system.
|
|
28
|
+
*
|
|
29
|
+
* Calendar adapters can use this to publish their normal left-to-right or right-to-left
|
|
30
|
+
* presentation. Callers can still pass an explicit direction when an application needs one.
|
|
31
|
+
*
|
|
32
|
+
* @param {CalendarSystem=} calendar Calendar system to read. Defaults to Gregorian.
|
|
33
|
+
* @returns {CalendarDirection} `ltr` or `rtl`, defaulting to `ltr`.
|
|
34
|
+
* @category calendar
|
|
35
|
+
*/
|
|
36
|
+
export function getCalendarDirection(calendar = gregorianCalendar) {
|
|
37
|
+
return getCalendarDirectionImpl(calendar);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns true when a calendar system recommends right-to-left presentation.
|
|
41
|
+
*
|
|
42
|
+
* @param {CalendarSystem=} calendar Calendar system to read. Defaults to Gregorian.
|
|
43
|
+
* @returns {boolean} True when the recommended direction is `rtl`.
|
|
44
|
+
* @category calendar
|
|
45
|
+
*/
|
|
46
|
+
export function isCalendarRTL(calendar = gregorianCalendar) {
|
|
47
|
+
return isCalendarRTLImpl(calendar);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the recommended visible weekday order for a calendar system.
|
|
51
|
+
*
|
|
52
|
+
* Calendar adapters can use this to publish their normal visible week. Callers can still pass an
|
|
53
|
+
* explicit weekday list for application-specific layouts such as a five-day work week.
|
|
54
|
+
*
|
|
55
|
+
* @param {CalendarSystem=} calendar Calendar system to read. Defaults to Gregorian.
|
|
56
|
+
* @returns {number[]} Weekday numbers where Sunday is `0` and Saturday is `6`.
|
|
57
|
+
* @category calendar
|
|
58
|
+
*/
|
|
59
|
+
export function getCalendarWeekdays(calendar = gregorianCalendar) {
|
|
60
|
+
return getCalendarWeekdaysImpl(calendar);
|
|
61
|
+
}
|
|
3
62
|
/**
|
|
4
63
|
* Matches supported date and date-time input.
|
|
5
64
|
*
|
|
@@ -259,26 +318,27 @@ export function parsed(input) {
|
|
|
259
318
|
timestamp.time = getTime(timestamp);
|
|
260
319
|
return freezeTimestamp(timestamp);
|
|
261
320
|
}
|
|
262
|
-
function parseDateByMode(date, utc) {
|
|
321
|
+
function parseDateByMode(date, utc, calendar = gregorianCalendar) {
|
|
263
322
|
if (!(date instanceof Date))
|
|
264
323
|
return null;
|
|
265
324
|
if (Number.isNaN(date.getTime()))
|
|
266
325
|
return null;
|
|
267
326
|
const UTC = utc ? 'UTC' : '';
|
|
327
|
+
const gregorian = {
|
|
328
|
+
year: date[`get${UTC}FullYear`](),
|
|
329
|
+
month: date[`get${UTC}Month`]() + 1,
|
|
330
|
+
day: date[`get${UTC}Date`](),
|
|
331
|
+
};
|
|
268
332
|
const second = date[`get${UTC}Seconds`]();
|
|
269
333
|
const millisecond = date[`get${UTC}Milliseconds`]();
|
|
270
334
|
const timestamp = {
|
|
271
|
-
date:
|
|
272
|
-
'-' +
|
|
273
|
-
padNumber(date[`get${UTC}Month`]() + 1, 2) +
|
|
274
|
-
'-' +
|
|
275
|
-
padNumber(date[`get${UTC}Date`](), 2),
|
|
335
|
+
date: formatCalendarDate(gregorian),
|
|
276
336
|
time: padNumber(date[`get${UTC}Hours`]() || 0, 2) +
|
|
277
337
|
':' +
|
|
278
338
|
padNumber(date[`get${UTC}Minutes`]() || 0, 2),
|
|
279
|
-
year:
|
|
280
|
-
month:
|
|
281
|
-
day:
|
|
339
|
+
year: gregorian.year,
|
|
340
|
+
month: gregorian.month,
|
|
341
|
+
day: gregorian.day,
|
|
282
342
|
hour: date[`get${UTC}Hours`](),
|
|
283
343
|
minute: date[`get${UTC}Minutes`](),
|
|
284
344
|
weekday: 0,
|
|
@@ -297,7 +357,13 @@ function parseDateByMode(date, utc) {
|
|
|
297
357
|
if (millisecond !== 0) {
|
|
298
358
|
timestamp.millisecond = millisecond;
|
|
299
359
|
}
|
|
300
|
-
|
|
360
|
+
const formatted = updateFormatted(timestamp);
|
|
361
|
+
if (calendar === gregorianCalendar) {
|
|
362
|
+
return formatted;
|
|
363
|
+
}
|
|
364
|
+
return createCalendarTimestampFromEpochDay(gregorianCalendar.toEpochDay(gregorian), calendar, {
|
|
365
|
+
...getCalendarTimestampOptions(formatted),
|
|
366
|
+
});
|
|
301
367
|
}
|
|
302
368
|
/**
|
|
303
369
|
* Converts a JavaScript Date into a formatted Timestamp using host-local fields.
|
|
@@ -306,11 +372,12 @@ function parseDateByMode(date, utc) {
|
|
|
306
372
|
* with UTC getters instead of host-local getters.
|
|
307
373
|
*
|
|
308
374
|
* @param {Date} date JavaScript Date to convert.
|
|
375
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
309
376
|
* @returns {Timestamp} Formatted Timestamp object, or `null` for invalid input.
|
|
310
377
|
* @category parsing
|
|
311
378
|
*/
|
|
312
|
-
export function parseDate(date) {
|
|
313
|
-
return parseDateByMode(date, false);
|
|
379
|
+
export function parseDate(date, calendar = gregorianCalendar) {
|
|
380
|
+
return parseDateByMode(date, false, calendar);
|
|
314
381
|
}
|
|
315
382
|
/**
|
|
316
383
|
* Converts a JavaScript Date into a formatted Timestamp using UTC fields.
|
|
@@ -319,11 +386,12 @@ export function parseDate(date) {
|
|
|
319
386
|
* and time fields for a native Date instant.
|
|
320
387
|
*
|
|
321
388
|
* @param {Date} date JavaScript Date to convert.
|
|
389
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
322
390
|
* @returns {Timestamp} Formatted Timestamp object, or `null` for invalid input.
|
|
323
391
|
* @category parsing
|
|
324
392
|
*/
|
|
325
|
-
export function parseDateUTC(date) {
|
|
326
|
-
return parseDateByMode(date, true);
|
|
393
|
+
export function parseDateUTC(date, calendar = gregorianCalendar) {
|
|
394
|
+
return parseDateByMode(date, true, calendar);
|
|
327
395
|
}
|
|
328
396
|
/**
|
|
329
397
|
* Pads a number to a requested string length.
|
|
@@ -344,85 +412,86 @@ export function padNumber(x, length) {
|
|
|
344
412
|
/**
|
|
345
413
|
* Returns if the passed year is a leap year
|
|
346
414
|
* @param {number} year The year to check (ie: 1999, 2020)
|
|
415
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
347
416
|
* @returns {boolean} True if the year is a leap year
|
|
348
417
|
* @category calendar
|
|
349
418
|
*/
|
|
350
|
-
export function isLeapYear(year) {
|
|
351
|
-
return
|
|
419
|
+
export function isLeapYear(year, calendar = gregorianCalendar) {
|
|
420
|
+
return calendar.isLeapYear(year);
|
|
352
421
|
}
|
|
353
422
|
/**
|
|
354
423
|
* Returns the days of the specified month in a year
|
|
355
424
|
* @param {number} year The year (ie: 1999, 2020)
|
|
356
|
-
* @param {number} month The
|
|
425
|
+
* @param {number} month The month number in the selected calendar, where January is `1` for Gregorian.
|
|
426
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
357
427
|
* @returns {number} The number of days in the month (corrected for leap years)
|
|
358
428
|
* @category calendar
|
|
359
429
|
*/
|
|
360
|
-
export function daysInMonth(year, month) {
|
|
361
|
-
return
|
|
430
|
+
export function daysInMonth(year, month, calendar = gregorianCalendar) {
|
|
431
|
+
return calendar.daysInMonth(year, month);
|
|
362
432
|
}
|
|
363
433
|
/**
|
|
364
434
|
* Returns a new Timestamp for the next calendar day.
|
|
365
435
|
*
|
|
366
436
|
* @param {Timestamp} timestamp Base Timestamp object.
|
|
437
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
367
438
|
* @returns {Timestamp} New Timestamp representing the next day.
|
|
368
439
|
* @category arithmetic
|
|
369
440
|
*/
|
|
370
|
-
export function nextDay(timestamp) {
|
|
371
|
-
|
|
372
|
-
return updateFormatted(normalizeTimestamp({
|
|
373
|
-
...timestamp,
|
|
374
|
-
year: date.year,
|
|
375
|
-
month: date.month,
|
|
376
|
-
day: date.day,
|
|
377
|
-
}));
|
|
441
|
+
export function nextDay(timestamp, calendar = gregorianCalendar) {
|
|
442
|
+
return nextCalendarDay(timestamp, calendar);
|
|
378
443
|
}
|
|
379
444
|
/**
|
|
380
445
|
* Returns a new Timestamp for the previous calendar day.
|
|
381
446
|
*
|
|
382
447
|
* @param {Timestamp} timestamp Base Timestamp object.
|
|
448
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
383
449
|
* @returns {Timestamp} New Timestamp representing the previous day.
|
|
384
450
|
* @category arithmetic
|
|
385
451
|
*/
|
|
386
|
-
export function prevDay(timestamp) {
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
452
|
+
export function prevDay(timestamp, calendar = gregorianCalendar) {
|
|
453
|
+
return prevCalendarDay(timestamp, calendar);
|
|
454
|
+
}
|
|
455
|
+
function formatCalendarDateFromDate(date, utc, calendar = gregorianCalendar) {
|
|
456
|
+
const UTC = utc ? 'UTC' : '';
|
|
457
|
+
const gregorian = {
|
|
458
|
+
year: date[`get${UTC}FullYear`](),
|
|
459
|
+
month: date[`get${UTC}Month`]() + 1,
|
|
460
|
+
day: date[`get${UTC}Date`](),
|
|
461
|
+
};
|
|
462
|
+
const epochDay = gregorianCalendar.toEpochDay(gregorian);
|
|
463
|
+
return formatCalendarDate(calendar.fromEpochDay(epochDay));
|
|
394
464
|
}
|
|
395
465
|
/**
|
|
396
466
|
* Returns today's date using the host runtime timezone.
|
|
397
467
|
*
|
|
398
468
|
* For SSR or static rendering, server and client runtimes can produce different
|
|
399
469
|
* values when they run in different timezones. Use todayUTC() when the app
|
|
400
|
-
* wants a stable UTC calendar date instead.
|
|
470
|
+
* wants a stable UTC calendar date instead. Pass a calendar system to return
|
|
471
|
+
* today's date in that calendar's native `YYYY-MM-DD` fields.
|
|
401
472
|
*
|
|
473
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
402
474
|
* @returns {string} Date string in the form `YYYY-MM-DD`
|
|
403
475
|
* @category state
|
|
404
476
|
*/
|
|
405
|
-
export function today() {
|
|
406
|
-
|
|
407
|
-
return [year, padNumber(month, 2), padNumber(day, 2)].join('-');
|
|
477
|
+
export function today(calendar = gregorianCalendar) {
|
|
478
|
+
return formatCalendarDateFromDate(new Date(), false, calendar);
|
|
408
479
|
}
|
|
409
480
|
/**
|
|
410
481
|
* Returns today's date using UTC calendar fields.
|
|
411
482
|
*
|
|
412
483
|
* Pass a Date fixture to make SSR, tests, and hydration-sensitive render paths
|
|
413
484
|
* deterministic. This helper reads UTC fields only; it does not convert an
|
|
414
|
-
* existing Timestamp or timezone-suffixed string.
|
|
485
|
+
* existing Timestamp or timezone-suffixed string. Pass a calendar system to
|
|
486
|
+
* return today's UTC date in that calendar's native `YYYY-MM-DD` fields.
|
|
415
487
|
*
|
|
416
488
|
* @param {Date} date Date source to read. Defaults to the current Date.
|
|
489
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
417
490
|
* @returns {string} UTC date string in the form `YYYY-MM-DD`
|
|
418
491
|
* @category state
|
|
419
492
|
*/
|
|
420
|
-
export function todayUTC(date = new Date()) {
|
|
421
|
-
return
|
|
422
|
-
padNumber(date.getUTCFullYear(), 4),
|
|
423
|
-
padNumber(date.getUTCMonth() + 1, 2),
|
|
424
|
-
padNumber(date.getUTCDate(), 2),
|
|
425
|
-
].join('-');
|
|
493
|
+
export function todayUTC(date = new Date(), calendar = gregorianCalendar) {
|
|
494
|
+
return formatCalendarDateFromDate(date, true, calendar);
|
|
426
495
|
}
|
|
427
496
|
/**
|
|
428
497
|
* Returns the current date-time as an immutable Timestamp using UTC fields.
|
|
@@ -432,20 +501,22 @@ export function todayUTC(date = new Date()) {
|
|
|
432
501
|
* caller instead of allowing each runtime to create its own current Date.
|
|
433
502
|
*
|
|
434
503
|
* @param {Date} date Date source to read. Defaults to the current Date.
|
|
504
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
435
505
|
* @returns {Timestamp} Immutable Timestamp built from UTC fields.
|
|
436
506
|
* @category state
|
|
437
507
|
*/
|
|
438
|
-
export function nowUTC(date = new Date()) {
|
|
439
|
-
return parseDateUTC(date);
|
|
508
|
+
export function nowUTC(date = new Date(), calendar = gregorianCalendar) {
|
|
509
|
+
return parseDateUTC(date, calendar);
|
|
440
510
|
}
|
|
441
511
|
/**
|
|
442
512
|
* Takes a date string ('YYYY-MM-DD') and validates if it is today's date
|
|
443
513
|
* @param {string} date Date string in the form 'YYYY-MM-DD'
|
|
514
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
444
515
|
* @returns {boolean} True if the date is today's date
|
|
445
516
|
* @category comparison
|
|
446
517
|
*/
|
|
447
|
-
export function isToday(date) {
|
|
448
|
-
return date === today();
|
|
518
|
+
export function isToday(date, calendar = gregorianCalendar) {
|
|
519
|
+
return date === today(calendar);
|
|
449
520
|
}
|
|
450
521
|
/**
|
|
451
522
|
* Checks whether a date string matches today's UTC date.
|
|
@@ -455,11 +526,12 @@ export function isToday(date) {
|
|
|
455
526
|
*
|
|
456
527
|
* @param {string} date Date string in the form `YYYY-MM-DD`.
|
|
457
528
|
* @param {Date} now Date source to read. Defaults to the current Date.
|
|
529
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
458
530
|
* @returns {boolean} True when the date matches the UTC date.
|
|
459
531
|
* @category comparison
|
|
460
532
|
*/
|
|
461
|
-
export function isTodayUTC(date, now = new Date()) {
|
|
462
|
-
return date === todayUTC(now);
|
|
533
|
+
export function isTodayUTC(date, now = new Date(), calendar = gregorianCalendar) {
|
|
534
|
+
return date === todayUTC(now, calendar);
|
|
463
535
|
}
|
|
464
536
|
/**
|
|
465
537
|
* Returns the start of the week for a Timestamp and weekday set.
|
|
@@ -467,25 +539,12 @@ export function isTodayUTC(date, now = new Date()) {
|
|
|
467
539
|
* @param {Timestamp} timestamp The Timestamp to use to find the start of the week
|
|
468
540
|
* @param {number[]} weekdays The array is [0,1,2,3,4,5,6] where 0=Sunday and 6=Saturday
|
|
469
541
|
* @param {Timestamp=} today Current timestamp used to update relative information
|
|
542
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
470
543
|
* @returns {Timestamp} A new Timestamp representing the start of the week
|
|
471
544
|
* @category ranges
|
|
472
545
|
*/
|
|
473
|
-
export function getStartOfWeek(timestamp, weekdays, today) {
|
|
474
|
-
|
|
475
|
-
if (!weekdays) {
|
|
476
|
-
return freezeTimestamp(start);
|
|
477
|
-
}
|
|
478
|
-
if (start.day === 1 || start.weekday === 0) {
|
|
479
|
-
while (!weekdays.includes(Number(start.weekday))) {
|
|
480
|
-
start = nextDay(start);
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
start = findWeekday(start, weekdays[0], prevDay);
|
|
484
|
-
start = updateFormatted(start);
|
|
485
|
-
if (today) {
|
|
486
|
-
start = updateRelative(start, today, start.hasTime);
|
|
487
|
-
}
|
|
488
|
-
return start;
|
|
546
|
+
export function getStartOfWeek(timestamp, weekdays, today, calendar = gregorianCalendar) {
|
|
547
|
+
return getCalendarStartOfWeek(timestamp, weekdays, calendar, today);
|
|
489
548
|
}
|
|
490
549
|
/**
|
|
491
550
|
* Returns the end of the week for a Timestamp and weekday set.
|
|
@@ -493,51 +552,32 @@ export function getStartOfWeek(timestamp, weekdays, today) {
|
|
|
493
552
|
* @param {Timestamp} timestamp The Timestamp to use to find the end of the week
|
|
494
553
|
* @param {number[]} weekdays The array is [0,1,2,3,4,5,6] where 0=Sunday and 6=Saturday
|
|
495
554
|
* @param {Timestamp=} today Current timestamp used to update relative information
|
|
555
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
496
556
|
* @returns {Timestamp} A new Timestamp representing the end of the week
|
|
497
557
|
* @category ranges
|
|
498
558
|
*/
|
|
499
|
-
export function getEndOfWeek(timestamp, weekdays, today) {
|
|
500
|
-
|
|
501
|
-
if (!weekdays || !Array.isArray(weekdays)) {
|
|
502
|
-
return freezeTimestamp(end);
|
|
503
|
-
}
|
|
504
|
-
// is last day of month?
|
|
505
|
-
const lastDay = daysInMonth(end.year, end.month);
|
|
506
|
-
if (lastDay === end.day || end.weekday === weekdays[weekdays.length - 1]) {
|
|
507
|
-
while (!weekdays.includes(Number(end.weekday))) {
|
|
508
|
-
end = prevDay(end);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
end = findWeekday(end, weekdays[weekdays.length - 1], nextDay);
|
|
512
|
-
end = updateFormatted(end);
|
|
513
|
-
if (today) {
|
|
514
|
-
end = updateRelative(end, today, end.hasTime);
|
|
515
|
-
}
|
|
516
|
-
return end;
|
|
559
|
+
export function getEndOfWeek(timestamp, weekdays, today, calendar = gregorianCalendar) {
|
|
560
|
+
return getCalendarEndOfWeek(timestamp, weekdays, calendar, today);
|
|
517
561
|
}
|
|
518
562
|
/**
|
|
519
563
|
* Finds the start of the month based on the passed in Timestamp
|
|
520
564
|
* @param {Timestamp} timestamp The Timestamp to use to find the start of the month
|
|
565
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
521
566
|
* @returns {Timestamp} A Timestamp of the start of the month
|
|
522
567
|
* @category ranges
|
|
523
568
|
*/
|
|
524
|
-
export function getStartOfMonth(timestamp) {
|
|
525
|
-
|
|
526
|
-
start.day = DAY_MIN;
|
|
527
|
-
start = updateFormatted(start);
|
|
528
|
-
return start;
|
|
569
|
+
export function getStartOfMonth(timestamp, calendar = gregorianCalendar) {
|
|
570
|
+
return getCalendarStartOfMonth(timestamp, calendar);
|
|
529
571
|
}
|
|
530
572
|
/**
|
|
531
573
|
* Finds the end of the month based on the passed in Timestamp
|
|
532
574
|
* @param {Timestamp} timestamp The Timestamp to use to find the end of the month
|
|
575
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
533
576
|
* @returns {Timestamp} A Timestamp of the end of the month
|
|
534
577
|
* @category ranges
|
|
535
578
|
*/
|
|
536
|
-
export function getEndOfMonth(timestamp) {
|
|
537
|
-
|
|
538
|
-
end.day = daysInMonth(end.year, end.month);
|
|
539
|
-
end = updateFormatted(end);
|
|
540
|
-
return end;
|
|
579
|
+
export function getEndOfMonth(timestamp, calendar = gregorianCalendar) {
|
|
580
|
+
return getCalendarEndOfMonth(timestamp, calendar);
|
|
541
581
|
}
|
|
542
582
|
/**
|
|
543
583
|
* Converts time input into minutes since midnight.
|
|
@@ -671,7 +711,7 @@ export function getDayIdentifier(timestamp) {
|
|
|
671
711
|
* same serial day space so ranges and comparisons can be calendar-agnostic.
|
|
672
712
|
*
|
|
673
713
|
* @param {Timestamp} timestamp Timestamp object to read.
|
|
674
|
-
* @param {CalendarSystem=} calendar Calendar
|
|
714
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
675
715
|
* @returns {number} Stable serial day.
|
|
676
716
|
* @category conversion
|
|
677
717
|
*/
|
|
@@ -685,18 +725,43 @@ export function getEpochDay(timestamp, calendar = gregorianCalendar) {
|
|
|
685
725
|
* range comparisons, or virtualized day rows across different calendar adapters.
|
|
686
726
|
*
|
|
687
727
|
* @param timestamp Timestamp object to read.
|
|
688
|
-
* @param calendar Calendar
|
|
728
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
689
729
|
* @returns Stable serial day.
|
|
690
730
|
* @category calendar
|
|
691
731
|
*/
|
|
692
732
|
export function getCalendarDayIdentifier(timestamp, calendar = gregorianCalendar) {
|
|
693
733
|
return getEpochDay(timestamp, calendar);
|
|
694
734
|
}
|
|
735
|
+
/**
|
|
736
|
+
* Creates stable native and Gregorian identities for a calendar timestamp.
|
|
737
|
+
*
|
|
738
|
+
* Use this when component APIs need to expose adapter-native values while also
|
|
739
|
+
* preserving a canonical Gregorian key for storage, comparisons, or interop
|
|
740
|
+
* with existing data.
|
|
741
|
+
*
|
|
742
|
+
* @param timestamp Timestamp object to identify.
|
|
743
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
744
|
+
* @returns Calendar-native date, Gregorian interop date, and shared epoch day.
|
|
745
|
+
* @category calendar
|
|
746
|
+
*/
|
|
747
|
+
export function getCalendarDateIdentity(timestamp, calendar = gregorianCalendar) {
|
|
748
|
+
const native = toCalendarDateParts(timestamp);
|
|
749
|
+
const epochDay = calendar.toEpochDay(native);
|
|
750
|
+
const gregorian = gregorianCalendar.fromEpochDay(epochDay);
|
|
751
|
+
return Object.freeze({
|
|
752
|
+
calendarId: calendar.id,
|
|
753
|
+
nativeDate: formatCalendarDate(native),
|
|
754
|
+
native,
|
|
755
|
+
gregorianDate: formatCalendarDate(gregorian),
|
|
756
|
+
gregorian,
|
|
757
|
+
epochDay,
|
|
758
|
+
});
|
|
759
|
+
}
|
|
695
760
|
/**
|
|
696
761
|
* Returns true when calendar date fields are valid for a calendar system.
|
|
697
762
|
*
|
|
698
763
|
* @param date Calendar date fields to validate.
|
|
699
|
-
* @param calendar Calendar
|
|
764
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
700
765
|
* @returns True when year, month, and day can exist in the calendar.
|
|
701
766
|
* @category calendar
|
|
702
767
|
*/
|
|
@@ -714,7 +779,7 @@ export function isValidCalendarDate(date, calendar = gregorianCalendar) {
|
|
|
714
779
|
* `calendarId`, and derives weekday/day-of-year values from the adapter.
|
|
715
780
|
*
|
|
716
781
|
* @param date Calendar date fields.
|
|
717
|
-
* @param calendar Calendar
|
|
782
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
718
783
|
* @param options Optional time and relative comparison settings.
|
|
719
784
|
* @returns Timestamp-shaped calendar value.
|
|
720
785
|
* @category calendar
|
|
@@ -760,7 +825,7 @@ export function createCalendarTimestamp(date, calendar = gregorianCalendar, opti
|
|
|
760
825
|
* calendar and derives weekday/day-of-year values through the adapter.
|
|
761
826
|
*
|
|
762
827
|
* @param input Date or date-time string.
|
|
763
|
-
* @param calendar Calendar
|
|
828
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
764
829
|
* @param now Optional comparison timestamp from the same calendar system.
|
|
765
830
|
* @returns Calendar timestamp, or `null` when the input cannot be parsed or validated.
|
|
766
831
|
* @category calendar
|
|
@@ -777,11 +842,26 @@ export function parseCalendarTimestamp(input, calendar = gregorianCalendar, now
|
|
|
777
842
|
now,
|
|
778
843
|
});
|
|
779
844
|
}
|
|
845
|
+
/**
|
|
846
|
+
* Validates whether an input string can be parsed as a calendar adapter timestamp.
|
|
847
|
+
*
|
|
848
|
+
* The default Gregorian calendar preserves existing Timestamp semantics. When
|
|
849
|
+
* an alternate calendar is supplied, `YYYY-MM-DD` is interpreted as native to
|
|
850
|
+
* that adapter.
|
|
851
|
+
*
|
|
852
|
+
* @param input Date or date-time string.
|
|
853
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
854
|
+
* @returns True when the string can be parsed and exists in the calendar.
|
|
855
|
+
* @category calendar
|
|
856
|
+
*/
|
|
857
|
+
export function validateCalendarTimestamp(input, calendar = gregorianCalendar) {
|
|
858
|
+
return parseCalendarTimestamp(input, calendar) !== null;
|
|
859
|
+
}
|
|
780
860
|
/**
|
|
781
861
|
* Creates a calendar timestamp from a stable serial day.
|
|
782
862
|
*
|
|
783
863
|
* @param epochDay Stable serial day.
|
|
784
|
-
* @param calendar Calendar
|
|
864
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
785
865
|
* @param options Optional time and relative comparison settings.
|
|
786
866
|
* @returns Timestamp-shaped calendar value.
|
|
787
867
|
* @category calendar
|
|
@@ -793,7 +873,7 @@ export function createCalendarTimestampFromEpochDay(epochDay, calendar = gregori
|
|
|
793
873
|
* Updates formatted calendar metadata on a timestamp-shaped value.
|
|
794
874
|
*
|
|
795
875
|
* @param timestamp Timestamp object to transform.
|
|
796
|
-
* @param calendar Calendar
|
|
876
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
797
877
|
* @returns Timestamp with adapter date formatting and metadata.
|
|
798
878
|
* @category calendar
|
|
799
879
|
*/
|
|
@@ -805,7 +885,7 @@ export function updateCalendarFormatted(timestamp, calendar = gregorianCalendar)
|
|
|
805
885
|
*
|
|
806
886
|
* @param timestamp Timestamp object to update.
|
|
807
887
|
* @param now Timestamp representing the comparison point in the same calendar.
|
|
808
|
-
* @param calendar Calendar
|
|
888
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
809
889
|
* @param time Include time-of-day in the comparison when true.
|
|
810
890
|
* @returns New Timestamp object with relative flags.
|
|
811
891
|
* @category calendar
|
|
@@ -830,7 +910,7 @@ export function updateCalendarRelative(timestamp, now, calendar = gregorianCalen
|
|
|
830
910
|
* Returns a calendar timestamp for the next day.
|
|
831
911
|
*
|
|
832
912
|
* @param timestamp Base timestamp.
|
|
833
|
-
* @param calendar Calendar
|
|
913
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
834
914
|
* @returns New timestamp for the next adapter day.
|
|
835
915
|
* @category calendar
|
|
836
916
|
*/
|
|
@@ -841,7 +921,7 @@ export function nextCalendarDay(timestamp, calendar = gregorianCalendar) {
|
|
|
841
921
|
* Returns a calendar timestamp for the previous day.
|
|
842
922
|
*
|
|
843
923
|
* @param timestamp Base timestamp.
|
|
844
|
-
* @param calendar Calendar
|
|
924
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
845
925
|
* @returns New timestamp for the previous adapter day.
|
|
846
926
|
* @category calendar
|
|
847
927
|
*/
|
|
@@ -853,7 +933,7 @@ export function prevCalendarDay(timestamp, calendar = gregorianCalendar) {
|
|
|
853
933
|
*
|
|
854
934
|
* @param timestamp Base timestamp.
|
|
855
935
|
* @param amount Number of days to move.
|
|
856
|
-
* @param calendar Calendar
|
|
936
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
857
937
|
* @returns New timestamp after moving.
|
|
858
938
|
* @category calendar
|
|
859
939
|
*/
|
|
@@ -865,7 +945,7 @@ export function addCalendarDays(timestamp, amount, calendar = gregorianCalendar)
|
|
|
865
945
|
*
|
|
866
946
|
* @param timestamp Base timestamp.
|
|
867
947
|
* @param amount Number of calendar months to move.
|
|
868
|
-
* @param calendar Calendar
|
|
948
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
869
949
|
* @returns New timestamp after moving.
|
|
870
950
|
* @category calendar
|
|
871
951
|
*/
|
|
@@ -896,7 +976,7 @@ export function addCalendarMonths(timestamp, amount, calendar = gregorianCalenda
|
|
|
896
976
|
*
|
|
897
977
|
* @param timestamp Base timestamp.
|
|
898
978
|
* @param amount Number of calendar years to move.
|
|
899
|
-
* @param calendar Calendar
|
|
979
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
900
980
|
* @returns New timestamp after moving.
|
|
901
981
|
* @category calendar
|
|
902
982
|
*/
|
|
@@ -911,7 +991,7 @@ export function addCalendarYears(timestamp, amount, calendar = gregorianCalendar
|
|
|
911
991
|
* Returns the start of the calendar month for a timestamp.
|
|
912
992
|
*
|
|
913
993
|
* @param timestamp Base timestamp.
|
|
914
|
-
* @param calendar Calendar
|
|
994
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
915
995
|
* @returns First day of the adapter month.
|
|
916
996
|
* @category calendar
|
|
917
997
|
*/
|
|
@@ -922,7 +1002,7 @@ export function getCalendarStartOfMonth(timestamp, calendar = gregorianCalendar)
|
|
|
922
1002
|
* Returns the end of the calendar month for a timestamp.
|
|
923
1003
|
*
|
|
924
1004
|
* @param timestamp Base timestamp.
|
|
925
|
-
* @param calendar Calendar
|
|
1005
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
926
1006
|
* @returns Last day of the adapter month.
|
|
927
1007
|
* @category calendar
|
|
928
1008
|
*/
|
|
@@ -937,7 +1017,7 @@ export function getCalendarEndOfMonth(timestamp, calendar = gregorianCalendar) {
|
|
|
937
1017
|
* Returns the start of the calendar year for a timestamp.
|
|
938
1018
|
*
|
|
939
1019
|
* @param timestamp Base timestamp.
|
|
940
|
-
* @param calendar Calendar
|
|
1020
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
941
1021
|
* @returns First day of the adapter year.
|
|
942
1022
|
* @category calendar
|
|
943
1023
|
*/
|
|
@@ -948,7 +1028,7 @@ export function getCalendarStartOfYear(timestamp, calendar = gregorianCalendar)
|
|
|
948
1028
|
* Returns the end of the calendar year for a timestamp.
|
|
949
1029
|
*
|
|
950
1030
|
* @param timestamp Base timestamp.
|
|
951
|
-
* @param calendar Calendar
|
|
1031
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
952
1032
|
* @returns Last day of the adapter year.
|
|
953
1033
|
* @category calendar
|
|
954
1034
|
*/
|
|
@@ -961,7 +1041,7 @@ export function getCalendarEndOfYear(timestamp, calendar = gregorianCalendar) {
|
|
|
961
1041
|
*
|
|
962
1042
|
* @param timestamp Base timestamp.
|
|
963
1043
|
* @param weekday Weekday number to find.
|
|
964
|
-
* @param calendar Calendar
|
|
1044
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
965
1045
|
* @param direction Direction to search.
|
|
966
1046
|
* @param maxDays Maximum days to inspect.
|
|
967
1047
|
* @returns Matching timestamp, or the last inspected timestamp.
|
|
@@ -980,7 +1060,7 @@ export function findCalendarWeekday(timestamp, weekday, calendar = gregorianCale
|
|
|
980
1060
|
*
|
|
981
1061
|
* @param timestamp Base timestamp.
|
|
982
1062
|
* @param weekdays Weekday numbers to include, from `0` Sunday to `6` Saturday.
|
|
983
|
-
* @param calendar Calendar
|
|
1063
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
984
1064
|
* @param now Optional comparison timestamp from the same calendar.
|
|
985
1065
|
* @returns Start of the adapter week.
|
|
986
1066
|
* @category calendar
|
|
@@ -1003,7 +1083,7 @@ export function getCalendarStartOfWeek(timestamp, weekdays, calendar = gregorian
|
|
|
1003
1083
|
*
|
|
1004
1084
|
* @param timestamp Base timestamp.
|
|
1005
1085
|
* @param weekdays Weekday numbers to include, from `0` Sunday to `6` Saturday.
|
|
1006
|
-
* @param calendar Calendar
|
|
1086
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1007
1087
|
* @param now Optional comparison timestamp from the same calendar.
|
|
1008
1088
|
* @returns End of the adapter week.
|
|
1009
1089
|
* @category calendar
|
|
@@ -1028,7 +1108,7 @@ export function getCalendarEndOfWeek(timestamp, weekdays, calendar = gregorianCa
|
|
|
1028
1108
|
* @param start First day in the list.
|
|
1029
1109
|
* @param end Last day boundary for the list.
|
|
1030
1110
|
* @param now Timestamp used to calculate relative flags.
|
|
1031
|
-
* @param calendar Calendar
|
|
1111
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1032
1112
|
* @param options Optional weekday, disabled, and size filters.
|
|
1033
1113
|
* @returns Timestamp days for the adapter calendar.
|
|
1034
1114
|
* @category calendar
|
|
@@ -1056,12 +1136,28 @@ export function createCalendarDayList(start, end, now, calendar = gregorianCalen
|
|
|
1056
1136
|
}
|
|
1057
1137
|
let day = updateCalendarFormatted(current, calendar);
|
|
1058
1138
|
day = updateCalendarRelative(day, now, calendar);
|
|
1059
|
-
day =
|
|
1139
|
+
day = updateCalendarDisabled(day, disabledBefore, disabledAfter, disabledWeekdays, disabledDays, calendar);
|
|
1060
1140
|
days.push(day);
|
|
1061
1141
|
current = nextCalendarDay(current, calendar);
|
|
1062
1142
|
}
|
|
1063
1143
|
return days;
|
|
1064
1144
|
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Returns true when a timestamp falls outside the reference timestamp's adapter month.
|
|
1147
|
+
*
|
|
1148
|
+
* @param timestamp Timestamp to test.
|
|
1149
|
+
* @param reference Timestamp whose month defines the inside range.
|
|
1150
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1151
|
+
* @returns True when timestamp is outside reference's calendar month.
|
|
1152
|
+
* @category calendar
|
|
1153
|
+
*/
|
|
1154
|
+
export function isOutsideCalendarMonth(timestamp, reference, calendar = gregorianCalendar) {
|
|
1155
|
+
const start = getCalendarStartOfMonth(reference, calendar);
|
|
1156
|
+
const end = getCalendarEndOfMonth(reference, calendar);
|
|
1157
|
+
const targetIdentifier = getCalendarDayIdentifier(timestamp, calendar);
|
|
1158
|
+
return (targetIdentifier < getCalendarDayIdentifier(start, calendar) ||
|
|
1159
|
+
targetIdentifier > getCalendarDayIdentifier(end, calendar));
|
|
1160
|
+
}
|
|
1065
1161
|
/**
|
|
1066
1162
|
* Converts a Timestamp time into a sortable numeric identifier.
|
|
1067
1163
|
*
|
|
@@ -1117,13 +1213,14 @@ export function diffTimestamp(ts1, ts2, strict = false) {
|
|
|
1117
1213
|
* @param {Timestamp} timestamp Timestamp object to update.
|
|
1118
1214
|
* @param {Timestamp} now Timestamp representing the comparison point.
|
|
1119
1215
|
* @param {boolean=} time Include time-of-day in the comparison when true.
|
|
1216
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1120
1217
|
* @returns {Timestamp} New Timestamp object with relative flags.
|
|
1121
1218
|
* @category state
|
|
1122
1219
|
*/
|
|
1123
|
-
export function updateRelative(timestamp, now, time = false) {
|
|
1220
|
+
export function updateRelative(timestamp, now, time = false, calendar = gregorianCalendar) {
|
|
1124
1221
|
const ts = cloneTimestamp(timestamp);
|
|
1125
|
-
let a =
|
|
1126
|
-
let b =
|
|
1222
|
+
let a = getCalendarDayIdentifier(now, calendar);
|
|
1223
|
+
let b = getCalendarDayIdentifier(ts, calendar);
|
|
1127
1224
|
let current = a === b;
|
|
1128
1225
|
if (ts.hasTime && time && current) {
|
|
1129
1226
|
a = getTimeComparisonValue(now);
|
|
@@ -1145,10 +1242,11 @@ export function updateRelative(timestamp, now, time = false) {
|
|
|
1145
1242
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
1146
1243
|
* @param {number} minutes The number of minutes to set from midnight
|
|
1147
1244
|
* @param {Timestamp=} now Optional Timestamp representing current date and time
|
|
1245
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1148
1246
|
* @returns {Timestamp} A new Timestamp
|
|
1149
1247
|
* @category arithmetic
|
|
1150
1248
|
*/
|
|
1151
|
-
export function updateMinutes(timestamp, minutes, now = null) {
|
|
1249
|
+
export function updateMinutes(timestamp, minutes, now = null, calendar = gregorianCalendar) {
|
|
1152
1250
|
let ts = cloneTimestamp(timestamp);
|
|
1153
1251
|
ts.hasTime = true;
|
|
1154
1252
|
ts.hour = Math.floor(minutes / TIME_CONSTANTS.MINUTES_IN.HOUR);
|
|
@@ -1157,41 +1255,44 @@ export function updateMinutes(timestamp, minutes, now = null) {
|
|
|
1157
1255
|
delete ts.millisecond;
|
|
1158
1256
|
ts.time = getTime(ts);
|
|
1159
1257
|
if (now) {
|
|
1160
|
-
return updateRelative(ts, now, true);
|
|
1258
|
+
return updateRelative(ts, now, true, calendar);
|
|
1161
1259
|
}
|
|
1162
1260
|
return freezeTimestamp(ts);
|
|
1163
1261
|
}
|
|
1164
1262
|
/**
|
|
1165
1263
|
* Updates the Timestamp with the weekday
|
|
1166
1264
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
1265
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1167
1266
|
* @returns A new Timestamp
|
|
1168
1267
|
* @category formatting
|
|
1169
1268
|
*/
|
|
1170
|
-
export function updateWeekday(timestamp) {
|
|
1269
|
+
export function updateWeekday(timestamp, calendar = gregorianCalendar) {
|
|
1171
1270
|
const ts = cloneTimestamp(timestamp);
|
|
1172
|
-
ts.weekday = getWeekday(ts);
|
|
1271
|
+
ts.weekday = getWeekday(ts, calendar);
|
|
1173
1272
|
return freezeTimestamp(ts);
|
|
1174
1273
|
}
|
|
1175
1274
|
/**
|
|
1176
1275
|
* Updates the Timestamp with the day of the year (doy)
|
|
1177
1276
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
1277
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1178
1278
|
* @returns A new Timestamp
|
|
1179
1279
|
* @category formatting
|
|
1180
1280
|
*/
|
|
1181
|
-
export function updateDayOfYear(timestamp) {
|
|
1281
|
+
export function updateDayOfYear(timestamp, calendar = gregorianCalendar) {
|
|
1182
1282
|
const ts = cloneTimestamp(timestamp);
|
|
1183
|
-
ts.doy = getDayOfYear(ts) || 0;
|
|
1283
|
+
ts.doy = getDayOfYear(ts, calendar) || 0;
|
|
1184
1284
|
return freezeTimestamp(ts);
|
|
1185
1285
|
}
|
|
1186
1286
|
/**
|
|
1187
1287
|
* Updates the Timestamp with the workweek
|
|
1188
1288
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
1289
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1189
1290
|
* @returns A new Timestamp
|
|
1190
1291
|
* @category formatting
|
|
1191
1292
|
*/
|
|
1192
|
-
export function updateWorkWeek(timestamp) {
|
|
1293
|
+
export function updateWorkWeek(timestamp, calendar = gregorianCalendar) {
|
|
1193
1294
|
const ts = cloneTimestamp(timestamp);
|
|
1194
|
-
ts.workweek = getWorkWeek(ts);
|
|
1295
|
+
ts.workweek = getWorkWeek(ts, calendar);
|
|
1195
1296
|
return freezeTimestamp(ts);
|
|
1196
1297
|
}
|
|
1197
1298
|
function isDisabledDayConfig(value) {
|
|
@@ -1239,6 +1340,42 @@ function isTimestampInDisabledDay(timestamp, day) {
|
|
|
1239
1340
|
const disabledDay = parseTimestamp(day);
|
|
1240
1341
|
return disabledDay !== null && getDayIdentifier(disabledDay) === target;
|
|
1241
1342
|
}
|
|
1343
|
+
function parseCalendarDateIdentifier(value, calendar) {
|
|
1344
|
+
const timestamp = parseCalendarTimestamp(value, calendar);
|
|
1345
|
+
return timestamp === null ? null : getCalendarDayIdentifier(timestamp, calendar);
|
|
1346
|
+
}
|
|
1347
|
+
function isTimestampInCalendarDisabledDay(timestamp, day, calendar) {
|
|
1348
|
+
const target = getCalendarDayIdentifier(timestamp, calendar);
|
|
1349
|
+
if (Array.isArray(day) === true) {
|
|
1350
|
+
if (day.length === 2 && day[0] && day[1]) {
|
|
1351
|
+
const start = parseCalendarDateIdentifier(day[0], calendar);
|
|
1352
|
+
const end = parseCalendarDateIdentifier(day[1], calendar);
|
|
1353
|
+
return (start !== null &&
|
|
1354
|
+
end !== null &&
|
|
1355
|
+
target >= Math.min(start, end) &&
|
|
1356
|
+
target <= Math.max(start, end));
|
|
1357
|
+
}
|
|
1358
|
+
return day.some((date) => parseCalendarDateIdentifier(date, calendar) === target);
|
|
1359
|
+
}
|
|
1360
|
+
if (isDisabledDayConfig(day) === true) {
|
|
1361
|
+
const date = day.date;
|
|
1362
|
+
const startDate = day.from ?? day.start;
|
|
1363
|
+
const endDate = day.to ?? day.end;
|
|
1364
|
+
if (date !== undefined) {
|
|
1365
|
+
return parseCalendarDateIdentifier(date, calendar) === target;
|
|
1366
|
+
}
|
|
1367
|
+
if (startDate !== undefined && endDate !== undefined) {
|
|
1368
|
+
const start = parseCalendarDateIdentifier(startDate, calendar);
|
|
1369
|
+
const end = parseCalendarDateIdentifier(endDate, calendar);
|
|
1370
|
+
return (start !== null &&
|
|
1371
|
+
end !== null &&
|
|
1372
|
+
target >= Math.min(start, end) &&
|
|
1373
|
+
target <= Math.max(start, end));
|
|
1374
|
+
}
|
|
1375
|
+
return false;
|
|
1376
|
+
}
|
|
1377
|
+
return parseCalendarDateIdentifier(day, calendar) === target;
|
|
1378
|
+
}
|
|
1242
1379
|
/**
|
|
1243
1380
|
* Updates the passed Timestamp with disabled, if needed
|
|
1244
1381
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
@@ -1288,47 +1425,218 @@ export function updateDisabled(timestamp, disabledBefore, disabledAfter, disable
|
|
|
1288
1425
|
}
|
|
1289
1426
|
return freezeTimestamp(ts);
|
|
1290
1427
|
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Updates a timestamp with disabled state using calendar-native date strings.
|
|
1430
|
+
*
|
|
1431
|
+
* The default Gregorian calendar preserves existing Timestamp behavior. When
|
|
1432
|
+
* an alternate calendar is supplied, `disabledBefore`, `disabledAfter`, and
|
|
1433
|
+
* `disabledDays` are parsed as native dates for that adapter.
|
|
1434
|
+
*
|
|
1435
|
+
* @param timestamp Timestamp to transform.
|
|
1436
|
+
* @param disabledBefore Disable days on or before this adapter date.
|
|
1437
|
+
* @param disabledAfter Disable days on or after this adapter date.
|
|
1438
|
+
* @param disabledWeekdays Weekday numbers to mark disabled.
|
|
1439
|
+
* @param disabledDays Specific adapter dates or date ranges to mark disabled.
|
|
1440
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1441
|
+
* @returns New timestamp with disabled metadata applied.
|
|
1442
|
+
* @category calendar
|
|
1443
|
+
*/
|
|
1444
|
+
export function updateCalendarDisabled(timestamp, disabledBefore, disabledAfter, disabledWeekdays, disabledDays, calendar = gregorianCalendar) {
|
|
1445
|
+
let ts = cloneTimestamp(timestamp);
|
|
1446
|
+
const target = getCalendarDayIdentifier(ts, calendar);
|
|
1447
|
+
if (disabledBefore !== undefined) {
|
|
1448
|
+
const before = parseCalendarDateIdentifier(disabledBefore, calendar);
|
|
1449
|
+
if (before !== null && target <= before) {
|
|
1450
|
+
ts.disabled = true;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
if (ts.disabled !== true && disabledAfter !== undefined) {
|
|
1454
|
+
const after = parseCalendarDateIdentifier(disabledAfter, calendar);
|
|
1455
|
+
if (after !== null && target >= after) {
|
|
1456
|
+
ts.disabled = true;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
if (ts.disabled !== true && Array.isArray(disabledWeekdays) && disabledWeekdays.length > 0) {
|
|
1460
|
+
for (const weekday of disabledWeekdays) {
|
|
1461
|
+
if (weekday === ts.weekday) {
|
|
1462
|
+
ts.disabled = true;
|
|
1463
|
+
break;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
if (ts.disabled !== true && Array.isArray(disabledDays) && disabledDays.length > 0) {
|
|
1468
|
+
for (const day of disabledDays) {
|
|
1469
|
+
if (isTimestampInCalendarDisabledDay(ts, day, calendar) === true) {
|
|
1470
|
+
ts = applyDisabledDayConfig(ts, isDisabledDayConfig(day) === true ? day : undefined);
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return freezeTimestamp(ts);
|
|
1476
|
+
}
|
|
1477
|
+
function isTimestampInCalendarDateCollection(timestamp, dates, calendar) {
|
|
1478
|
+
if (dates === undefined) {
|
|
1479
|
+
return false;
|
|
1480
|
+
}
|
|
1481
|
+
const target = getCalendarDayIdentifier(timestamp, calendar);
|
|
1482
|
+
for (const date of dates) {
|
|
1483
|
+
if (parseCalendarDateIdentifier(date, calendar) === target) {
|
|
1484
|
+
return true;
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Resolves selected-date and selected-range state for a calendar timestamp.
|
|
1491
|
+
*
|
|
1492
|
+
* The default Gregorian calendar preserves existing Timestamp behavior. When
|
|
1493
|
+
* an alternate calendar is supplied, selected date strings are parsed as native
|
|
1494
|
+
* adapter dates.
|
|
1495
|
+
*
|
|
1496
|
+
* @param timestamp Timestamp to inspect.
|
|
1497
|
+
* @param options Selected dates and selected start/end dates.
|
|
1498
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1499
|
+
* @returns Selected-date state for the timestamp.
|
|
1500
|
+
* @category calendar
|
|
1501
|
+
*/
|
|
1502
|
+
export function getCalendarSelectionState(timestamp, options = {}, calendar = gregorianCalendar) {
|
|
1503
|
+
const selectedDate = isTimestampInCalendarDateCollection(timestamp, options.selectedDates, calendar);
|
|
1504
|
+
const target = getCalendarDayIdentifier(timestamp, calendar);
|
|
1505
|
+
const rangeBoundaryDates = options.selectedStartEndDates ?? [];
|
|
1506
|
+
let rangeFirst = false;
|
|
1507
|
+
let range = false;
|
|
1508
|
+
let rangeLast = false;
|
|
1509
|
+
if (rangeBoundaryDates.length === 2 && rangeBoundaryDates[0] && rangeBoundaryDates[1]) {
|
|
1510
|
+
const first = parseCalendarDateIdentifier(rangeBoundaryDates[0], calendar);
|
|
1511
|
+
const last = parseCalendarDateIdentifier(rangeBoundaryDates[1], calendar);
|
|
1512
|
+
if (first !== null && last !== null) {
|
|
1513
|
+
const start = Math.min(first, last);
|
|
1514
|
+
const end = Math.max(first, last);
|
|
1515
|
+
rangeFirst = target === start;
|
|
1516
|
+
rangeLast = target === end;
|
|
1517
|
+
range = target > start && target < end;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return Object.freeze({
|
|
1521
|
+
selectedDate,
|
|
1522
|
+
rangeFirst,
|
|
1523
|
+
range,
|
|
1524
|
+
rangeLast,
|
|
1525
|
+
selected: selectedDate || rangeFirst || range || rangeLast,
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Resolves disabled, selected, identity, and outside-month state for one date.
|
|
1530
|
+
*
|
|
1531
|
+
* @param timestamp Timestamp to resolve.
|
|
1532
|
+
* @param options Calendar-aware disabled, selection, and outside-month options.
|
|
1533
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1534
|
+
* @returns Calendar date state suitable for component scopes.
|
|
1535
|
+
* @category calendar
|
|
1536
|
+
*/
|
|
1537
|
+
export function getCalendarDateState(timestamp, options = {}, calendar = gregorianCalendar) {
|
|
1538
|
+
const disabledTimestamp = updateCalendarDisabled(timestamp, options.disabledBefore, options.disabledAfter, options.disabledWeekdays, options.disabledDays, calendar);
|
|
1539
|
+
const selection = getCalendarSelectionState(disabledTimestamp, options, calendar);
|
|
1540
|
+
const outside = options.outside ??
|
|
1541
|
+
(options.referenceMonth === undefined
|
|
1542
|
+
? false
|
|
1543
|
+
: isOutsideCalendarMonth(disabledTimestamp, options.referenceMonth, calendar));
|
|
1544
|
+
return Object.freeze({
|
|
1545
|
+
timestamp: disabledTimestamp,
|
|
1546
|
+
identity: getCalendarDateIdentity(disabledTimestamp, calendar),
|
|
1547
|
+
outside,
|
|
1548
|
+
disabled: disabledTimestamp.disabled === true,
|
|
1549
|
+
...selection,
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Creates native calendar month view state for component rendering.
|
|
1554
|
+
*
|
|
1555
|
+
* The returned `days` use adapter-native `YYYY-MM-DD` values, while each
|
|
1556
|
+
* state's identity also includes Gregorian interop metadata.
|
|
1557
|
+
*
|
|
1558
|
+
* @param timestamp Reference timestamp in the adapter calendar.
|
|
1559
|
+
* @param now Timestamp used to calculate relative flags.
|
|
1560
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1561
|
+
* @param options Calendar-aware disabled, selection, weekday, and size options.
|
|
1562
|
+
* @returns Calendar month view state.
|
|
1563
|
+
* @category calendar
|
|
1564
|
+
*/
|
|
1565
|
+
export function createCalendarMonthView(timestamp, now, calendar = gregorianCalendar, options = {}) {
|
|
1566
|
+
const weekdays = options.weekdays ?? [0, 1, 2, 3, 4, 5, 6];
|
|
1567
|
+
const reference = updateCalendarFormatted(timestamp, calendar);
|
|
1568
|
+
const start = getCalendarStartOfMonth(reference, calendar);
|
|
1569
|
+
const end = getCalendarEndOfMonth(reference, calendar);
|
|
1570
|
+
const visibleStart = getCalendarStartOfWeek(start, weekdays, calendar, now);
|
|
1571
|
+
const visibleEnd = getCalendarEndOfWeek(end, weekdays, calendar, now);
|
|
1572
|
+
const days = createCalendarDayList(visibleStart, visibleEnd, now, calendar, {
|
|
1573
|
+
weekdays,
|
|
1574
|
+
disabledBefore: options.disabledBefore,
|
|
1575
|
+
disabledAfter: options.disabledAfter,
|
|
1576
|
+
disabledWeekdays: options.disabledWeekdays,
|
|
1577
|
+
disabledDays: options.disabledDays,
|
|
1578
|
+
max: options.max ?? weekdays.length * 6,
|
|
1579
|
+
min: options.min ?? weekdays.length * 6,
|
|
1580
|
+
}).map((day) => getCalendarDateState(day, {
|
|
1581
|
+
...options,
|
|
1582
|
+
referenceMonth: reference,
|
|
1583
|
+
}, calendar));
|
|
1584
|
+
return Object.freeze({
|
|
1585
|
+
reference,
|
|
1586
|
+
start,
|
|
1587
|
+
end,
|
|
1588
|
+
visibleStart,
|
|
1589
|
+
visibleEnd,
|
|
1590
|
+
days,
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1291
1593
|
/**
|
|
1292
1594
|
* Updates the passed Timestamp with formatted data (time string, date string, weekday, day of year and workweek)
|
|
1293
1595
|
* @param {Timestamp} timestamp The Timestamp to transform
|
|
1596
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1294
1597
|
* @returns A new Timestamp
|
|
1295
1598
|
* @category formatting
|
|
1296
1599
|
*/
|
|
1297
|
-
export function updateFormatted(timestamp) {
|
|
1600
|
+
export function updateFormatted(timestamp, calendar = gregorianCalendar) {
|
|
1298
1601
|
const ts = cloneTimestamp(timestamp);
|
|
1299
1602
|
ts.hasTime = true;
|
|
1300
1603
|
ts.time = getTime(ts);
|
|
1301
1604
|
ts.date = getDate(ts);
|
|
1302
|
-
ts.weekday = getWeekday(ts);
|
|
1303
|
-
ts.doy = getDayOfYear(ts) || 0;
|
|
1304
|
-
ts.workweek = getWorkWeek(ts);
|
|
1605
|
+
ts.weekday = getWeekday(ts, calendar);
|
|
1606
|
+
ts.doy = getDayOfYear(ts, calendar) || 0;
|
|
1607
|
+
ts.workweek = getWorkWeek(ts, calendar);
|
|
1305
1608
|
return freezeTimestamp(ts);
|
|
1306
1609
|
}
|
|
1307
1610
|
/**
|
|
1308
1611
|
* Returns day of the year (doy) for the passed in Timestamp
|
|
1309
1612
|
* @param {Timestamp} timestamp The Timestamp to use
|
|
1613
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1310
1614
|
* @returns {number} The day of the year
|
|
1311
1615
|
* @category formatting
|
|
1312
1616
|
*/
|
|
1313
|
-
export function getDayOfYear(timestamp) {
|
|
1617
|
+
export function getDayOfYear(timestamp, calendar = gregorianCalendar) {
|
|
1314
1618
|
if (timestamp.year === 0)
|
|
1315
1619
|
return;
|
|
1316
|
-
return
|
|
1620
|
+
return calendar.getDayOfYear(toCalendarDateParts(timestamp));
|
|
1317
1621
|
}
|
|
1318
1622
|
/**
|
|
1319
1623
|
* Returns workweek for the passed in Timestamp
|
|
1320
1624
|
* @param {Timestamp} timestamp The Timestamp to use
|
|
1625
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1321
1626
|
* @returns {number} The work week
|
|
1322
1627
|
* @category formatting
|
|
1323
1628
|
*/
|
|
1324
|
-
export function getWorkWeek(timestamp) {
|
|
1629
|
+
export function getWorkWeek(timestamp, calendar = gregorianCalendar) {
|
|
1325
1630
|
let ts = timestamp;
|
|
1326
1631
|
if (ts.year === 0) {
|
|
1327
|
-
const parsedToday =
|
|
1632
|
+
const parsedToday = parseCalendarTimestamp(today(calendar), calendar);
|
|
1328
1633
|
if (parsedToday) {
|
|
1329
1634
|
ts = parsedToday;
|
|
1330
1635
|
}
|
|
1331
1636
|
}
|
|
1637
|
+
if (calendar !== gregorianCalendar) {
|
|
1638
|
+
return getCalendarWorkWeek(toCalendarDateParts(ts), calendar);
|
|
1639
|
+
}
|
|
1332
1640
|
// Remove time components of date
|
|
1333
1641
|
const weekday = new Date(Date.UTC(ts.year, ts.month - 1, ts.day));
|
|
1334
1642
|
// Adjust the date to the correct day of the week
|
|
@@ -1346,13 +1654,14 @@ export function getWorkWeek(timestamp) {
|
|
|
1346
1654
|
/**
|
|
1347
1655
|
* Returns weekday for the passed in Timestamp
|
|
1348
1656
|
* @param {Timestamp} timestamp The Timestamp to use
|
|
1657
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1349
1658
|
* @returns {number} The weekday
|
|
1350
1659
|
* @category formatting
|
|
1351
1660
|
*/
|
|
1352
|
-
export function getWeekday(timestamp) {
|
|
1661
|
+
export function getWeekday(timestamp, calendar = gregorianCalendar) {
|
|
1353
1662
|
let weekday = timestamp.weekday;
|
|
1354
1663
|
if (timestamp.hasDay) {
|
|
1355
|
-
weekday =
|
|
1664
|
+
weekday = calendar.getWeekday(toCalendarDateParts(timestamp));
|
|
1356
1665
|
}
|
|
1357
1666
|
return weekday ?? 0;
|
|
1358
1667
|
}
|
|
@@ -1406,30 +1715,26 @@ export function getEndOfDay(timestamp) {
|
|
|
1406
1715
|
return setTimeParts(timestamp, 23, 59, 59, 999);
|
|
1407
1716
|
}
|
|
1408
1717
|
/**
|
|
1409
|
-
* Returns a Timestamp at the start of the same
|
|
1718
|
+
* Returns a Timestamp at the start of the same calendar year.
|
|
1410
1719
|
*
|
|
1411
1720
|
* @param {Timestamp} timestamp Timestamp object to transform.
|
|
1412
|
-
* @
|
|
1721
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1722
|
+
* @returns {Timestamp} New Timestamp for the first calendar day of the year at `00:00`.
|
|
1413
1723
|
* @category ranges
|
|
1414
1724
|
*/
|
|
1415
|
-
export function getStartOfYear(timestamp) {
|
|
1416
|
-
|
|
1417
|
-
ts.month = MONTH_MIN;
|
|
1418
|
-
ts.day = DAY_MIN;
|
|
1419
|
-
return getStartOfDay(updateFormatted(ts));
|
|
1725
|
+
export function getStartOfYear(timestamp, calendar = gregorianCalendar) {
|
|
1726
|
+
return getStartOfDay(getCalendarStartOfYear(timestamp, calendar));
|
|
1420
1727
|
}
|
|
1421
1728
|
/**
|
|
1422
|
-
* Returns a Timestamp at the end of the same
|
|
1729
|
+
* Returns a Timestamp at the end of the same calendar year.
|
|
1423
1730
|
*
|
|
1424
1731
|
* @param {Timestamp} timestamp Timestamp object to transform.
|
|
1425
|
-
* @
|
|
1732
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1733
|
+
* @returns {Timestamp} New Timestamp for the last calendar day of the year at `23:59:59.999`.
|
|
1426
1734
|
* @category ranges
|
|
1427
1735
|
*/
|
|
1428
|
-
export function getEndOfYear(timestamp) {
|
|
1429
|
-
|
|
1430
|
-
ts.month = MONTH_MAX;
|
|
1431
|
-
ts.day = daysInMonth(ts.year, MONTH_MAX);
|
|
1432
|
-
return getEndOfDay(updateFormatted(ts));
|
|
1736
|
+
export function getEndOfYear(timestamp, calendar = gregorianCalendar) {
|
|
1737
|
+
return getEndOfDay(getCalendarEndOfYear(timestamp, calendar));
|
|
1433
1738
|
}
|
|
1434
1739
|
/**
|
|
1435
1740
|
* Formats the date portion of a Timestamp object.
|
|
@@ -1483,11 +1788,12 @@ export function getDateTime(timestamp) {
|
|
|
1483
1788
|
* @param {function} [mover=nextDay] The mover function to use (ie: {nextDay} or {prevDay}).
|
|
1484
1789
|
* @param {number} [days=1] The number of days to move.
|
|
1485
1790
|
* @param {number[]} [allowedWeekdays=[ 0, 1, 2, 3, 4, 5, 6 ]] An array of numbers representing the weekdays. ie: [0 = Sun, ..., 6 = Sat].
|
|
1791
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1486
1792
|
* @returns A new Timestamp
|
|
1487
1793
|
* @category ranges
|
|
1488
1794
|
*/
|
|
1489
|
-
export function moveRelativeDays(timestamp, mover = nextDay, days = 1, allowedWeekdays = [0, 1, 2, 3, 4, 5, 6]) {
|
|
1490
|
-
return relativeDays(timestamp, mover, days, allowedWeekdays);
|
|
1795
|
+
export function moveRelativeDays(timestamp, mover = nextDay, days = 1, allowedWeekdays = [0, 1, 2, 3, 4, 5, 6], calendar = gregorianCalendar) {
|
|
1796
|
+
return relativeDays(timestamp, mover, days, allowedWeekdays, calendar);
|
|
1491
1797
|
}
|
|
1492
1798
|
/**
|
|
1493
1799
|
* Moves the Timestamp the number of relative days
|
|
@@ -1495,16 +1801,17 @@ export function moveRelativeDays(timestamp, mover = nextDay, days = 1, allowedWe
|
|
|
1495
1801
|
* @param {function} [mover=nextDay] The mover function to use (ie: {nextDay} or {prevDay}).
|
|
1496
1802
|
* @param {number} [days=1] The number of days to move.
|
|
1497
1803
|
* @param {number[]} [allowedWeekdays=[ 0, 1, 2, 3, 4, 5, 6 ]] An array of numbers representing the weekdays. ie: [0 = Sun, ..., 6 = Sat].
|
|
1804
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1498
1805
|
* @returns A new Timestamp
|
|
1499
1806
|
* @category ranges
|
|
1500
1807
|
*/
|
|
1501
|
-
export function relativeDays(timestamp, mover = nextDay, days = 1, allowedWeekdays = [0, 1, 2, 3, 4, 5, 6]) {
|
|
1808
|
+
export function relativeDays(timestamp, mover = nextDay, days = 1, allowedWeekdays = [0, 1, 2, 3, 4, 5, 6], calendar = gregorianCalendar) {
|
|
1502
1809
|
let ts = copyTimestamp(timestamp);
|
|
1503
1810
|
if (!allowedWeekdays.includes(Number(ts.weekday)) && ts.weekday === 0 && mover === nextDay) {
|
|
1504
1811
|
++days;
|
|
1505
1812
|
}
|
|
1506
1813
|
while (--days >= 0) {
|
|
1507
|
-
ts = mover(ts);
|
|
1814
|
+
ts = mover(ts, calendar);
|
|
1508
1815
|
if (allowedWeekdays.length < 7 && !allowedWeekdays.includes(Number(ts.weekday))) {
|
|
1509
1816
|
++days;
|
|
1510
1817
|
}
|
|
@@ -1517,13 +1824,14 @@ export function relativeDays(timestamp, mover = nextDay, days = 1, allowedWeekda
|
|
|
1517
1824
|
* @param {number} weekday The weekday number (Sun = 0, ..., Sat = 6)
|
|
1518
1825
|
* @param {function} [mover=nextDay] The function to use ({prevDay} or {nextDay}).
|
|
1519
1826
|
* @param {number} [maxDays=6] The number of days to look forward or back.
|
|
1827
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1520
1828
|
* @returns A new Timestamp
|
|
1521
1829
|
* @category ranges
|
|
1522
1830
|
*/
|
|
1523
|
-
export function findWeekday(timestamp, weekday, mover = nextDay, maxDays = 6) {
|
|
1831
|
+
export function findWeekday(timestamp, weekday, mover = nextDay, maxDays = 6, calendar = gregorianCalendar) {
|
|
1524
1832
|
let ts = copyTimestamp(timestamp);
|
|
1525
1833
|
while (ts.weekday !== weekday && --maxDays >= 0)
|
|
1526
|
-
ts = mover(ts);
|
|
1834
|
+
ts = mover(ts, calendar);
|
|
1527
1835
|
return ts;
|
|
1528
1836
|
}
|
|
1529
1837
|
/**
|
|
@@ -1542,10 +1850,22 @@ export function findWeekday(timestamp, weekday, mover = nextDay, maxDays = 6) {
|
|
|
1542
1850
|
* @param {DisabledDays} [disabledDays] Specific dates or date ranges to mark disabled.
|
|
1543
1851
|
* @param {number} [max=42] Maximum number of days to return.
|
|
1544
1852
|
* @param {number} [min=0] Minimum number of days to return.
|
|
1853
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1545
1854
|
* @returns {Timestamp[]} Timestamp days.
|
|
1546
1855
|
* @category ranges
|
|
1547
1856
|
*/
|
|
1548
|
-
export function createDayList(start, end, now, weekdays = [0, 1, 2, 3, 4, 5, 6], disabledBefore = undefined, disabledAfter = undefined, disabledWeekdays = [], disabledDays = [], max = 42, min = 0) {
|
|
1857
|
+
export function createDayList(start, end, now, weekdays = [0, 1, 2, 3, 4, 5, 6], disabledBefore = undefined, disabledAfter = undefined, disabledWeekdays = [], disabledDays = [], max = 42, min = 0, calendar = gregorianCalendar) {
|
|
1858
|
+
if (calendar !== gregorianCalendar) {
|
|
1859
|
+
return createCalendarDayList(start, end, now, calendar, {
|
|
1860
|
+
weekdays,
|
|
1861
|
+
disabledBefore,
|
|
1862
|
+
disabledAfter,
|
|
1863
|
+
disabledWeekdays,
|
|
1864
|
+
disabledDays,
|
|
1865
|
+
max,
|
|
1866
|
+
min,
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1549
1869
|
const begin = getDayIdentifier(start);
|
|
1550
1870
|
const stop = getDayIdentifier(end);
|
|
1551
1871
|
const days = [];
|
|
@@ -1663,7 +1983,7 @@ export function createNativeLocaleFormatterUTC(locale, cb) {
|
|
|
1663
1983
|
* `calendar` option. The helper supplies `timeZone: "UTC"` unless the caller
|
|
1664
1984
|
* provides a different timezone.
|
|
1665
1985
|
*
|
|
1666
|
-
* @param calendar Calendar
|
|
1986
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1667
1987
|
* @param locale The locale to use.
|
|
1668
1988
|
* @param cb Callback that returns Intl formatting options.
|
|
1669
1989
|
* @returns Function that formats a calendar timestamp.
|
|
@@ -1714,7 +2034,7 @@ export function makeDateUTC(timestamp) {
|
|
|
1714
2034
|
* can format the adapter date correctly when paired with a calendar option.
|
|
1715
2035
|
*
|
|
1716
2036
|
* @param timestamp Calendar timestamp object to convert.
|
|
1717
|
-
* @param calendar Calendar
|
|
2037
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1718
2038
|
* @returns JavaScript Date object built with `Date.UTC()`.
|
|
1719
2039
|
* @category calendar
|
|
1720
2040
|
*/
|
|
@@ -1736,7 +2056,7 @@ export function makeDateTime(timestamp) {
|
|
|
1736
2056
|
* Converts an adapter calendar timestamp date-time into a UTC JavaScript Date.
|
|
1737
2057
|
*
|
|
1738
2058
|
* @param timestamp Calendar timestamp object to convert.
|
|
1739
|
-
* @param calendar Calendar
|
|
2059
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
1740
2060
|
* @returns JavaScript Date object built with `Date.UTC()`.
|
|
1741
2061
|
* @category calendar
|
|
1742
2062
|
*/
|
|
@@ -2063,10 +2383,80 @@ export function isOverlappingDates(startTimestamp, endTimestamp, firstTimestamp,
|
|
|
2063
2383
|
* @param {number=} options.minute If positive, adds minutes. If negative, removes minutes.
|
|
2064
2384
|
* @param {number=} options.second If positive, adds seconds. If negative, removes seconds.
|
|
2065
2385
|
* @param {number=} options.millisecond If positive, adds milliseconds. If negative, removes milliseconds.
|
|
2386
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
2066
2387
|
* @returns {Timestamp} New normalized Timestamp object.
|
|
2067
2388
|
* @category arithmetic
|
|
2068
2389
|
*/
|
|
2069
|
-
|
|
2390
|
+
function addToCalendarDateTime(timestamp, options, calendar) {
|
|
2391
|
+
let ts = updateCalendarFormatted(timestamp, calendar);
|
|
2392
|
+
if (options.year)
|
|
2393
|
+
ts = addCalendarYears(ts, options.year, calendar);
|
|
2394
|
+
if (options.month)
|
|
2395
|
+
ts = addCalendarMonths(ts, options.month, calendar);
|
|
2396
|
+
if (options.day)
|
|
2397
|
+
ts = addCalendarDays(ts, options.day, calendar);
|
|
2398
|
+
const hasTimeOffset = options.hour !== undefined ||
|
|
2399
|
+
options.minute !== undefined ||
|
|
2400
|
+
options.second !== undefined ||
|
|
2401
|
+
options.millisecond !== undefined;
|
|
2402
|
+
if (hasTimeOffset) {
|
|
2403
|
+
const totalMilliseconds = (ts.hour + (options.hour ?? 0)) * MILLISECONDS_IN_HOUR +
|
|
2404
|
+
(ts.minute + (options.minute ?? 0)) * MILLISECONDS_IN_MINUTE +
|
|
2405
|
+
((ts.second ?? 0) + (options.second ?? 0)) * MILLISECONDS_IN_SECOND +
|
|
2406
|
+
((ts.millisecond ?? 0) + (options.millisecond ?? 0));
|
|
2407
|
+
const dayOffset = Math.floor(totalMilliseconds / MILLISECONDS_IN_DAY);
|
|
2408
|
+
let timeMilliseconds = totalMilliseconds % MILLISECONDS_IN_DAY;
|
|
2409
|
+
if (timeMilliseconds < 0) {
|
|
2410
|
+
timeMilliseconds += MILLISECONDS_IN_DAY;
|
|
2411
|
+
}
|
|
2412
|
+
if (dayOffset !== 0) {
|
|
2413
|
+
ts = addCalendarDays(ts, dayOffset, calendar);
|
|
2414
|
+
}
|
|
2415
|
+
const next = cloneTimestamp(ts);
|
|
2416
|
+
next.hasTime = true;
|
|
2417
|
+
next.hour = Math.floor(timeMilliseconds / MILLISECONDS_IN_HOUR);
|
|
2418
|
+
timeMilliseconds %= MILLISECONDS_IN_HOUR;
|
|
2419
|
+
next.minute = Math.floor(timeMilliseconds / MILLISECONDS_IN_MINUTE);
|
|
2420
|
+
timeMilliseconds %= MILLISECONDS_IN_MINUTE;
|
|
2421
|
+
next.second = Math.floor(timeMilliseconds / MILLISECONDS_IN_SECOND);
|
|
2422
|
+
next.millisecond = timeMilliseconds % MILLISECONDS_IN_SECOND;
|
|
2423
|
+
if (next.second === 0 && timestamp.second === undefined && options.second === undefined) {
|
|
2424
|
+
delete next.second;
|
|
2425
|
+
}
|
|
2426
|
+
if (next.millisecond === 0 &&
|
|
2427
|
+
timestamp.millisecond === undefined &&
|
|
2428
|
+
options.millisecond === undefined) {
|
|
2429
|
+
delete next.millisecond;
|
|
2430
|
+
}
|
|
2431
|
+
ts = next;
|
|
2432
|
+
}
|
|
2433
|
+
return updateCalendarFormatted(ts, calendar);
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Adds or subtracts date/time units from a timestamp.
|
|
2437
|
+
*
|
|
2438
|
+
* This function returns a new frozen Timestamp; it does not mutate the
|
|
2439
|
+
* timestamp passed in. Gregorian dates are normalized through JavaScript Date
|
|
2440
|
+
* rules. Adapter-native dates use the supplied calendar system for year,
|
|
2441
|
+
* month, and day math.
|
|
2442
|
+
*
|
|
2443
|
+
* @param {Timestamp} timestamp Timestamp object to offset.
|
|
2444
|
+
* @param {Object} options Date/time units to add or subtract.
|
|
2445
|
+
* @param {number=} options.year If positive, adds years. If negative, removes years.
|
|
2446
|
+
* @param {number=} options.month If positive, adds months. If negative, removes month.
|
|
2447
|
+
* @param {number=} options.day If positive, adds days. If negative, removes days.
|
|
2448
|
+
* @param {number=} options.hour If positive, adds hours. If negative, removes hours.
|
|
2449
|
+
* @param {number=} options.minute If positive, adds minutes. If negative, removes minutes.
|
|
2450
|
+
* @param {number=} options.second If positive, adds seconds. If negative, removes seconds.
|
|
2451
|
+
* @param {number=} options.millisecond If positive, adds milliseconds. If negative, removes milliseconds.
|
|
2452
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
2453
|
+
* @returns {Timestamp} New normalized Timestamp object.
|
|
2454
|
+
* @category arithmetic
|
|
2455
|
+
*/
|
|
2456
|
+
export function addToDate(timestamp, options, calendar = gregorianCalendar) {
|
|
2457
|
+
if (calendar !== gregorianCalendar) {
|
|
2458
|
+
return addToCalendarDateTime(timestamp, options, calendar);
|
|
2459
|
+
}
|
|
2070
2460
|
const ts = cloneTimestamp(timestamp);
|
|
2071
2461
|
if (options.year)
|
|
2072
2462
|
ts.year += options.year;
|
|
@@ -2105,10 +2495,14 @@ export function addToDate(timestamp, options) {
|
|
|
2105
2495
|
* @param {number=} options.minute If positive, adds minutes. If negative, removes minutes.
|
|
2106
2496
|
* @param {number=} options.second If positive, adds seconds. If negative, removes seconds.
|
|
2107
2497
|
* @param {number=} options.millisecond If positive, adds milliseconds. If negative, removes milliseconds.
|
|
2498
|
+
* @param {CalendarSystem=} calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
2108
2499
|
* @returns {Timestamp} New normalized Timestamp object.
|
|
2109
2500
|
* @category arithmetic
|
|
2110
2501
|
*/
|
|
2111
|
-
export function addToDateClamped(timestamp, options) {
|
|
2502
|
+
export function addToDateClamped(timestamp, options, calendar = gregorianCalendar) {
|
|
2503
|
+
if (calendar !== gregorianCalendar) {
|
|
2504
|
+
return addToCalendarDateTime(timestamp, options, calendar);
|
|
2505
|
+
}
|
|
2112
2506
|
const ts = cloneTimestamp(timestamp);
|
|
2113
2507
|
if (options.year || options.month) {
|
|
2114
2508
|
const target = normalizeYearMonth(ts.year + (options.year ?? 0), ts.month + (options.month ?? 0));
|
|
@@ -2456,6 +2850,61 @@ export function getMonthFormatter() {
|
|
|
2456
2850
|
}
|
|
2457
2851
|
return monthFormatter;
|
|
2458
2852
|
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Returns a function that formats one-based calendar adapter month numbers.
|
|
2855
|
+
*
|
|
2856
|
+
* This is the calendar-aware counterpart to getMonthFormatter(). It converts
|
|
2857
|
+
* adapter fields through the adapter's epoch-day mapping, then asks Intl to
|
|
2858
|
+
* format the equivalent Gregorian Date with the adapter's Intl calendar id
|
|
2859
|
+
* when one is available.
|
|
2860
|
+
*
|
|
2861
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
2862
|
+
* @returns Function that formats one-based month numbers for the adapter.
|
|
2863
|
+
* @category calendar
|
|
2864
|
+
*/
|
|
2865
|
+
export function getCalendarMonthFormatter(calendar = gregorianCalendar) {
|
|
2866
|
+
const options = {
|
|
2867
|
+
long: { timeZone: 'UTC', month: 'long' },
|
|
2868
|
+
short: { timeZone: 'UTC', month: 'short' },
|
|
2869
|
+
narrow: { timeZone: 'UTC', month: 'narrow' },
|
|
2870
|
+
};
|
|
2871
|
+
const fallbackFormatter = (month) => Number.isFinite(month) && month >= 1 ? `Month ${month}` : '';
|
|
2872
|
+
if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') {
|
|
2873
|
+
return fallbackFormatter;
|
|
2874
|
+
}
|
|
2875
|
+
return (month, type = 'long', locale, year = 1) => {
|
|
2876
|
+
const calendarMonth = Math.trunc(month);
|
|
2877
|
+
const calendarYear = Math.trunc(year);
|
|
2878
|
+
const date = {
|
|
2879
|
+
year: calendarYear,
|
|
2880
|
+
month: calendarMonth,
|
|
2881
|
+
day: 1,
|
|
2882
|
+
};
|
|
2883
|
+
if (Number.isFinite(calendarMonth) === false ||
|
|
2884
|
+
Number.isFinite(calendarYear) === false ||
|
|
2885
|
+
isValidCalendarDate(date, calendar) === false) {
|
|
2886
|
+
return '';
|
|
2887
|
+
}
|
|
2888
|
+
try {
|
|
2889
|
+
const resolvedOptions = resolveIntlNameFormat(options, type);
|
|
2890
|
+
const formatterOptions = calendar.intlCalendar === undefined || resolvedOptions.calendar !== undefined
|
|
2891
|
+
? resolvedOptions
|
|
2892
|
+
: {
|
|
2893
|
+
...resolvedOptions,
|
|
2894
|
+
calendar: calendar.intlCalendar,
|
|
2895
|
+
};
|
|
2896
|
+
const gregorianDate = gregorianCalendar.fromEpochDay(calendar.toEpochDay(date));
|
|
2897
|
+
const nativeDate = new Date(Date.UTC(gregorianDate.year, gregorianDate.month - 1, gregorianDate.day));
|
|
2898
|
+
return new Intl.DateTimeFormat(locale || undefined, formatterOptions).format(nativeDate);
|
|
2899
|
+
}
|
|
2900
|
+
catch (e) {
|
|
2901
|
+
if (e instanceof Error) {
|
|
2902
|
+
console.error(`Intl.DateTimeFormat: ${e.message} -> calendar month: ${calendarMonth}`);
|
|
2903
|
+
}
|
|
2904
|
+
return fallbackFormatter(calendarMonth);
|
|
2905
|
+
}
|
|
2906
|
+
};
|
|
2907
|
+
}
|
|
2459
2908
|
/**
|
|
2460
2909
|
* Retrieves localized month names.
|
|
2461
2910
|
*
|
|
@@ -2468,4 +2917,22 @@ export function getMonthNames(type, locale) {
|
|
|
2468
2917
|
const monthFormatter = getMonthFormatter();
|
|
2469
2918
|
return [...Array(12).keys()].map((month) => monthFormatter(month, type, locale));
|
|
2470
2919
|
}
|
|
2920
|
+
/**
|
|
2921
|
+
* Retrieves localized month names for a calendar adapter.
|
|
2922
|
+
*
|
|
2923
|
+
* Month numbers are generated from `1` through `calendar.monthsInYear(year)`.
|
|
2924
|
+
* Pass a year when the calendar can have leap months or year-specific month
|
|
2925
|
+
* naming rules.
|
|
2926
|
+
*
|
|
2927
|
+
* @param calendar Calendar system to use. Defaults to Gregorian; pass an adapter such as islamicCivilCalendar for native calendar fields.
|
|
2928
|
+
* @param type Format type: `narrow`, `short`, or `long`.
|
|
2929
|
+
* @param locale Locale to use for formatting, such as `en-US`.
|
|
2930
|
+
* @param year Calendar year to sample. Defaults to `1`.
|
|
2931
|
+
* @returns Localized month names in calendar-native order.
|
|
2932
|
+
* @category calendar
|
|
2933
|
+
*/
|
|
2934
|
+
export function getCalendarMonthNames(calendar = gregorianCalendar, type = 'long', locale, year = 1) {
|
|
2935
|
+
const monthFormatter = getCalendarMonthFormatter(calendar);
|
|
2936
|
+
return [...Array(calendar.monthsInYear(year)).keys()].map((month) => monthFormatter(month + 1, type, locale, year));
|
|
2937
|
+
}
|
|
2471
2938
|
//# sourceMappingURL=index.js.map
|