chronos-ts 2.0.3 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +253 -38
- package/dist/index.mjs +253 -38
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -630,6 +630,13 @@ declare class Chronos implements ChronosLike {
|
|
|
630
630
|
* ```
|
|
631
631
|
*/
|
|
632
632
|
add(amount: number | Duration, unit?: AnyTimeUnit): Chronos;
|
|
633
|
+
/**
|
|
634
|
+
* Add an amount of a single unit while respecting the instance timezone.
|
|
635
|
+
* Calendar units (day/week/month/quarter/year/…) preserve the wall-clock time
|
|
636
|
+
* in the zone (DST-safe); absolute units (hour/minute/second/millisecond) add a
|
|
637
|
+
* fixed offset to the instant. Day clamping mirrors the local-time path.
|
|
638
|
+
*/
|
|
639
|
+
private addInZone;
|
|
633
640
|
/**
|
|
634
641
|
* Subtract time from the date
|
|
635
642
|
*/
|
|
@@ -656,6 +663,14 @@ declare class Chronos implements ChronosLike {
|
|
|
656
663
|
* ```
|
|
657
664
|
*/
|
|
658
665
|
endOf(unit: AnyTimeUnit): Chronos;
|
|
666
|
+
/**
|
|
667
|
+
* Compute the start/end boundary of a unit in the instance timezone.
|
|
668
|
+
* The plain `startOf`/`endOf` helpers operate on local wall-clock fields of the
|
|
669
|
+
* underlying Date, which is wrong when an explicit timezone is attached. Here we
|
|
670
|
+
* read the wall-clock components in the target zone, snap them to the boundary,
|
|
671
|
+
* and rebuild the instant (dateFromComponents handles DST).
|
|
672
|
+
*/
|
|
673
|
+
private boundaryInZone;
|
|
659
674
|
addMilliseconds(amount: number): Chronos;
|
|
660
675
|
addSeconds(amount: number): Chronos;
|
|
661
676
|
addMinutes(amount: number): Chronos;
|
|
@@ -1216,7 +1231,6 @@ declare class ChronosPeriod implements Iterable<Chronos> {
|
|
|
1216
1231
|
private _recurrences;
|
|
1217
1232
|
private _options;
|
|
1218
1233
|
private _filters;
|
|
1219
|
-
private _current;
|
|
1220
1234
|
private _locale;
|
|
1221
1235
|
/**
|
|
1222
1236
|
* Create a new ChronosPeriod
|
|
@@ -1484,6 +1498,12 @@ declare class ChronosPeriod implements Iterable<Chronos> {
|
|
|
1484
1498
|
* Reduce dates to a single value
|
|
1485
1499
|
*/
|
|
1486
1500
|
reduce<T>(callback: (acc: T, date: Chronos, index: number) => T, initial: T): T;
|
|
1501
|
+
/**
|
|
1502
|
+
* Resolve the effective end of the period.
|
|
1503
|
+
* Returns null for a truly unbounded period (no end and no recurrence limit),
|
|
1504
|
+
* which avoids calling last() — that would iterate until the safety limit and throw.
|
|
1505
|
+
*/
|
|
1506
|
+
private _resolvedEnd;
|
|
1487
1507
|
/**
|
|
1488
1508
|
* Check if two periods overlap
|
|
1489
1509
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -630,6 +630,13 @@ declare class Chronos implements ChronosLike {
|
|
|
630
630
|
* ```
|
|
631
631
|
*/
|
|
632
632
|
add(amount: number | Duration, unit?: AnyTimeUnit): Chronos;
|
|
633
|
+
/**
|
|
634
|
+
* Add an amount of a single unit while respecting the instance timezone.
|
|
635
|
+
* Calendar units (day/week/month/quarter/year/…) preserve the wall-clock time
|
|
636
|
+
* in the zone (DST-safe); absolute units (hour/minute/second/millisecond) add a
|
|
637
|
+
* fixed offset to the instant. Day clamping mirrors the local-time path.
|
|
638
|
+
*/
|
|
639
|
+
private addInZone;
|
|
633
640
|
/**
|
|
634
641
|
* Subtract time from the date
|
|
635
642
|
*/
|
|
@@ -656,6 +663,14 @@ declare class Chronos implements ChronosLike {
|
|
|
656
663
|
* ```
|
|
657
664
|
*/
|
|
658
665
|
endOf(unit: AnyTimeUnit): Chronos;
|
|
666
|
+
/**
|
|
667
|
+
* Compute the start/end boundary of a unit in the instance timezone.
|
|
668
|
+
* The plain `startOf`/`endOf` helpers operate on local wall-clock fields of the
|
|
669
|
+
* underlying Date, which is wrong when an explicit timezone is attached. Here we
|
|
670
|
+
* read the wall-clock components in the target zone, snap them to the boundary,
|
|
671
|
+
* and rebuild the instant (dateFromComponents handles DST).
|
|
672
|
+
*/
|
|
673
|
+
private boundaryInZone;
|
|
659
674
|
addMilliseconds(amount: number): Chronos;
|
|
660
675
|
addSeconds(amount: number): Chronos;
|
|
661
676
|
addMinutes(amount: number): Chronos;
|
|
@@ -1216,7 +1231,6 @@ declare class ChronosPeriod implements Iterable<Chronos> {
|
|
|
1216
1231
|
private _recurrences;
|
|
1217
1232
|
private _options;
|
|
1218
1233
|
private _filters;
|
|
1219
|
-
private _current;
|
|
1220
1234
|
private _locale;
|
|
1221
1235
|
/**
|
|
1222
1236
|
* Create a new ChronosPeriod
|
|
@@ -1484,6 +1498,12 @@ declare class ChronosPeriod implements Iterable<Chronos> {
|
|
|
1484
1498
|
* Reduce dates to a single value
|
|
1485
1499
|
*/
|
|
1486
1500
|
reduce<T>(callback: (acc: T, date: Chronos, index: number) => T, initial: T): T;
|
|
1501
|
+
/**
|
|
1502
|
+
* Resolve the effective end of the period.
|
|
1503
|
+
* Returns null for a truly unbounded period (no end and no recurrence limit),
|
|
1504
|
+
* which avoids calling last() — that would iterate until the safety limit and throw.
|
|
1505
|
+
*/
|
|
1506
|
+
private _resolvedEnd;
|
|
1487
1507
|
/**
|
|
1488
1508
|
* Check if two periods overlap
|
|
1489
1509
|
*/
|
package/dist/index.js
CHANGED
|
@@ -2017,18 +2017,14 @@ var Chronos = class _Chronos {
|
|
|
2017
2017
|
if (isValidDate(isoDate)) {
|
|
2018
2018
|
return isoDate;
|
|
2019
2019
|
}
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
const parsed = new Date(input);
|
|
2029
|
-
if (isValidDate(parsed)) {
|
|
2030
|
-
return parsed;
|
|
2031
|
-
}
|
|
2020
|
+
const dmy = input.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
|
|
2021
|
+
if (dmy) {
|
|
2022
|
+
const day = parseInt(dmy[1], 10);
|
|
2023
|
+
const month = parseInt(dmy[2], 10);
|
|
2024
|
+
const year = parseInt(dmy[3], 10);
|
|
2025
|
+
const parsed = new Date(year, month - 1, day);
|
|
2026
|
+
if (isValidDate(parsed) && parsed.getMonth() === month - 1) {
|
|
2027
|
+
return parsed;
|
|
2032
2028
|
}
|
|
2033
2029
|
}
|
|
2034
2030
|
throw new Error(`Unable to parse date: ${input}`);
|
|
@@ -2332,18 +2328,40 @@ var Chronos = class _Chronos {
|
|
|
2332
2328
|
}
|
|
2333
2329
|
/** Get the quarter (1-4) */
|
|
2334
2330
|
get quarter() {
|
|
2331
|
+
if (this._timezone) {
|
|
2332
|
+
const month = new ChronosTimezone(this._timezone).getComponents(
|
|
2333
|
+
this._date
|
|
2334
|
+
).month;
|
|
2335
|
+
return Math.floor((month - 1) / 3) + 1;
|
|
2336
|
+
}
|
|
2335
2337
|
return getQuarter(this._date);
|
|
2336
2338
|
}
|
|
2337
2339
|
/** Get the day of year (1-366) */
|
|
2338
2340
|
get dayOfYear() {
|
|
2341
|
+
if (this._timezone) {
|
|
2342
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2343
|
+
let days = c.day;
|
|
2344
|
+
for (let m = 1; m < c.month; m++) {
|
|
2345
|
+
days += getDaysInMonth(c.year, m - 1);
|
|
2346
|
+
}
|
|
2347
|
+
return days;
|
|
2348
|
+
}
|
|
2339
2349
|
return getDayOfYear(this._date);
|
|
2340
2350
|
}
|
|
2341
2351
|
/** Get the ISO week number (1-53) */
|
|
2342
2352
|
get week() {
|
|
2353
|
+
if (this._timezone) {
|
|
2354
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2355
|
+
return getISOWeek(new Date(c.year, c.month - 1, c.day));
|
|
2356
|
+
}
|
|
2343
2357
|
return getISOWeek(this._date);
|
|
2344
2358
|
}
|
|
2345
2359
|
/** Get the ISO week year */
|
|
2346
2360
|
get weekYear() {
|
|
2361
|
+
if (this._timezone) {
|
|
2362
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2363
|
+
return getISOWeekYear(new Date(c.year, c.month - 1, c.day));
|
|
2364
|
+
}
|
|
2347
2365
|
return getISOWeekYear(this._date);
|
|
2348
2366
|
}
|
|
2349
2367
|
/** Get the number of days in the current month */
|
|
@@ -2364,6 +2382,9 @@ var Chronos = class _Chronos {
|
|
|
2364
2382
|
}
|
|
2365
2383
|
/** Get the timezone offset in minutes */
|
|
2366
2384
|
get offset() {
|
|
2385
|
+
if (this._timezone) {
|
|
2386
|
+
return -new ChronosTimezone(this._timezone).getOffsetMinutes(this._date);
|
|
2387
|
+
}
|
|
2367
2388
|
return this._date.getTimezoneOffset();
|
|
2368
2389
|
}
|
|
2369
2390
|
/** Get the timezone offset as string (+05:30) */
|
|
@@ -2475,9 +2496,82 @@ var Chronos = class _Chronos {
|
|
|
2475
2496
|
throw new Error("Unit is required when amount is a number");
|
|
2476
2497
|
}
|
|
2477
2498
|
const normalizedUnit = normalizeUnit(unit);
|
|
2499
|
+
if (this._timezone) {
|
|
2500
|
+
return this.addInZone(amount, normalizedUnit);
|
|
2501
|
+
}
|
|
2478
2502
|
const newDate = addUnits(this._date, amount, normalizedUnit);
|
|
2479
2503
|
return new _Chronos(newDate, this._timezone);
|
|
2480
2504
|
}
|
|
2505
|
+
/**
|
|
2506
|
+
* Add an amount of a single unit while respecting the instance timezone.
|
|
2507
|
+
* Calendar units (day/week/month/quarter/year/…) preserve the wall-clock time
|
|
2508
|
+
* in the zone (DST-safe); absolute units (hour/minute/second/millisecond) add a
|
|
2509
|
+
* fixed offset to the instant. Day clamping mirrors the local-time path.
|
|
2510
|
+
*/
|
|
2511
|
+
addInZone(amount, unit) {
|
|
2512
|
+
const absoluteMs = {
|
|
2513
|
+
millisecond: 1,
|
|
2514
|
+
second: MILLISECONDS_PER_SECOND,
|
|
2515
|
+
minute: MILLISECONDS_PER_MINUTE,
|
|
2516
|
+
hour: MILLISECONDS_PER_HOUR
|
|
2517
|
+
};
|
|
2518
|
+
const perUnit = absoluteMs[unit];
|
|
2519
|
+
if (perUnit !== void 0) {
|
|
2520
|
+
const newDate = new Date(this._date.getTime() + amount * perUnit);
|
|
2521
|
+
return new _Chronos(newDate, this._timezone);
|
|
2522
|
+
}
|
|
2523
|
+
const tz = new ChronosTimezone(this._timezone);
|
|
2524
|
+
const c = tz.getComponents(this._date);
|
|
2525
|
+
let year = c.year;
|
|
2526
|
+
let month = c.month;
|
|
2527
|
+
let day = c.day;
|
|
2528
|
+
const calendarUnit = unit === "month" || unit === "quarter" || unit === "year" || unit === "decade" || unit === "century" || unit === "millennium";
|
|
2529
|
+
switch (unit) {
|
|
2530
|
+
case "day":
|
|
2531
|
+
day += amount;
|
|
2532
|
+
break;
|
|
2533
|
+
case "week":
|
|
2534
|
+
day += amount * 7;
|
|
2535
|
+
break;
|
|
2536
|
+
case "month":
|
|
2537
|
+
month += amount;
|
|
2538
|
+
break;
|
|
2539
|
+
case "quarter":
|
|
2540
|
+
month += amount * 3;
|
|
2541
|
+
break;
|
|
2542
|
+
case "year":
|
|
2543
|
+
year += amount;
|
|
2544
|
+
break;
|
|
2545
|
+
case "decade":
|
|
2546
|
+
year += amount * 10;
|
|
2547
|
+
break;
|
|
2548
|
+
case "century":
|
|
2549
|
+
year += amount * 100;
|
|
2550
|
+
break;
|
|
2551
|
+
case "millennium":
|
|
2552
|
+
year += amount * 1e3;
|
|
2553
|
+
break;
|
|
2554
|
+
}
|
|
2555
|
+
year += Math.floor((month - 1) / 12);
|
|
2556
|
+
month = ((month - 1) % 12 + 12) % 12 + 1;
|
|
2557
|
+
if (calendarUnit) {
|
|
2558
|
+
const maxDay = getDaysInMonth(year, month - 1);
|
|
2559
|
+
if (day > maxDay) day = maxDay;
|
|
2560
|
+
}
|
|
2561
|
+
const date = _Chronos.dateFromComponents(
|
|
2562
|
+
{
|
|
2563
|
+
year,
|
|
2564
|
+
month,
|
|
2565
|
+
day,
|
|
2566
|
+
hour: c.hour,
|
|
2567
|
+
minute: c.minute,
|
|
2568
|
+
second: c.second,
|
|
2569
|
+
millisecond: this._date.getMilliseconds()
|
|
2570
|
+
},
|
|
2571
|
+
this._timezone
|
|
2572
|
+
);
|
|
2573
|
+
return new _Chronos(date, this._timezone);
|
|
2574
|
+
}
|
|
2481
2575
|
/**
|
|
2482
2576
|
* Subtract time from the date
|
|
2483
2577
|
*/
|
|
@@ -2505,6 +2599,9 @@ var Chronos = class _Chronos {
|
|
|
2505
2599
|
*/
|
|
2506
2600
|
startOf(unit) {
|
|
2507
2601
|
const normalizedUnit = normalizeUnit(unit);
|
|
2602
|
+
if (this._timezone) {
|
|
2603
|
+
return this.boundaryInZone(normalizedUnit, false);
|
|
2604
|
+
}
|
|
2508
2605
|
const newDate = startOf(this._date, normalizedUnit);
|
|
2509
2606
|
return new _Chronos(newDate, this._timezone);
|
|
2510
2607
|
}
|
|
@@ -2520,9 +2617,96 @@ var Chronos = class _Chronos {
|
|
|
2520
2617
|
*/
|
|
2521
2618
|
endOf(unit) {
|
|
2522
2619
|
const normalizedUnit = normalizeUnit(unit);
|
|
2620
|
+
if (this._timezone) {
|
|
2621
|
+
return this.boundaryInZone(normalizedUnit, true);
|
|
2622
|
+
}
|
|
2523
2623
|
const newDate = endOf(this._date, normalizedUnit);
|
|
2524
2624
|
return new _Chronos(newDate, this._timezone);
|
|
2525
2625
|
}
|
|
2626
|
+
/**
|
|
2627
|
+
* Compute the start/end boundary of a unit in the instance timezone.
|
|
2628
|
+
* The plain `startOf`/`endOf` helpers operate on local wall-clock fields of the
|
|
2629
|
+
* underlying Date, which is wrong when an explicit timezone is attached. Here we
|
|
2630
|
+
* read the wall-clock components in the target zone, snap them to the boundary,
|
|
2631
|
+
* and rebuild the instant (dateFromComponents handles DST).
|
|
2632
|
+
*/
|
|
2633
|
+
boundaryInZone(unit, end) {
|
|
2634
|
+
if (unit === "millisecond") {
|
|
2635
|
+
return this.clone();
|
|
2636
|
+
}
|
|
2637
|
+
const tz = new ChronosTimezone(this._timezone);
|
|
2638
|
+
const c = tz.getComponents(this._date);
|
|
2639
|
+
const comp = {
|
|
2640
|
+
year: c.year,
|
|
2641
|
+
month: c.month,
|
|
2642
|
+
day: c.day,
|
|
2643
|
+
hour: c.hour,
|
|
2644
|
+
minute: c.minute,
|
|
2645
|
+
second: c.second,
|
|
2646
|
+
millisecond: this._date.getMilliseconds()
|
|
2647
|
+
};
|
|
2648
|
+
const resetTime = () => {
|
|
2649
|
+
comp.hour = end ? 23 : 0;
|
|
2650
|
+
comp.minute = end ? 59 : 0;
|
|
2651
|
+
comp.second = end ? 59 : 0;
|
|
2652
|
+
comp.millisecond = end ? 999 : 0;
|
|
2653
|
+
};
|
|
2654
|
+
switch (unit) {
|
|
2655
|
+
case "second":
|
|
2656
|
+
comp.millisecond = end ? 999 : 0;
|
|
2657
|
+
break;
|
|
2658
|
+
case "minute":
|
|
2659
|
+
comp.second = end ? 59 : 0;
|
|
2660
|
+
comp.millisecond = end ? 999 : 0;
|
|
2661
|
+
break;
|
|
2662
|
+
case "hour":
|
|
2663
|
+
comp.minute = end ? 59 : 0;
|
|
2664
|
+
comp.second = end ? 59 : 0;
|
|
2665
|
+
comp.millisecond = end ? 999 : 0;
|
|
2666
|
+
break;
|
|
2667
|
+
case "day":
|
|
2668
|
+
resetTime();
|
|
2669
|
+
break;
|
|
2670
|
+
case "week":
|
|
2671
|
+
resetTime();
|
|
2672
|
+
comp.day = c.day + (end ? 6 - c.dayOfWeek : -c.dayOfWeek);
|
|
2673
|
+
break;
|
|
2674
|
+
case "month":
|
|
2675
|
+
resetTime();
|
|
2676
|
+
comp.day = end ? getDaysInMonth(c.year, c.month - 1) : 1;
|
|
2677
|
+
break;
|
|
2678
|
+
case "quarter": {
|
|
2679
|
+
resetTime();
|
|
2680
|
+
const qStartMonth = Math.floor((c.month - 1) / 3) * 3 + 1;
|
|
2681
|
+
if (end) {
|
|
2682
|
+
comp.month = qStartMonth + 2;
|
|
2683
|
+
comp.day = getDaysInMonth(c.year, comp.month - 1);
|
|
2684
|
+
} else {
|
|
2685
|
+
comp.month = qStartMonth;
|
|
2686
|
+
comp.day = 1;
|
|
2687
|
+
}
|
|
2688
|
+
break;
|
|
2689
|
+
}
|
|
2690
|
+
case "year":
|
|
2691
|
+
resetTime();
|
|
2692
|
+
comp.month = end ? 12 : 1;
|
|
2693
|
+
comp.day = end ? 31 : 1;
|
|
2694
|
+
break;
|
|
2695
|
+
case "decade":
|
|
2696
|
+
case "century":
|
|
2697
|
+
case "millennium": {
|
|
2698
|
+
resetTime();
|
|
2699
|
+
comp.month = end ? 12 : 1;
|
|
2700
|
+
comp.day = end ? 31 : 1;
|
|
2701
|
+
const span = unit === "decade" ? 10 : unit === "century" ? 100 : 1e3;
|
|
2702
|
+
const base = Math.floor(c.year / span) * span;
|
|
2703
|
+
comp.year = end ? base + span - 1 : base;
|
|
2704
|
+
break;
|
|
2705
|
+
}
|
|
2706
|
+
}
|
|
2707
|
+
const date = _Chronos.dateFromComponents(comp, this._timezone);
|
|
2708
|
+
return new _Chronos(date, this._timezone);
|
|
2709
|
+
}
|
|
2526
2710
|
// ============================================================================
|
|
2527
2711
|
// Convenience Add/Subtract Methods
|
|
2528
2712
|
// ============================================================================
|
|
@@ -2717,6 +2901,12 @@ var Chronos = class _Chronos {
|
|
|
2717
2901
|
return diffMs / MILLISECONDS_PER_DAY;
|
|
2718
2902
|
case "week":
|
|
2719
2903
|
return diffMs / (MILLISECONDS_PER_DAY * 7);
|
|
2904
|
+
case "month":
|
|
2905
|
+
return diffMs / MILLISECONDS_PER_MONTH;
|
|
2906
|
+
case "quarter":
|
|
2907
|
+
return diffMs / (MILLISECONDS_PER_MONTH * 3);
|
|
2908
|
+
case "year":
|
|
2909
|
+
return diffMs / MILLISECONDS_PER_YEAR;
|
|
2720
2910
|
}
|
|
2721
2911
|
}
|
|
2722
2912
|
return diffInUnits(this._date, otherDate._date, normalizedUnit);
|
|
@@ -2774,12 +2964,12 @@ var Chronos = class _Chronos {
|
|
|
2774
2964
|
* Get relative time from another date
|
|
2775
2965
|
*/
|
|
2776
2966
|
from(other, options = {}) {
|
|
2777
|
-
var _a, _b;
|
|
2967
|
+
var _a, _b, _c;
|
|
2778
2968
|
const otherDate = _Chronos.parse(other);
|
|
2779
2969
|
const diffMs = this._date.getTime() - otherDate._date.getTime();
|
|
2780
2970
|
const absDiff = Math.abs(diffMs);
|
|
2781
2971
|
const isFuture = diffMs > 0;
|
|
2782
|
-
const { short
|
|
2972
|
+
const { short = false, absolute = false } = options;
|
|
2783
2973
|
const relative = this._locale.relativeTime;
|
|
2784
2974
|
let value;
|
|
2785
2975
|
let unit;
|
|
@@ -2805,10 +2995,26 @@ var Chronos = class _Chronos {
|
|
|
2805
2995
|
value = Math.round(absDiff / (MILLISECONDS_PER_DAY * 365));
|
|
2806
2996
|
unit = value === 1 ? "y" : "yy";
|
|
2807
2997
|
}
|
|
2808
|
-
const
|
|
2998
|
+
const shortUnits = {
|
|
2999
|
+
s: "s",
|
|
3000
|
+
ss: "s",
|
|
3001
|
+
m: "m",
|
|
3002
|
+
mm: "m",
|
|
3003
|
+
h: "h",
|
|
3004
|
+
hh: "h",
|
|
3005
|
+
d: "d",
|
|
3006
|
+
dd: "d",
|
|
3007
|
+
w: "w",
|
|
3008
|
+
ww: "w",
|
|
3009
|
+
M: "mo",
|
|
3010
|
+
MM: "mo",
|
|
3011
|
+
y: "y",
|
|
3012
|
+
yy: "y"
|
|
3013
|
+
};
|
|
3014
|
+
const relativeStr = short ? `${value}${(_a = shortUnits[unit]) != null ? _a : unit}` : (_c = (_b = relative[unit]) == null ? void 0 : _b.replace(
|
|
2809
3015
|
"%d",
|
|
2810
3016
|
String(value)
|
|
2811
|
-
)) != null ?
|
|
3017
|
+
)) != null ? _c : `${value} ${unit}`;
|
|
2812
3018
|
if (absolute) {
|
|
2813
3019
|
return relativeStr;
|
|
2814
3020
|
}
|
|
@@ -2887,7 +3093,7 @@ var Chronos = class _Chronos {
|
|
|
2887
3093
|
Z: () => this.offsetString,
|
|
2888
3094
|
ZZ: () => this.offsetString.replace(":", ""),
|
|
2889
3095
|
Q: () => String(this.quarter),
|
|
2890
|
-
Do: () =>
|
|
3096
|
+
Do: () => this._locale.ordinal(this.date),
|
|
2891
3097
|
W: () => String(this.week),
|
|
2892
3098
|
WW: () => padStart(this.week, 2),
|
|
2893
3099
|
X: () => String(this.unix),
|
|
@@ -3161,15 +3367,16 @@ var ChronosInterval = class _ChronosInterval {
|
|
|
3161
3367
|
// Constructor
|
|
3162
3368
|
// ============================================================================
|
|
3163
3369
|
constructor(duration = {}, inverted = false) {
|
|
3164
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
3370
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3165
3371
|
this._years = (_a = duration.years) != null ? _a : 0;
|
|
3166
3372
|
this._months = (_b = duration.months) != null ? _b : 0;
|
|
3167
3373
|
this._weeks = (_c = duration.weeks) != null ? _c : 0;
|
|
3168
3374
|
this._days = (_d = duration.days) != null ? _d : 0;
|
|
3169
3375
|
this._hours = (_e = duration.hours) != null ? _e : 0;
|
|
3170
3376
|
this._minutes = (_f = duration.minutes) != null ? _f : 0;
|
|
3171
|
-
|
|
3172
|
-
this.
|
|
3377
|
+
const totalSeconds = (_g = duration.seconds) != null ? _g : 0;
|
|
3378
|
+
this._seconds = Math.trunc(totalSeconds);
|
|
3379
|
+
this._milliseconds = (_h = duration.milliseconds) != null ? _h : Math.round((totalSeconds - this._seconds) * 1e3);
|
|
3173
3380
|
this._locale = getLocale("en");
|
|
3174
3381
|
this._inverted = inverted;
|
|
3175
3382
|
}
|
|
@@ -3858,7 +4065,6 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
3858
4065
|
immutable: (_c = options.immutable) != null ? _c : true
|
|
3859
4066
|
};
|
|
3860
4067
|
this._filters = [];
|
|
3861
|
-
this._current = 0;
|
|
3862
4068
|
this._locale = getLocale("en");
|
|
3863
4069
|
}
|
|
3864
4070
|
// ============================================================================
|
|
@@ -4468,13 +4674,24 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4468
4674
|
// ============================================================================
|
|
4469
4675
|
// Range Operations
|
|
4470
4676
|
// ============================================================================
|
|
4677
|
+
/**
|
|
4678
|
+
* Resolve the effective end of the period.
|
|
4679
|
+
* Returns null for a truly unbounded period (no end and no recurrence limit),
|
|
4680
|
+
* which avoids calling last() — that would iterate until the safety limit and throw.
|
|
4681
|
+
*/
|
|
4682
|
+
_resolvedEnd() {
|
|
4683
|
+
var _a;
|
|
4684
|
+
if (this.isUnbounded) {
|
|
4685
|
+
return null;
|
|
4686
|
+
}
|
|
4687
|
+
return (_a = this._end) != null ? _a : this.last();
|
|
4688
|
+
}
|
|
4471
4689
|
/**
|
|
4472
4690
|
* Check if two periods overlap
|
|
4473
4691
|
*/
|
|
4474
4692
|
overlaps(other) {
|
|
4475
|
-
|
|
4476
|
-
const
|
|
4477
|
-
const otherEnd = (_b = other._end) != null ? _b : other.last();
|
|
4693
|
+
const thisEnd = this._resolvedEnd();
|
|
4694
|
+
const otherEnd = other._resolvedEnd();
|
|
4478
4695
|
if (!thisEnd || !otherEnd) {
|
|
4479
4696
|
return true;
|
|
4480
4697
|
}
|
|
@@ -4484,13 +4701,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4484
4701
|
* Get the intersection of two periods
|
|
4485
4702
|
*/
|
|
4486
4703
|
intersect(other) {
|
|
4487
|
-
var _a, _b;
|
|
4488
4704
|
if (!this.overlaps(other)) {
|
|
4489
4705
|
return null;
|
|
4490
4706
|
}
|
|
4491
4707
|
const start = this._start.isAfter(other._start) ? this._start : other._start;
|
|
4492
|
-
const thisEnd =
|
|
4493
|
-
const otherEnd =
|
|
4708
|
+
const thisEnd = this._resolvedEnd();
|
|
4709
|
+
const otherEnd = other._resolvedEnd();
|
|
4494
4710
|
if (!thisEnd || !otherEnd) {
|
|
4495
4711
|
return new _ChronosPeriod(start, void 0, this._interval);
|
|
4496
4712
|
}
|
|
@@ -4501,13 +4717,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4501
4717
|
* Get the union of two periods
|
|
4502
4718
|
*/
|
|
4503
4719
|
union(other) {
|
|
4504
|
-
var _a, _b;
|
|
4505
4720
|
if (!this.overlaps(other) && !this._adjacentTo(other)) {
|
|
4506
4721
|
return null;
|
|
4507
4722
|
}
|
|
4508
4723
|
const start = this._start.isBefore(other._start) ? this._start : other._start;
|
|
4509
|
-
const thisEnd =
|
|
4510
|
-
const otherEnd =
|
|
4724
|
+
const thisEnd = this._resolvedEnd();
|
|
4725
|
+
const otherEnd = other._resolvedEnd();
|
|
4511
4726
|
if (!thisEnd || !otherEnd) {
|
|
4512
4727
|
return new _ChronosPeriod(start, void 0, this._interval);
|
|
4513
4728
|
}
|
|
@@ -4519,13 +4734,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4519
4734
|
* Returns the parts of this period that don't overlap with the other period
|
|
4520
4735
|
*/
|
|
4521
4736
|
diff(other) {
|
|
4522
|
-
var _a, _b;
|
|
4523
4737
|
if (!this.overlaps(other)) {
|
|
4524
4738
|
return [this.clone()];
|
|
4525
4739
|
}
|
|
4526
4740
|
const results = [];
|
|
4527
|
-
const thisEnd =
|
|
4528
|
-
const otherEnd =
|
|
4741
|
+
const thisEnd = this._resolvedEnd();
|
|
4742
|
+
const otherEnd = other._resolvedEnd();
|
|
4529
4743
|
if (this._start.isBefore(other._start)) {
|
|
4530
4744
|
results.push(
|
|
4531
4745
|
new _ChronosPeriod(this._start, other._start, this._interval)
|
|
@@ -4540,9 +4754,8 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4540
4754
|
* Check if this period is adjacent to another
|
|
4541
4755
|
*/
|
|
4542
4756
|
_adjacentTo(other) {
|
|
4543
|
-
|
|
4544
|
-
const
|
|
4545
|
-
const otherEnd = (_b = other._end) != null ? _b : other.last();
|
|
4757
|
+
const thisEnd = this._resolvedEnd();
|
|
4758
|
+
const otherEnd = other._resolvedEnd();
|
|
4546
4759
|
if (!thisEnd || !otherEnd) {
|
|
4547
4760
|
return false;
|
|
4548
4761
|
}
|
|
@@ -4634,11 +4847,13 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4634
4847
|
}
|
|
4635
4848
|
const chunks = [];
|
|
4636
4849
|
let current = this._start.clone();
|
|
4850
|
+
const subStep = splitInterval.total("days") >= 1 ? { days: 1 } : { milliseconds: 1 };
|
|
4637
4851
|
while (current.isSameOrBefore(this._end)) {
|
|
4638
|
-
const
|
|
4852
|
+
const nextStart = current.add(splitInterval.toDuration());
|
|
4853
|
+
const chunkEnd = nextStart.subtract(subStep);
|
|
4639
4854
|
const end = chunkEnd.isAfter(this._end) ? this._end : chunkEnd;
|
|
4640
4855
|
chunks.push(new _ChronosPeriod(current, end, this._interval));
|
|
4641
|
-
current =
|
|
4856
|
+
current = nextStart;
|
|
4642
4857
|
}
|
|
4643
4858
|
return chunks;
|
|
4644
4859
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -2013,18 +2013,14 @@ var Chronos = class _Chronos {
|
|
|
2013
2013
|
if (isValidDate(isoDate)) {
|
|
2014
2014
|
return isoDate;
|
|
2015
2015
|
}
|
|
2016
|
-
const
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
const parsed = new Date(input);
|
|
2025
|
-
if (isValidDate(parsed)) {
|
|
2026
|
-
return parsed;
|
|
2027
|
-
}
|
|
2016
|
+
const dmy = input.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
|
|
2017
|
+
if (dmy) {
|
|
2018
|
+
const day = parseInt(dmy[1], 10);
|
|
2019
|
+
const month = parseInt(dmy[2], 10);
|
|
2020
|
+
const year = parseInt(dmy[3], 10);
|
|
2021
|
+
const parsed = new Date(year, month - 1, day);
|
|
2022
|
+
if (isValidDate(parsed) && parsed.getMonth() === month - 1) {
|
|
2023
|
+
return parsed;
|
|
2028
2024
|
}
|
|
2029
2025
|
}
|
|
2030
2026
|
throw new Error(`Unable to parse date: ${input}`);
|
|
@@ -2328,18 +2324,40 @@ var Chronos = class _Chronos {
|
|
|
2328
2324
|
}
|
|
2329
2325
|
/** Get the quarter (1-4) */
|
|
2330
2326
|
get quarter() {
|
|
2327
|
+
if (this._timezone) {
|
|
2328
|
+
const month = new ChronosTimezone(this._timezone).getComponents(
|
|
2329
|
+
this._date
|
|
2330
|
+
).month;
|
|
2331
|
+
return Math.floor((month - 1) / 3) + 1;
|
|
2332
|
+
}
|
|
2331
2333
|
return getQuarter(this._date);
|
|
2332
2334
|
}
|
|
2333
2335
|
/** Get the day of year (1-366) */
|
|
2334
2336
|
get dayOfYear() {
|
|
2337
|
+
if (this._timezone) {
|
|
2338
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2339
|
+
let days = c.day;
|
|
2340
|
+
for (let m = 1; m < c.month; m++) {
|
|
2341
|
+
days += getDaysInMonth(c.year, m - 1);
|
|
2342
|
+
}
|
|
2343
|
+
return days;
|
|
2344
|
+
}
|
|
2335
2345
|
return getDayOfYear(this._date);
|
|
2336
2346
|
}
|
|
2337
2347
|
/** Get the ISO week number (1-53) */
|
|
2338
2348
|
get week() {
|
|
2349
|
+
if (this._timezone) {
|
|
2350
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2351
|
+
return getISOWeek(new Date(c.year, c.month - 1, c.day));
|
|
2352
|
+
}
|
|
2339
2353
|
return getISOWeek(this._date);
|
|
2340
2354
|
}
|
|
2341
2355
|
/** Get the ISO week year */
|
|
2342
2356
|
get weekYear() {
|
|
2357
|
+
if (this._timezone) {
|
|
2358
|
+
const c = new ChronosTimezone(this._timezone).getComponents(this._date);
|
|
2359
|
+
return getISOWeekYear(new Date(c.year, c.month - 1, c.day));
|
|
2360
|
+
}
|
|
2343
2361
|
return getISOWeekYear(this._date);
|
|
2344
2362
|
}
|
|
2345
2363
|
/** Get the number of days in the current month */
|
|
@@ -2360,6 +2378,9 @@ var Chronos = class _Chronos {
|
|
|
2360
2378
|
}
|
|
2361
2379
|
/** Get the timezone offset in minutes */
|
|
2362
2380
|
get offset() {
|
|
2381
|
+
if (this._timezone) {
|
|
2382
|
+
return -new ChronosTimezone(this._timezone).getOffsetMinutes(this._date);
|
|
2383
|
+
}
|
|
2363
2384
|
return this._date.getTimezoneOffset();
|
|
2364
2385
|
}
|
|
2365
2386
|
/** Get the timezone offset as string (+05:30) */
|
|
@@ -2471,9 +2492,82 @@ var Chronos = class _Chronos {
|
|
|
2471
2492
|
throw new Error("Unit is required when amount is a number");
|
|
2472
2493
|
}
|
|
2473
2494
|
const normalizedUnit = normalizeUnit(unit);
|
|
2495
|
+
if (this._timezone) {
|
|
2496
|
+
return this.addInZone(amount, normalizedUnit);
|
|
2497
|
+
}
|
|
2474
2498
|
const newDate = addUnits(this._date, amount, normalizedUnit);
|
|
2475
2499
|
return new _Chronos(newDate, this._timezone);
|
|
2476
2500
|
}
|
|
2501
|
+
/**
|
|
2502
|
+
* Add an amount of a single unit while respecting the instance timezone.
|
|
2503
|
+
* Calendar units (day/week/month/quarter/year/…) preserve the wall-clock time
|
|
2504
|
+
* in the zone (DST-safe); absolute units (hour/minute/second/millisecond) add a
|
|
2505
|
+
* fixed offset to the instant. Day clamping mirrors the local-time path.
|
|
2506
|
+
*/
|
|
2507
|
+
addInZone(amount, unit) {
|
|
2508
|
+
const absoluteMs = {
|
|
2509
|
+
millisecond: 1,
|
|
2510
|
+
second: MILLISECONDS_PER_SECOND,
|
|
2511
|
+
minute: MILLISECONDS_PER_MINUTE,
|
|
2512
|
+
hour: MILLISECONDS_PER_HOUR
|
|
2513
|
+
};
|
|
2514
|
+
const perUnit = absoluteMs[unit];
|
|
2515
|
+
if (perUnit !== void 0) {
|
|
2516
|
+
const newDate = new Date(this._date.getTime() + amount * perUnit);
|
|
2517
|
+
return new _Chronos(newDate, this._timezone);
|
|
2518
|
+
}
|
|
2519
|
+
const tz = new ChronosTimezone(this._timezone);
|
|
2520
|
+
const c = tz.getComponents(this._date);
|
|
2521
|
+
let year = c.year;
|
|
2522
|
+
let month = c.month;
|
|
2523
|
+
let day = c.day;
|
|
2524
|
+
const calendarUnit = unit === "month" || unit === "quarter" || unit === "year" || unit === "decade" || unit === "century" || unit === "millennium";
|
|
2525
|
+
switch (unit) {
|
|
2526
|
+
case "day":
|
|
2527
|
+
day += amount;
|
|
2528
|
+
break;
|
|
2529
|
+
case "week":
|
|
2530
|
+
day += amount * 7;
|
|
2531
|
+
break;
|
|
2532
|
+
case "month":
|
|
2533
|
+
month += amount;
|
|
2534
|
+
break;
|
|
2535
|
+
case "quarter":
|
|
2536
|
+
month += amount * 3;
|
|
2537
|
+
break;
|
|
2538
|
+
case "year":
|
|
2539
|
+
year += amount;
|
|
2540
|
+
break;
|
|
2541
|
+
case "decade":
|
|
2542
|
+
year += amount * 10;
|
|
2543
|
+
break;
|
|
2544
|
+
case "century":
|
|
2545
|
+
year += amount * 100;
|
|
2546
|
+
break;
|
|
2547
|
+
case "millennium":
|
|
2548
|
+
year += amount * 1e3;
|
|
2549
|
+
break;
|
|
2550
|
+
}
|
|
2551
|
+
year += Math.floor((month - 1) / 12);
|
|
2552
|
+
month = ((month - 1) % 12 + 12) % 12 + 1;
|
|
2553
|
+
if (calendarUnit) {
|
|
2554
|
+
const maxDay = getDaysInMonth(year, month - 1);
|
|
2555
|
+
if (day > maxDay) day = maxDay;
|
|
2556
|
+
}
|
|
2557
|
+
const date = _Chronos.dateFromComponents(
|
|
2558
|
+
{
|
|
2559
|
+
year,
|
|
2560
|
+
month,
|
|
2561
|
+
day,
|
|
2562
|
+
hour: c.hour,
|
|
2563
|
+
minute: c.minute,
|
|
2564
|
+
second: c.second,
|
|
2565
|
+
millisecond: this._date.getMilliseconds()
|
|
2566
|
+
},
|
|
2567
|
+
this._timezone
|
|
2568
|
+
);
|
|
2569
|
+
return new _Chronos(date, this._timezone);
|
|
2570
|
+
}
|
|
2477
2571
|
/**
|
|
2478
2572
|
* Subtract time from the date
|
|
2479
2573
|
*/
|
|
@@ -2501,6 +2595,9 @@ var Chronos = class _Chronos {
|
|
|
2501
2595
|
*/
|
|
2502
2596
|
startOf(unit) {
|
|
2503
2597
|
const normalizedUnit = normalizeUnit(unit);
|
|
2598
|
+
if (this._timezone) {
|
|
2599
|
+
return this.boundaryInZone(normalizedUnit, false);
|
|
2600
|
+
}
|
|
2504
2601
|
const newDate = startOf(this._date, normalizedUnit);
|
|
2505
2602
|
return new _Chronos(newDate, this._timezone);
|
|
2506
2603
|
}
|
|
@@ -2516,9 +2613,96 @@ var Chronos = class _Chronos {
|
|
|
2516
2613
|
*/
|
|
2517
2614
|
endOf(unit) {
|
|
2518
2615
|
const normalizedUnit = normalizeUnit(unit);
|
|
2616
|
+
if (this._timezone) {
|
|
2617
|
+
return this.boundaryInZone(normalizedUnit, true);
|
|
2618
|
+
}
|
|
2519
2619
|
const newDate = endOf(this._date, normalizedUnit);
|
|
2520
2620
|
return new _Chronos(newDate, this._timezone);
|
|
2521
2621
|
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Compute the start/end boundary of a unit in the instance timezone.
|
|
2624
|
+
* The plain `startOf`/`endOf` helpers operate on local wall-clock fields of the
|
|
2625
|
+
* underlying Date, which is wrong when an explicit timezone is attached. Here we
|
|
2626
|
+
* read the wall-clock components in the target zone, snap them to the boundary,
|
|
2627
|
+
* and rebuild the instant (dateFromComponents handles DST).
|
|
2628
|
+
*/
|
|
2629
|
+
boundaryInZone(unit, end) {
|
|
2630
|
+
if (unit === "millisecond") {
|
|
2631
|
+
return this.clone();
|
|
2632
|
+
}
|
|
2633
|
+
const tz = new ChronosTimezone(this._timezone);
|
|
2634
|
+
const c = tz.getComponents(this._date);
|
|
2635
|
+
const comp = {
|
|
2636
|
+
year: c.year,
|
|
2637
|
+
month: c.month,
|
|
2638
|
+
day: c.day,
|
|
2639
|
+
hour: c.hour,
|
|
2640
|
+
minute: c.minute,
|
|
2641
|
+
second: c.second,
|
|
2642
|
+
millisecond: this._date.getMilliseconds()
|
|
2643
|
+
};
|
|
2644
|
+
const resetTime = () => {
|
|
2645
|
+
comp.hour = end ? 23 : 0;
|
|
2646
|
+
comp.minute = end ? 59 : 0;
|
|
2647
|
+
comp.second = end ? 59 : 0;
|
|
2648
|
+
comp.millisecond = end ? 999 : 0;
|
|
2649
|
+
};
|
|
2650
|
+
switch (unit) {
|
|
2651
|
+
case "second":
|
|
2652
|
+
comp.millisecond = end ? 999 : 0;
|
|
2653
|
+
break;
|
|
2654
|
+
case "minute":
|
|
2655
|
+
comp.second = end ? 59 : 0;
|
|
2656
|
+
comp.millisecond = end ? 999 : 0;
|
|
2657
|
+
break;
|
|
2658
|
+
case "hour":
|
|
2659
|
+
comp.minute = end ? 59 : 0;
|
|
2660
|
+
comp.second = end ? 59 : 0;
|
|
2661
|
+
comp.millisecond = end ? 999 : 0;
|
|
2662
|
+
break;
|
|
2663
|
+
case "day":
|
|
2664
|
+
resetTime();
|
|
2665
|
+
break;
|
|
2666
|
+
case "week":
|
|
2667
|
+
resetTime();
|
|
2668
|
+
comp.day = c.day + (end ? 6 - c.dayOfWeek : -c.dayOfWeek);
|
|
2669
|
+
break;
|
|
2670
|
+
case "month":
|
|
2671
|
+
resetTime();
|
|
2672
|
+
comp.day = end ? getDaysInMonth(c.year, c.month - 1) : 1;
|
|
2673
|
+
break;
|
|
2674
|
+
case "quarter": {
|
|
2675
|
+
resetTime();
|
|
2676
|
+
const qStartMonth = Math.floor((c.month - 1) / 3) * 3 + 1;
|
|
2677
|
+
if (end) {
|
|
2678
|
+
comp.month = qStartMonth + 2;
|
|
2679
|
+
comp.day = getDaysInMonth(c.year, comp.month - 1);
|
|
2680
|
+
} else {
|
|
2681
|
+
comp.month = qStartMonth;
|
|
2682
|
+
comp.day = 1;
|
|
2683
|
+
}
|
|
2684
|
+
break;
|
|
2685
|
+
}
|
|
2686
|
+
case "year":
|
|
2687
|
+
resetTime();
|
|
2688
|
+
comp.month = end ? 12 : 1;
|
|
2689
|
+
comp.day = end ? 31 : 1;
|
|
2690
|
+
break;
|
|
2691
|
+
case "decade":
|
|
2692
|
+
case "century":
|
|
2693
|
+
case "millennium": {
|
|
2694
|
+
resetTime();
|
|
2695
|
+
comp.month = end ? 12 : 1;
|
|
2696
|
+
comp.day = end ? 31 : 1;
|
|
2697
|
+
const span = unit === "decade" ? 10 : unit === "century" ? 100 : 1e3;
|
|
2698
|
+
const base = Math.floor(c.year / span) * span;
|
|
2699
|
+
comp.year = end ? base + span - 1 : base;
|
|
2700
|
+
break;
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
const date = _Chronos.dateFromComponents(comp, this._timezone);
|
|
2704
|
+
return new _Chronos(date, this._timezone);
|
|
2705
|
+
}
|
|
2522
2706
|
// ============================================================================
|
|
2523
2707
|
// Convenience Add/Subtract Methods
|
|
2524
2708
|
// ============================================================================
|
|
@@ -2713,6 +2897,12 @@ var Chronos = class _Chronos {
|
|
|
2713
2897
|
return diffMs / MILLISECONDS_PER_DAY;
|
|
2714
2898
|
case "week":
|
|
2715
2899
|
return diffMs / (MILLISECONDS_PER_DAY * 7);
|
|
2900
|
+
case "month":
|
|
2901
|
+
return diffMs / MILLISECONDS_PER_MONTH;
|
|
2902
|
+
case "quarter":
|
|
2903
|
+
return diffMs / (MILLISECONDS_PER_MONTH * 3);
|
|
2904
|
+
case "year":
|
|
2905
|
+
return diffMs / MILLISECONDS_PER_YEAR;
|
|
2716
2906
|
}
|
|
2717
2907
|
}
|
|
2718
2908
|
return diffInUnits(this._date, otherDate._date, normalizedUnit);
|
|
@@ -2770,12 +2960,12 @@ var Chronos = class _Chronos {
|
|
|
2770
2960
|
* Get relative time from another date
|
|
2771
2961
|
*/
|
|
2772
2962
|
from(other, options = {}) {
|
|
2773
|
-
var _a, _b;
|
|
2963
|
+
var _a, _b, _c;
|
|
2774
2964
|
const otherDate = _Chronos.parse(other);
|
|
2775
2965
|
const diffMs = this._date.getTime() - otherDate._date.getTime();
|
|
2776
2966
|
const absDiff = Math.abs(diffMs);
|
|
2777
2967
|
const isFuture = diffMs > 0;
|
|
2778
|
-
const { short
|
|
2968
|
+
const { short = false, absolute = false } = options;
|
|
2779
2969
|
const relative = this._locale.relativeTime;
|
|
2780
2970
|
let value;
|
|
2781
2971
|
let unit;
|
|
@@ -2801,10 +2991,26 @@ var Chronos = class _Chronos {
|
|
|
2801
2991
|
value = Math.round(absDiff / (MILLISECONDS_PER_DAY * 365));
|
|
2802
2992
|
unit = value === 1 ? "y" : "yy";
|
|
2803
2993
|
}
|
|
2804
|
-
const
|
|
2994
|
+
const shortUnits = {
|
|
2995
|
+
s: "s",
|
|
2996
|
+
ss: "s",
|
|
2997
|
+
m: "m",
|
|
2998
|
+
mm: "m",
|
|
2999
|
+
h: "h",
|
|
3000
|
+
hh: "h",
|
|
3001
|
+
d: "d",
|
|
3002
|
+
dd: "d",
|
|
3003
|
+
w: "w",
|
|
3004
|
+
ww: "w",
|
|
3005
|
+
M: "mo",
|
|
3006
|
+
MM: "mo",
|
|
3007
|
+
y: "y",
|
|
3008
|
+
yy: "y"
|
|
3009
|
+
};
|
|
3010
|
+
const relativeStr = short ? `${value}${(_a = shortUnits[unit]) != null ? _a : unit}` : (_c = (_b = relative[unit]) == null ? void 0 : _b.replace(
|
|
2805
3011
|
"%d",
|
|
2806
3012
|
String(value)
|
|
2807
|
-
)) != null ?
|
|
3013
|
+
)) != null ? _c : `${value} ${unit}`;
|
|
2808
3014
|
if (absolute) {
|
|
2809
3015
|
return relativeStr;
|
|
2810
3016
|
}
|
|
@@ -2883,7 +3089,7 @@ var Chronos = class _Chronos {
|
|
|
2883
3089
|
Z: () => this.offsetString,
|
|
2884
3090
|
ZZ: () => this.offsetString.replace(":", ""),
|
|
2885
3091
|
Q: () => String(this.quarter),
|
|
2886
|
-
Do: () =>
|
|
3092
|
+
Do: () => this._locale.ordinal(this.date),
|
|
2887
3093
|
W: () => String(this.week),
|
|
2888
3094
|
WW: () => padStart(this.week, 2),
|
|
2889
3095
|
X: () => String(this.unix),
|
|
@@ -3157,15 +3363,16 @@ var ChronosInterval = class _ChronosInterval {
|
|
|
3157
3363
|
// Constructor
|
|
3158
3364
|
// ============================================================================
|
|
3159
3365
|
constructor(duration = {}, inverted = false) {
|
|
3160
|
-
var _a, _b, _c, _d, _e, _f, _g, _h
|
|
3366
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
3161
3367
|
this._years = (_a = duration.years) != null ? _a : 0;
|
|
3162
3368
|
this._months = (_b = duration.months) != null ? _b : 0;
|
|
3163
3369
|
this._weeks = (_c = duration.weeks) != null ? _c : 0;
|
|
3164
3370
|
this._days = (_d = duration.days) != null ? _d : 0;
|
|
3165
3371
|
this._hours = (_e = duration.hours) != null ? _e : 0;
|
|
3166
3372
|
this._minutes = (_f = duration.minutes) != null ? _f : 0;
|
|
3167
|
-
|
|
3168
|
-
this.
|
|
3373
|
+
const totalSeconds = (_g = duration.seconds) != null ? _g : 0;
|
|
3374
|
+
this._seconds = Math.trunc(totalSeconds);
|
|
3375
|
+
this._milliseconds = (_h = duration.milliseconds) != null ? _h : Math.round((totalSeconds - this._seconds) * 1e3);
|
|
3169
3376
|
this._locale = getLocale("en");
|
|
3170
3377
|
this._inverted = inverted;
|
|
3171
3378
|
}
|
|
@@ -3854,7 +4061,6 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
3854
4061
|
immutable: (_c = options.immutable) != null ? _c : true
|
|
3855
4062
|
};
|
|
3856
4063
|
this._filters = [];
|
|
3857
|
-
this._current = 0;
|
|
3858
4064
|
this._locale = getLocale("en");
|
|
3859
4065
|
}
|
|
3860
4066
|
// ============================================================================
|
|
@@ -4464,13 +4670,24 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4464
4670
|
// ============================================================================
|
|
4465
4671
|
// Range Operations
|
|
4466
4672
|
// ============================================================================
|
|
4673
|
+
/**
|
|
4674
|
+
* Resolve the effective end of the period.
|
|
4675
|
+
* Returns null for a truly unbounded period (no end and no recurrence limit),
|
|
4676
|
+
* which avoids calling last() — that would iterate until the safety limit and throw.
|
|
4677
|
+
*/
|
|
4678
|
+
_resolvedEnd() {
|
|
4679
|
+
var _a;
|
|
4680
|
+
if (this.isUnbounded) {
|
|
4681
|
+
return null;
|
|
4682
|
+
}
|
|
4683
|
+
return (_a = this._end) != null ? _a : this.last();
|
|
4684
|
+
}
|
|
4467
4685
|
/**
|
|
4468
4686
|
* Check if two periods overlap
|
|
4469
4687
|
*/
|
|
4470
4688
|
overlaps(other) {
|
|
4471
|
-
|
|
4472
|
-
const
|
|
4473
|
-
const otherEnd = (_b = other._end) != null ? _b : other.last();
|
|
4689
|
+
const thisEnd = this._resolvedEnd();
|
|
4690
|
+
const otherEnd = other._resolvedEnd();
|
|
4474
4691
|
if (!thisEnd || !otherEnd) {
|
|
4475
4692
|
return true;
|
|
4476
4693
|
}
|
|
@@ -4480,13 +4697,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4480
4697
|
* Get the intersection of two periods
|
|
4481
4698
|
*/
|
|
4482
4699
|
intersect(other) {
|
|
4483
|
-
var _a, _b;
|
|
4484
4700
|
if (!this.overlaps(other)) {
|
|
4485
4701
|
return null;
|
|
4486
4702
|
}
|
|
4487
4703
|
const start = this._start.isAfter(other._start) ? this._start : other._start;
|
|
4488
|
-
const thisEnd =
|
|
4489
|
-
const otherEnd =
|
|
4704
|
+
const thisEnd = this._resolvedEnd();
|
|
4705
|
+
const otherEnd = other._resolvedEnd();
|
|
4490
4706
|
if (!thisEnd || !otherEnd) {
|
|
4491
4707
|
return new _ChronosPeriod(start, void 0, this._interval);
|
|
4492
4708
|
}
|
|
@@ -4497,13 +4713,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4497
4713
|
* Get the union of two periods
|
|
4498
4714
|
*/
|
|
4499
4715
|
union(other) {
|
|
4500
|
-
var _a, _b;
|
|
4501
4716
|
if (!this.overlaps(other) && !this._adjacentTo(other)) {
|
|
4502
4717
|
return null;
|
|
4503
4718
|
}
|
|
4504
4719
|
const start = this._start.isBefore(other._start) ? this._start : other._start;
|
|
4505
|
-
const thisEnd =
|
|
4506
|
-
const otherEnd =
|
|
4720
|
+
const thisEnd = this._resolvedEnd();
|
|
4721
|
+
const otherEnd = other._resolvedEnd();
|
|
4507
4722
|
if (!thisEnd || !otherEnd) {
|
|
4508
4723
|
return new _ChronosPeriod(start, void 0, this._interval);
|
|
4509
4724
|
}
|
|
@@ -4515,13 +4730,12 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4515
4730
|
* Returns the parts of this period that don't overlap with the other period
|
|
4516
4731
|
*/
|
|
4517
4732
|
diff(other) {
|
|
4518
|
-
var _a, _b;
|
|
4519
4733
|
if (!this.overlaps(other)) {
|
|
4520
4734
|
return [this.clone()];
|
|
4521
4735
|
}
|
|
4522
4736
|
const results = [];
|
|
4523
|
-
const thisEnd =
|
|
4524
|
-
const otherEnd =
|
|
4737
|
+
const thisEnd = this._resolvedEnd();
|
|
4738
|
+
const otherEnd = other._resolvedEnd();
|
|
4525
4739
|
if (this._start.isBefore(other._start)) {
|
|
4526
4740
|
results.push(
|
|
4527
4741
|
new _ChronosPeriod(this._start, other._start, this._interval)
|
|
@@ -4536,9 +4750,8 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4536
4750
|
* Check if this period is adjacent to another
|
|
4537
4751
|
*/
|
|
4538
4752
|
_adjacentTo(other) {
|
|
4539
|
-
|
|
4540
|
-
const
|
|
4541
|
-
const otherEnd = (_b = other._end) != null ? _b : other.last();
|
|
4753
|
+
const thisEnd = this._resolvedEnd();
|
|
4754
|
+
const otherEnd = other._resolvedEnd();
|
|
4542
4755
|
if (!thisEnd || !otherEnd) {
|
|
4543
4756
|
return false;
|
|
4544
4757
|
}
|
|
@@ -4630,11 +4843,13 @@ var ChronosPeriod = class _ChronosPeriod {
|
|
|
4630
4843
|
}
|
|
4631
4844
|
const chunks = [];
|
|
4632
4845
|
let current = this._start.clone();
|
|
4846
|
+
const subStep = splitInterval.total("days") >= 1 ? { days: 1 } : { milliseconds: 1 };
|
|
4633
4847
|
while (current.isSameOrBefore(this._end)) {
|
|
4634
|
-
const
|
|
4848
|
+
const nextStart = current.add(splitInterval.toDuration());
|
|
4849
|
+
const chunkEnd = nextStart.subtract(subStep);
|
|
4635
4850
|
const end = chunkEnd.isAfter(this._end) ? this._end : chunkEnd;
|
|
4636
4851
|
chunks.push(new _ChronosPeriod(current, end, this._interval));
|
|
4637
|
-
current =
|
|
4852
|
+
current = nextStart;
|
|
4638
4853
|
}
|
|
4639
4854
|
return chunks;
|
|
4640
4855
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chronos-ts",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "A comprehensive TypeScript library for date and time manipulation, inspired by Carbon PHP. Features immutable API, intervals, periods, timezones, and i18n support.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|