temporal-utils 1.0.0 → 1.0.1
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/LICENSE +21 -0
- package/README.md +873 -0
- package/dist/diff.d.ts +17 -0
- package/dist/diff.js +52 -0
- package/dist/endOf.d.ts +9 -0
- package/dist/endOf.js +56 -0
- package/dist/errorMessages.d.ts +9 -0
- package/dist/errorMessages.js +14 -0
- package/dist/global-types.d.ts +1 -0
- package/dist/global-types.js +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/protected-error-messages.d.ts +1 -0
- package/dist/protected-error-messages.js +1 -0
- package/dist/protected.d.ts +1 -0
- package/dist/protected.js +1 -0
- package/dist/round.d.ts +24 -0
- package/dist/round.js +47 -0
- package/dist/startOf.d.ts +9 -0
- package/dist/startOf.js +73 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +81 -0
- package/dist/with.d.ts +3 -0
- package/dist/with.js +44 -0
- package/package.json +54 -8
package/dist/diff.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RoundingMathOptions, RoundingMode } from './utils';
|
|
2
|
+
type DiffFunc<T extends Temporal.Instant | Temporal.PlainTime | Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime = Temporal.Instant | Temporal.PlainTime | Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime> = {
|
|
3
|
+
(date0: T, date1: T): number;
|
|
4
|
+
(date0: T, date1: T, roundingMode: RoundingMode): number;
|
|
5
|
+
(date0: T, date1: T, options: RoundingMathOptions): number;
|
|
6
|
+
};
|
|
7
|
+
export declare const diffYears: DiffFunc<Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
8
|
+
export declare const diffMonths: DiffFunc<Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
9
|
+
export declare const diffWeeks: DiffFunc<Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
10
|
+
export declare const diffDays: DiffFunc<Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
11
|
+
export declare const diffHours: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
12
|
+
export declare const diffMinutes: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
13
|
+
export declare const diffSeconds: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
14
|
+
export declare const diffMilliseconds: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
15
|
+
export declare const diffMicroseconds: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
16
|
+
export declare const diffNanoseconds: DiffFunc<Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>;
|
|
17
|
+
export {};
|
package/dist/diff.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function createDiffFunc(unit) {
|
|
2
|
+
return (date0, date1, options) => {
|
|
3
|
+
const normOptions = normalizeDiffOptions(options);
|
|
4
|
+
// TODO: throw error if unit impossible for input-types?
|
|
5
|
+
// like diffing years for PlainTime?
|
|
6
|
+
if (normOptions.roundingMode) {
|
|
7
|
+
return date0.until(date1, {
|
|
8
|
+
...normOptions,
|
|
9
|
+
largestUnit: unit,
|
|
10
|
+
smallestUnit: unit,
|
|
11
|
+
})[unit];
|
|
12
|
+
}
|
|
13
|
+
const duration = date0.until(date1, {
|
|
14
|
+
...normOptions,
|
|
15
|
+
largestUnit: unit,
|
|
16
|
+
});
|
|
17
|
+
// Time-unit helpers produce pure elapsed-time totals. This keeps Instant
|
|
18
|
+
// and PlainTime valid because neither can be used as a `relativeTo` value.
|
|
19
|
+
if (isTimeUnit(unit)) {
|
|
20
|
+
return duration.total(unit);
|
|
21
|
+
}
|
|
22
|
+
// Date-bearing objects need `relativeTo` so totals account for calendar
|
|
23
|
+
// units and, for ZonedDateTime, time-zone transitions. PlainYearMonth has
|
|
24
|
+
// month precision, so day 1 gives Duration.total a concrete date anchor.
|
|
25
|
+
const relativeTo = (!('day' in date0) && 'toPlainDate' in date0
|
|
26
|
+
? date0.toPlainDate({ day: 1 })
|
|
27
|
+
: date0);
|
|
28
|
+
return duration.total({ unit, relativeTo });
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// TODO: more DRY with elsewhere?
|
|
32
|
+
function isTimeUnit(unit) {
|
|
33
|
+
return (unit === 'hours' ||
|
|
34
|
+
unit === 'minutes' ||
|
|
35
|
+
unit === 'seconds' ||
|
|
36
|
+
unit === 'milliseconds' ||
|
|
37
|
+
unit === 'microseconds' ||
|
|
38
|
+
unit === 'nanoseconds');
|
|
39
|
+
}
|
|
40
|
+
export const diffYears = createDiffFunc('years');
|
|
41
|
+
export const diffMonths = createDiffFunc('months');
|
|
42
|
+
export const diffWeeks = createDiffFunc('weeks');
|
|
43
|
+
export const diffDays = createDiffFunc('days');
|
|
44
|
+
export const diffHours = createDiffFunc('hours');
|
|
45
|
+
export const diffMinutes = createDiffFunc('minutes');
|
|
46
|
+
export const diffSeconds = createDiffFunc('seconds');
|
|
47
|
+
export const diffMilliseconds = createDiffFunc('milliseconds');
|
|
48
|
+
export const diffMicroseconds = createDiffFunc('microseconds');
|
|
49
|
+
export const diffNanoseconds = createDiffFunc('nanoseconds');
|
|
50
|
+
function normalizeDiffOptions(options) {
|
|
51
|
+
return typeof options === 'string' ? { roundingMode: options } : options || {};
|
|
52
|
+
}
|
package/dist/endOf.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function endOfYear<T extends Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
2
|
+
export declare function endOfMonth<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
3
|
+
export declare function endOfWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
4
|
+
export declare function endOfDay<T extends Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
5
|
+
export declare function endOfHour<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
6
|
+
export declare function endOfMinute<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
7
|
+
export declare function endOfSecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
8
|
+
export declare function endOfMillisecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
9
|
+
export declare function endOfMicrosecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
package/dist/endOf.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { startOfHour, startOfMicrosecond, startOfMillisecond, startOfMinute, startOfMonth, startOfSecond, startOfWeek, startOfYear, } from './startOf.js';
|
|
2
|
+
import { nanoInHour, nanoInMicro, nanoInMilli, nanoInMinute, nanoInSec, } from './utils.js';
|
|
3
|
+
export function endOfYear(date) {
|
|
4
|
+
return startOfYear(date)
|
|
5
|
+
.add({ years: 1 })
|
|
6
|
+
.subtract(date.day === undefined
|
|
7
|
+
? { months: 1 }
|
|
8
|
+
: date
|
|
9
|
+
.nanosecond !== undefined
|
|
10
|
+
? { nanoseconds: 1 }
|
|
11
|
+
: { days: 1 });
|
|
12
|
+
}
|
|
13
|
+
export function endOfMonth(date) {
|
|
14
|
+
return startOfMonth(date)
|
|
15
|
+
.add({ months: 1 })
|
|
16
|
+
.subtract(date.nanosecond !==
|
|
17
|
+
undefined
|
|
18
|
+
? { nanoseconds: 1 }
|
|
19
|
+
: { days: 1 });
|
|
20
|
+
}
|
|
21
|
+
export function endOfWeek(date) {
|
|
22
|
+
return startOfWeek(date)
|
|
23
|
+
.add({ weeks: 1 })
|
|
24
|
+
.subtract(date.nanosecond !==
|
|
25
|
+
undefined
|
|
26
|
+
? { nanoseconds: 1 }
|
|
27
|
+
: { days: 1 });
|
|
28
|
+
}
|
|
29
|
+
export function endOfDay(date) {
|
|
30
|
+
if (date.withPlainTime) {
|
|
31
|
+
return date
|
|
32
|
+
.withPlainTime()
|
|
33
|
+
.add({ days: 1 })
|
|
34
|
+
.subtract({ nanoseconds: 1 });
|
|
35
|
+
}
|
|
36
|
+
return date; // in case PlainDate passed in, not moved to next day
|
|
37
|
+
}
|
|
38
|
+
export function endOfHour(date) {
|
|
39
|
+
return startOfHour(date).add({ nanoseconds: nanoInHour - 1 });
|
|
40
|
+
}
|
|
41
|
+
export function endOfMinute(date) {
|
|
42
|
+
return startOfMinute(date).add({ nanoseconds: nanoInMinute - 1 });
|
|
43
|
+
}
|
|
44
|
+
export function endOfSecond(date) {
|
|
45
|
+
return startOfSecond(date).add({ nanoseconds: nanoInSec - 1 });
|
|
46
|
+
}
|
|
47
|
+
export function endOfMillisecond(date) {
|
|
48
|
+
return startOfMillisecond(date).add({
|
|
49
|
+
nanoseconds: nanoInMilli - 1,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export function endOfMicrosecond(date) {
|
|
53
|
+
return startOfMicrosecond(date).add({
|
|
54
|
+
nanoseconds: nanoInMicro - 1,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const expectedPositive: (entityName: string, num: number) => string;
|
|
2
|
+
export declare const expectedFinite: (entityName: string, num: number) => string;
|
|
3
|
+
export declare const forbiddenBigIntToNumber: (entityName: string) => string;
|
|
4
|
+
export declare const invalidObject = "Invalid object";
|
|
5
|
+
export declare const numberOutOfRange: (entityName: string, val: number | string, min: number | string, max: number | string) => string;
|
|
6
|
+
export declare const invalidEntity: (fieldName: string, val: any) => string;
|
|
7
|
+
export declare const unsupportedWeekNumbers = "Calendar week operations forbidden";
|
|
8
|
+
export declare const nonOneRoundingIncrement = "Non-1 roundingIncrement not allowed";
|
|
9
|
+
export declare const invalidOverflowOption = "Invalid overflow option";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Low-Level
|
|
2
|
+
export const expectedPositive = (entityName, num) => `Non-positive ${entityName}: ${num}`;
|
|
3
|
+
export const expectedFinite = (entityName, num) => `Non-finite ${entityName}: ${num}`;
|
|
4
|
+
export const forbiddenBigIntToNumber = (entityName) => `Cannot convert bigint to ${entityName}`;
|
|
5
|
+
export const invalidObject = 'Invalid object';
|
|
6
|
+
export const numberOutOfRange = (entityName, val, min, max) => invalidEntity(entityName, val) + `; must be between ${min}-${max}`;
|
|
7
|
+
// Entity/Fields/Bags
|
|
8
|
+
export const invalidEntity = (fieldName, val) => `Invalid ${fieldName}: ${val}`;
|
|
9
|
+
// Calendar
|
|
10
|
+
export const unsupportedWeekNumbers = 'Calendar week operations forbidden';
|
|
11
|
+
// Rounding
|
|
12
|
+
export const nonOneRoundingIncrement = 'Non-1 roundingIncrement not allowed';
|
|
13
|
+
// Options
|
|
14
|
+
export const invalidOverflowOption = 'Invalid overflow option';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { invalidEntity, numberOutOfRange, unsupportedWeekNumbers, } from './errorMessages.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { invalidEntity, numberOutOfRange, unsupportedWeekNumbers, } from './errorMessages.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { constrainToRange, isObjectLike, nanoInHour, nanoInMicro, nanoInMilli, nanoInMinute, nanoInSec, normalizeNumberInRange, normalizeOptions, requireNumberIsPositive, requireObjectLike, toFiniteNumber, toIntegerWithTrunc, toPositiveIntegerWithTruncation, } from './utils.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { constrainToRange, isObjectLike, nanoInHour, nanoInMicro, nanoInMilli, nanoInMinute, nanoInSec, normalizeNumberInRange, normalizeOptions, requireNumberIsPositive, requireObjectLike, toFiniteNumber, toIntegerWithTrunc, toPositiveIntegerWithTruncation, } from './utils.js';
|
package/dist/round.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RoundingMathOptions, RoundingMode } from './utils.js';
|
|
2
|
+
export declare function roundToYear<T extends Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
3
|
+
export declare function roundToYear<T extends Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, roundingMode: RoundingMode): T;
|
|
4
|
+
export declare function roundToYear<T extends Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, options: RoundingMathOptions): T;
|
|
5
|
+
export declare function roundToMonth<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
6
|
+
export declare function roundToMonth<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, roundingMode: RoundingMode): T;
|
|
7
|
+
export declare function roundToMonth<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, options: RoundingMathOptions): T;
|
|
8
|
+
export declare function roundToWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
9
|
+
export declare function roundToWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, roundingMode: RoundingMode): T;
|
|
10
|
+
export declare function roundToWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, options: RoundingMathOptions): T;
|
|
11
|
+
type NativeRoundFunc<T> = {
|
|
12
|
+
(date: T): T;
|
|
13
|
+
(date: T, roundingMode: RoundingMode): T;
|
|
14
|
+
(date: T, options: RoundingMathOptions): T;
|
|
15
|
+
};
|
|
16
|
+
type DayRoundable = Temporal.PlainDateTime | Temporal.ZonedDateTime;
|
|
17
|
+
type TimeRoundable = Temporal.Instant | Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime;
|
|
18
|
+
export declare const roundToDay: NativeRoundFunc<DayRoundable>;
|
|
19
|
+
export declare const roundToHour: NativeRoundFunc<TimeRoundable>;
|
|
20
|
+
export declare const roundToMinute: NativeRoundFunc<TimeRoundable>;
|
|
21
|
+
export declare const roundToSecond: NativeRoundFunc<TimeRoundable>;
|
|
22
|
+
export declare const roundToMillisecond: NativeRoundFunc<TimeRoundable>;
|
|
23
|
+
export declare const roundToMicrosecond: NativeRoundFunc<TimeRoundable>;
|
|
24
|
+
export {};
|
package/dist/round.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as errorMessages from './errorMessages.js';
|
|
2
|
+
import { startOfMonth, startOfWeek, startOfYear } from './startOf.js';
|
|
3
|
+
import { normalizeOptions } from './utils.js';
|
|
4
|
+
export function roundToYear(date, options) {
|
|
5
|
+
const start = startOfYear(date);
|
|
6
|
+
const duration = start.until(date, normalizeRoundingOptions('year', options));
|
|
7
|
+
return start.add(duration);
|
|
8
|
+
}
|
|
9
|
+
export function roundToMonth(date, options) {
|
|
10
|
+
const start = startOfMonth(date);
|
|
11
|
+
const duration = start.until(date, normalizeRoundingOptions('month', options));
|
|
12
|
+
return start.add(duration);
|
|
13
|
+
}
|
|
14
|
+
export function roundToWeek(date, options) {
|
|
15
|
+
const start = startOfWeek(date);
|
|
16
|
+
const duration = start.until(date, normalizeRoundingOptions('week', options));
|
|
17
|
+
return start.add(duration);
|
|
18
|
+
}
|
|
19
|
+
export const roundToDay = ((date, options) => date.round(getNativeRoundOptions('day', options)));
|
|
20
|
+
export const roundToHour = ((date, options) => date.round(getNativeRoundOptions('hour', options)));
|
|
21
|
+
export const roundToMinute = ((date, options) => date.round(getNativeRoundOptions('minute', options)));
|
|
22
|
+
export const roundToSecond = ((date, options) => date.round(getNativeRoundOptions('second', options)));
|
|
23
|
+
export const roundToMillisecond = ((date, options) => date.round(getNativeRoundOptions('millisecond', options)));
|
|
24
|
+
export const roundToMicrosecond = ((date, options) => date.round(getNativeRoundOptions('microsecond', options)));
|
|
25
|
+
function getNativeRoundOptions(forcedUnit, options) {
|
|
26
|
+
return {
|
|
27
|
+
...(typeof options === 'string'
|
|
28
|
+
? { roundingMode: options }
|
|
29
|
+
: normalizeOptions(options)),
|
|
30
|
+
smallestUnit: forcedUnit,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function normalizeRoundingOptions(forcedUnit, options) {
|
|
34
|
+
// Accept a bare roundingMode string as shorthand for { roundingMode }.
|
|
35
|
+
const normOptions = typeof options === 'string'
|
|
36
|
+
? { roundingMode: options }
|
|
37
|
+
: normalizeOptions(options);
|
|
38
|
+
// This is just for units >day
|
|
39
|
+
if (normOptions.roundingIncrement && normOptions.roundingIncrement !== 1) {
|
|
40
|
+
throw new RangeError(errorMessages.nonOneRoundingIncrement);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
roundingMode: 'halfExpand',
|
|
44
|
+
...normOptions,
|
|
45
|
+
smallestUnit: forcedUnit,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function startOfYear<T extends Temporal.PlainYearMonth | Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
2
|
+
export declare function startOfMonth<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
3
|
+
export declare function startOfWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T): T;
|
|
4
|
+
export declare function startOfDay<T extends Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
|
5
|
+
export declare function startOfHour<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
|
6
|
+
export declare function startOfMinute<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
|
7
|
+
export declare function startOfSecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
|
8
|
+
export declare function startOfMillisecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
|
9
|
+
export declare function startOfMicrosecond<T extends Temporal.PlainTime | Temporal.PlainDateTime | Temporal.ZonedDateTime>(dateTime: T): T;
|
package/dist/startOf.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { withDayOfWeek } from './with.js';
|
|
2
|
+
const zeroTimeFields = {
|
|
3
|
+
hour: 0,
|
|
4
|
+
minute: 0,
|
|
5
|
+
second: 0,
|
|
6
|
+
millisecond: 0,
|
|
7
|
+
microsecond: 0,
|
|
8
|
+
nanosecond: 0,
|
|
9
|
+
};
|
|
10
|
+
export function startOfYear(date) {
|
|
11
|
+
if (date.day === undefined) {
|
|
12
|
+
return date.with({ month: 1 });
|
|
13
|
+
}
|
|
14
|
+
return date.with({
|
|
15
|
+
month: 1,
|
|
16
|
+
day: 1,
|
|
17
|
+
...zeroTimeFields,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function startOfMonth(date) {
|
|
21
|
+
return date.with({
|
|
22
|
+
day: 1,
|
|
23
|
+
...zeroTimeFields,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function startOfWeek(date) {
|
|
27
|
+
const movedDate = withDayOfWeek(date, 1);
|
|
28
|
+
return movedDate
|
|
29
|
+
.withPlainTime
|
|
30
|
+
? movedDate.withPlainTime()
|
|
31
|
+
: movedDate;
|
|
32
|
+
}
|
|
33
|
+
export function startOfDay(dateTime) {
|
|
34
|
+
if (dateTime.withPlainTime) {
|
|
35
|
+
return dateTime.withPlainTime();
|
|
36
|
+
}
|
|
37
|
+
return dateTime; // in case PlainDate passed in, no error
|
|
38
|
+
}
|
|
39
|
+
export function startOfHour(dateTime) {
|
|
40
|
+
return dateTime.with({
|
|
41
|
+
minute: 0,
|
|
42
|
+
second: 0,
|
|
43
|
+
millisecond: 0,
|
|
44
|
+
microsecond: 0,
|
|
45
|
+
nanosecond: 0,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
export function startOfMinute(dateTime) {
|
|
49
|
+
return dateTime.with({
|
|
50
|
+
second: 0,
|
|
51
|
+
millisecond: 0,
|
|
52
|
+
microsecond: 0,
|
|
53
|
+
nanosecond: 0,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
export function startOfSecond(dateTime) {
|
|
57
|
+
return dateTime.with({
|
|
58
|
+
millisecond: 0,
|
|
59
|
+
microsecond: 0,
|
|
60
|
+
nanosecond: 0,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export function startOfMillisecond(dateTime) {
|
|
64
|
+
return dateTime.with({
|
|
65
|
+
microsecond: 0,
|
|
66
|
+
nanosecond: 0,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
export function startOfMicrosecond(dateTime) {
|
|
70
|
+
return dateTime.with({
|
|
71
|
+
nanosecond: 0,
|
|
72
|
+
});
|
|
73
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const nanoInMicro = 1000;
|
|
2
|
+
export declare const nanoInMilli = 1000000;
|
|
3
|
+
export declare const nanoInSec = 1000000000;
|
|
4
|
+
export declare const nanoInMinute = 60000000000;
|
|
5
|
+
export declare const nanoInHour = 3600000000000;
|
|
6
|
+
type RoundingUnit = Temporal.DateUnit | Temporal.TimeUnit;
|
|
7
|
+
type RoundingOptionBag = Temporal.RoundingOptions<RoundingUnit>;
|
|
8
|
+
export type RoundingMode = RoundingOptionBag['roundingMode'];
|
|
9
|
+
export type RoundingMathOptions = Pick<RoundingOptionBag, 'roundingIncrement' | 'roundingMode'>;
|
|
10
|
+
export declare function normalizeOptions<O extends {}>(options: O | undefined): O;
|
|
11
|
+
export declare function toFiniteNumber(arg: number, entityName?: string): number;
|
|
12
|
+
export declare function toIntegerWithTrunc(arg: number, entityName?: string): number;
|
|
13
|
+
export declare function toPositiveIntegerWithTruncation(arg: number, entityName?: string): number;
|
|
14
|
+
export declare function requireNumberIsPositive(num: number, entityName?: string): number;
|
|
15
|
+
export declare function constrainToRange(num: number, min: number, max: number): number;
|
|
16
|
+
export declare function isObjectLike(arg: unknown): arg is {};
|
|
17
|
+
export declare function requireObjectLike<O extends {}>(arg: O): O;
|
|
18
|
+
export declare function normalizeNumberInRange(num: number, min: number, max: number, // inclusive
|
|
19
|
+
options?: Temporal.OverflowOptions): number;
|
|
20
|
+
export {};
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as errorMessages from './errorMessages.js';
|
|
2
|
+
export const nanoInMicro = 1_000;
|
|
3
|
+
export const nanoInMilli = 1_000_000;
|
|
4
|
+
export const nanoInSec = 1_000_000_000;
|
|
5
|
+
export const nanoInMinute = 60_000_000_000;
|
|
6
|
+
export const nanoInHour = 3_600_000_000_000;
|
|
7
|
+
export function normalizeOptions(options) {
|
|
8
|
+
if (options === undefined) {
|
|
9
|
+
return Object.create(null);
|
|
10
|
+
}
|
|
11
|
+
return requireObjectLike(options);
|
|
12
|
+
}
|
|
13
|
+
export function toFiniteNumber(arg, entityName = 'number') {
|
|
14
|
+
if (typeof arg === 'bigint') {
|
|
15
|
+
throw new TypeError(errorMessages.forbiddenBigIntToNumber(entityName));
|
|
16
|
+
}
|
|
17
|
+
arg = Number(arg);
|
|
18
|
+
if (!Number.isFinite(arg)) {
|
|
19
|
+
throw new RangeError(errorMessages.expectedFinite(entityName, arg));
|
|
20
|
+
}
|
|
21
|
+
return arg;
|
|
22
|
+
}
|
|
23
|
+
export function toIntegerWithTrunc(arg, entityName) {
|
|
24
|
+
return Math.trunc(toFiniteNumber(arg, entityName)) || 0; // ensure no -0
|
|
25
|
+
}
|
|
26
|
+
export function toPositiveIntegerWithTruncation(arg, entityName) {
|
|
27
|
+
return requireNumberIsPositive(toIntegerWithTrunc(arg, entityName), entityName);
|
|
28
|
+
}
|
|
29
|
+
/*
|
|
30
|
+
Already known to be number.
|
|
31
|
+
*/
|
|
32
|
+
export function requireNumberIsPositive(num, entityName = 'number') {
|
|
33
|
+
if (num <= 0) {
|
|
34
|
+
throw new RangeError(errorMessages.expectedPositive(entityName, num));
|
|
35
|
+
}
|
|
36
|
+
return num;
|
|
37
|
+
}
|
|
38
|
+
/*
|
|
39
|
+
min/max are inclusive
|
|
40
|
+
*/
|
|
41
|
+
export function constrainToRange(num, min, max) {
|
|
42
|
+
return Math.min(Math.max(num, min), max);
|
|
43
|
+
}
|
|
44
|
+
export function isObjectLike(arg) {
|
|
45
|
+
return arg !== null && (typeof arg === 'object' || typeof arg === 'function');
|
|
46
|
+
}
|
|
47
|
+
export function requireObjectLike(arg) {
|
|
48
|
+
if (!isObjectLike(arg)) {
|
|
49
|
+
throw new TypeError(errorMessages.invalidObject);
|
|
50
|
+
}
|
|
51
|
+
return arg;
|
|
52
|
+
}
|
|
53
|
+
// Options-bag-parsing-adjacent
|
|
54
|
+
// ----------------------------
|
|
55
|
+
/*
|
|
56
|
+
Already known to be number
|
|
57
|
+
*/
|
|
58
|
+
export function normalizeNumberInRange(num, min, max, // inclusive
|
|
59
|
+
options) {
|
|
60
|
+
const clamped = constrainToRange(num, min, max);
|
|
61
|
+
if (normalizeOverflow(options) === 'reject' && num !== clamped) {
|
|
62
|
+
throw new RangeError(errorMessages.numberOutOfRange('number', num, min, max));
|
|
63
|
+
}
|
|
64
|
+
return clamped;
|
|
65
|
+
}
|
|
66
|
+
/*
|
|
67
|
+
Match Temporal's field overflow shape without depending on the polyfill's
|
|
68
|
+
internal option readers. Undefined defaults to constrain; explicit reject asks
|
|
69
|
+
for exact in-range input.
|
|
70
|
+
*/
|
|
71
|
+
function normalizeOverflow(options) {
|
|
72
|
+
options = normalizeOptions(options);
|
|
73
|
+
const overflow = options.overflow;
|
|
74
|
+
if (overflow === undefined) {
|
|
75
|
+
return 'constrain';
|
|
76
|
+
}
|
|
77
|
+
if (overflow === 'constrain' || overflow === 'reject') {
|
|
78
|
+
return overflow;
|
|
79
|
+
}
|
|
80
|
+
throw new RangeError(errorMessages.invalidOverflowOption);
|
|
81
|
+
}
|
package/dist/with.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function withDayOfYear<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, dayOfYear: number, options?: Temporal.OverflowOptions): T;
|
|
2
|
+
export declare function withDayOfWeek<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, dayOfWeek: number, options?: Temporal.OverflowOptions): T;
|
|
3
|
+
export declare function withWeekOfYear<T extends Temporal.PlainDate | Temporal.PlainDateTime | Temporal.ZonedDateTime>(date: T, weekOfYear: number, options?: Temporal.OverflowOptions): T;
|
package/dist/with.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as errorMessages from './errorMessages.js';
|
|
2
|
+
import { normalizeNumberInRange, toIntegerWithTrunc } from './utils.js';
|
|
3
|
+
const isoCalendarId = 'iso8601';
|
|
4
|
+
export function withDayOfYear(date, dayOfYear, options) {
|
|
5
|
+
const normDayOfYear = normalizeNumberInRange(toIntegerWithTrunc(dayOfYear), 1, date.daysInYear, options);
|
|
6
|
+
return date.add({
|
|
7
|
+
days: normDayOfYear - date.dayOfYear,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export function withDayOfWeek(date, dayOfWeek, options) {
|
|
11
|
+
const normDayOfWeek = normalizeNumberInRange(toIntegerWithTrunc(dayOfWeek), 1, date.daysInWeek, options);
|
|
12
|
+
return date.add({
|
|
13
|
+
days: normDayOfWeek - date.dayOfWeek,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function withWeekOfYear(date, weekOfYear, options) {
|
|
17
|
+
if (date.calendarId !== isoCalendarId) {
|
|
18
|
+
throw new RangeError(errorMessages.unsupportedWeekNumbers);
|
|
19
|
+
}
|
|
20
|
+
const currentWeekOfYear = date.weekOfYear;
|
|
21
|
+
const currentYearOfWeek = date.yearOfWeek;
|
|
22
|
+
const normWeekOfYear = normalizeNumberInRange(toIntegerWithTrunc(weekOfYear), 1, computeIsoWeeksInYear(currentYearOfWeek), options);
|
|
23
|
+
return date.add({
|
|
24
|
+
weeks: normWeekOfYear - currentWeekOfYear,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
// Week Number Utils
|
|
28
|
+
// TODO: make DRY with temporal-polyfill
|
|
29
|
+
function computeIsoWeeksInYear(year) {
|
|
30
|
+
const y0DayOfWeek = computeIsoDayOfWeek(year, 1, 1);
|
|
31
|
+
return y0DayOfWeek === 4 || (y0DayOfWeek === 3 && computeIsoInLeapYear(year))
|
|
32
|
+
? 53
|
|
33
|
+
: 52;
|
|
34
|
+
}
|
|
35
|
+
function computeIsoDayOfWeek(year, month, day) {
|
|
36
|
+
const legacyDate = new Date(0);
|
|
37
|
+
legacyDate.setUTCHours(0, 0, 0, 0);
|
|
38
|
+
legacyDate.setUTCFullYear(year, month - 1, day);
|
|
39
|
+
const dayOfWeek = legacyDate.getUTCDay();
|
|
40
|
+
return dayOfWeek || 7;
|
|
41
|
+
}
|
|
42
|
+
function computeIsoInLeapYear(year) {
|
|
43
|
+
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
44
|
+
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "temporal-utils",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"title": "Temporal Utils",
|
|
5
|
+
"description": "Convenience helpers for native Temporal objects",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "Adam Shaw",
|
|
8
|
+
"email": "arshaw@users.noreply.github.com",
|
|
9
|
+
"url": "http://arshaw.com/"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"copyright": "2026 Adam Shaw",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/fullcalendar/temporal-polyfill.git",
|
|
16
|
+
"directory": "utils"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"!dist/*.tsbuildinfo"
|
|
21
|
+
],
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./protected": {
|
|
30
|
+
"types": "./dist/protected.d.ts",
|
|
31
|
+
"import": "./dist/protected.js"
|
|
32
|
+
},
|
|
33
|
+
"./protected-error-messages": {
|
|
34
|
+
"types": "./dist/protected-error-messages.d.ts",
|
|
35
|
+
"import": "./dist/protected-error-messages.js"
|
|
36
|
+
}
|
|
8
37
|
},
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
38
|
+
"type": "module",
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@biomejs/biome": "1.5.1",
|
|
41
|
+
"@js-temporal/polyfill": "^0.5.1",
|
|
42
|
+
"typescript": "~5.3.3",
|
|
43
|
+
"vitest": "^1.2.2",
|
|
44
|
+
"temporal-spec": "1.0.0"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "pnpm run clean && tsc --build tsconfig.build.json",
|
|
48
|
+
"dev": "pnpm run clean && tsc --build tsconfig.dev.json --watch",
|
|
49
|
+
"lint": "biome check .",
|
|
50
|
+
"lint:fix": "biome check --apply .",
|
|
51
|
+
"test": "pnpm run vitest",
|
|
52
|
+
"vitest": "./scripts/vitest.js",
|
|
53
|
+
"vitest:dev": "vitest dev",
|
|
54
|
+
"vitest:debug": "vitest run --no-isolate --no-file-parallelism --test-timeout 3600000",
|
|
55
|
+
"clean": "rm -rf dist"
|
|
56
|
+
}
|
|
57
|
+
}
|