@venizia/ignis-helpers 0.2.2-1 → 0.2.2-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/dist/cjs/modules/temporal/abstract.d.ts +295 -0
- package/dist/cjs/modules/temporal/abstract.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/abstract.js +330 -0
- package/dist/cjs/modules/temporal/abstract.js.map +1 -0
- package/dist/cjs/modules/temporal/adapters/dayjs.d.ts +1 -1
- package/dist/cjs/modules/temporal/adapters/dayjs.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/adapters/dayjs.js +3 -3
- package/dist/cjs/modules/temporal/adapters/dayjs.js.map +1 -1
- package/dist/cjs/modules/temporal/adapters/intl.d.ts +1 -1
- package/dist/cjs/modules/temporal/adapters/intl.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/adapters/intl.js +7 -7
- package/dist/cjs/modules/temporal/adapters/intl.js.map +1 -1
- package/dist/cjs/modules/temporal/adapters/luxon.d.ts +1 -1
- package/dist/cjs/modules/temporal/adapters/luxon.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/adapters/luxon.js +3 -3
- package/dist/cjs/modules/temporal/adapters/luxon.js.map +1 -1
- package/dist/cjs/modules/temporal/adapters/native.d.ts +3 -1
- package/dist/cjs/modules/temporal/adapters/native.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/adapters/native.js +13 -5
- package/dist/cjs/modules/temporal/adapters/native.js.map +1 -1
- package/dist/cjs/modules/temporal/calendar/calendar.d.ts +56 -0
- package/dist/cjs/modules/temporal/calendar/calendar.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/calendar/calendar.js +166 -0
- package/dist/cjs/modules/temporal/calendar/calendar.js.map +1 -0
- package/dist/cjs/modules/temporal/calendar/index.d.ts +2 -0
- package/dist/cjs/modules/temporal/calendar/index.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/calendar/index.js +18 -0
- package/dist/cjs/modules/temporal/calendar/index.js.map +1 -0
- package/dist/cjs/modules/temporal/common/constants.d.ts +14 -3
- package/dist/cjs/modules/temporal/common/constants.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/common/constants.js +23 -4
- package/dist/cjs/modules/temporal/common/constants.js.map +1 -1
- package/dist/cjs/modules/temporal/common/types.d.ts +258 -5
- package/dist/cjs/modules/temporal/common/types.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/{duration.d.ts → duration/duration.d.ts} +9 -2
- package/dist/cjs/modules/temporal/duration/duration.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/duration/duration.js +135 -0
- package/dist/cjs/modules/temporal/duration/duration.js.map +1 -0
- package/dist/cjs/modules/temporal/duration/index.d.ts +2 -0
- package/dist/cjs/modules/temporal/duration/index.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/duration/index.js +18 -0
- package/dist/cjs/modules/temporal/duration/index.js.map +1 -0
- package/dist/cjs/modules/temporal/helper.d.ts +105 -77
- package/dist/cjs/modules/temporal/helper.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/helper.js +209 -258
- package/dist/cjs/modules/temporal/helper.js.map +1 -1
- package/dist/cjs/modules/temporal/index.d.ts +1 -0
- package/dist/cjs/modules/temporal/index.d.ts.map +1 -1
- package/dist/cjs/modules/temporal/index.js +1 -0
- package/dist/cjs/modules/temporal/index.js.map +1 -1
- package/dist/cjs/modules/temporal/locale/index.d.ts +2 -0
- package/dist/cjs/modules/temporal/locale/index.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/locale/index.js +18 -0
- package/dist/cjs/modules/temporal/locale/index.js.map +1 -0
- package/dist/{esm/modules/temporal → cjs/modules/temporal/locale}/locale.d.ts +3 -2
- package/dist/cjs/modules/temporal/locale/locale.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/{locale.js → locale/locale.js} +3 -3
- package/dist/cjs/modules/temporal/locale/locale.js.map +1 -0
- package/dist/cjs/modules/temporal/pattern/common/index.d.ts +2 -0
- package/dist/cjs/modules/temporal/pattern/common/index.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/pattern/common/index.js +18 -0
- package/dist/cjs/modules/temporal/pattern/common/index.js.map +1 -0
- package/dist/cjs/modules/temporal/pattern/common/types.d.ts +26 -0
- package/dist/cjs/modules/temporal/pattern/common/types.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/pattern/common/types.js +3 -0
- package/dist/cjs/modules/temporal/pattern/common/types.js.map +1 -0
- package/dist/cjs/modules/temporal/pattern/index.d.ts +4 -0
- package/dist/cjs/modules/temporal/pattern/index.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/pattern/index.js +20 -0
- package/dist/cjs/modules/temporal/pattern/index.js.map +1 -0
- package/dist/{esm/modules/temporal → cjs/modules/temporal/pattern}/pattern.d.ts +2 -1
- package/dist/cjs/modules/temporal/pattern/pattern.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/{pattern.js → pattern/pattern.js} +19 -14
- package/dist/cjs/modules/temporal/pattern/pattern.js.map +1 -0
- package/dist/cjs/modules/temporal/pattern/tokens.d.ts +59 -0
- package/dist/cjs/modules/temporal/pattern/tokens.d.ts.map +1 -0
- package/dist/cjs/modules/temporal/pattern/tokens.js +195 -0
- package/dist/cjs/modules/temporal/pattern/tokens.js.map +1 -0
- package/dist/esm/modules/temporal/abstract.d.ts +295 -0
- package/dist/esm/modules/temporal/abstract.d.ts.map +1 -0
- package/dist/esm/modules/temporal/abstract.js +326 -0
- package/dist/esm/modules/temporal/abstract.js.map +1 -0
- package/dist/esm/modules/temporal/adapters/dayjs.d.ts +1 -1
- package/dist/esm/modules/temporal/adapters/dayjs.d.ts.map +1 -1
- package/dist/esm/modules/temporal/adapters/dayjs.js +3 -3
- package/dist/esm/modules/temporal/adapters/dayjs.js.map +1 -1
- package/dist/esm/modules/temporal/adapters/intl.d.ts +1 -1
- package/dist/esm/modules/temporal/adapters/intl.d.ts.map +1 -1
- package/dist/esm/modules/temporal/adapters/intl.js +7 -7
- package/dist/esm/modules/temporal/adapters/intl.js.map +1 -1
- package/dist/esm/modules/temporal/adapters/luxon.d.ts +1 -1
- package/dist/esm/modules/temporal/adapters/luxon.d.ts.map +1 -1
- package/dist/esm/modules/temporal/adapters/luxon.js +3 -3
- package/dist/esm/modules/temporal/adapters/luxon.js.map +1 -1
- package/dist/esm/modules/temporal/adapters/native.d.ts +3 -1
- package/dist/esm/modules/temporal/adapters/native.d.ts.map +1 -1
- package/dist/esm/modules/temporal/adapters/native.js +13 -5
- package/dist/esm/modules/temporal/adapters/native.js.map +1 -1
- package/dist/esm/modules/temporal/calendar/calendar.d.ts +56 -0
- package/dist/esm/modules/temporal/calendar/calendar.d.ts.map +1 -0
- package/dist/esm/modules/temporal/calendar/calendar.js +162 -0
- package/dist/esm/modules/temporal/calendar/calendar.js.map +1 -0
- package/dist/esm/modules/temporal/calendar/index.d.ts +2 -0
- package/dist/esm/modules/temporal/calendar/index.d.ts.map +1 -0
- package/dist/esm/modules/temporal/calendar/index.js +2 -0
- package/dist/esm/modules/temporal/calendar/index.js.map +1 -0
- package/dist/esm/modules/temporal/common/constants.d.ts +14 -3
- package/dist/esm/modules/temporal/common/constants.d.ts.map +1 -1
- package/dist/esm/modules/temporal/common/constants.js +21 -3
- package/dist/esm/modules/temporal/common/constants.js.map +1 -1
- package/dist/esm/modules/temporal/common/types.d.ts +258 -5
- package/dist/esm/modules/temporal/common/types.d.ts.map +1 -1
- package/dist/esm/modules/temporal/{duration.d.ts → duration/duration.d.ts} +9 -2
- package/dist/esm/modules/temporal/duration/duration.d.ts.map +1 -0
- package/dist/esm/modules/temporal/duration/duration.js +131 -0
- package/dist/esm/modules/temporal/duration/duration.js.map +1 -0
- package/dist/esm/modules/temporal/duration/index.d.ts +2 -0
- package/dist/esm/modules/temporal/duration/index.d.ts.map +1 -0
- package/dist/esm/modules/temporal/duration/index.js +2 -0
- package/dist/esm/modules/temporal/duration/index.js.map +1 -0
- package/dist/esm/modules/temporal/helper.d.ts +105 -77
- package/dist/esm/modules/temporal/helper.d.ts.map +1 -1
- package/dist/esm/modules/temporal/helper.js +214 -263
- package/dist/esm/modules/temporal/helper.js.map +1 -1
- package/dist/esm/modules/temporal/index.d.ts +1 -0
- package/dist/esm/modules/temporal/index.d.ts.map +1 -1
- package/dist/esm/modules/temporal/index.js +1 -0
- package/dist/esm/modules/temporal/index.js.map +1 -1
- package/dist/esm/modules/temporal/locale/index.d.ts +2 -0
- package/dist/esm/modules/temporal/locale/index.d.ts.map +1 -0
- package/dist/esm/modules/temporal/locale/index.js +2 -0
- package/dist/esm/modules/temporal/locale/index.js.map +1 -0
- package/dist/{cjs/modules/temporal → esm/modules/temporal/locale}/locale.d.ts +3 -2
- package/dist/esm/modules/temporal/locale/locale.d.ts.map +1 -0
- package/dist/esm/modules/temporal/{locale.js → locale/locale.js} +3 -3
- package/dist/esm/modules/temporal/locale/locale.js.map +1 -0
- package/dist/esm/modules/temporal/pattern/common/index.d.ts +2 -0
- package/dist/esm/modules/temporal/pattern/common/index.d.ts.map +1 -0
- package/dist/esm/modules/temporal/pattern/common/index.js +2 -0
- package/dist/esm/modules/temporal/pattern/common/index.js.map +1 -0
- package/dist/esm/modules/temporal/pattern/common/types.d.ts +26 -0
- package/dist/esm/modules/temporal/pattern/common/types.d.ts.map +1 -0
- package/dist/esm/modules/temporal/pattern/common/types.js +2 -0
- package/dist/esm/modules/temporal/pattern/common/types.js.map +1 -0
- package/dist/esm/modules/temporal/pattern/index.d.ts +4 -0
- package/dist/esm/modules/temporal/pattern/index.d.ts.map +1 -0
- package/dist/esm/modules/temporal/pattern/index.js +4 -0
- package/dist/esm/modules/temporal/pattern/index.js.map +1 -0
- package/dist/{cjs/modules/temporal → esm/modules/temporal/pattern}/pattern.d.ts +2 -1
- package/dist/esm/modules/temporal/pattern/pattern.d.ts.map +1 -0
- package/dist/esm/modules/temporal/{pattern.js → pattern/pattern.js} +20 -15
- package/dist/esm/modules/temporal/pattern/pattern.js.map +1 -0
- package/dist/esm/modules/temporal/pattern/tokens.d.ts +59 -0
- package/dist/esm/modules/temporal/pattern/tokens.d.ts.map +1 -0
- package/dist/esm/modules/temporal/pattern/tokens.js +191 -0
- package/dist/esm/modules/temporal/pattern/tokens.js.map +1 -0
- package/package.json +2 -2
- package/dist/cjs/modules/temporal/adapters/guards.d.ts +0 -4
- package/dist/cjs/modules/temporal/adapters/guards.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/adapters/guards.js +0 -14
- package/dist/cjs/modules/temporal/adapters/guards.js.map +0 -1
- package/dist/cjs/modules/temporal/calendar.d.ts +0 -52
- package/dist/cjs/modules/temporal/calendar.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/calendar.js +0 -151
- package/dist/cjs/modules/temporal/calendar.js.map +0 -1
- package/dist/cjs/modules/temporal/duration.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/duration.js +0 -64
- package/dist/cjs/modules/temporal/duration.js.map +0 -1
- package/dist/cjs/modules/temporal/locale.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/locale.js.map +0 -1
- package/dist/cjs/modules/temporal/pattern.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/pattern.js.map +0 -1
- package/dist/cjs/modules/temporal/tokens.d.ts +0 -78
- package/dist/cjs/modules/temporal/tokens.d.ts.map +0 -1
- package/dist/cjs/modules/temporal/tokens.js +0 -145
- package/dist/cjs/modules/temporal/tokens.js.map +0 -1
- package/dist/esm/modules/temporal/adapters/guards.d.ts +0 -4
- package/dist/esm/modules/temporal/adapters/guards.d.ts.map +0 -1
- package/dist/esm/modules/temporal/adapters/guards.js +0 -10
- package/dist/esm/modules/temporal/adapters/guards.js.map +0 -1
- package/dist/esm/modules/temporal/calendar.d.ts +0 -52
- package/dist/esm/modules/temporal/calendar.d.ts.map +0 -1
- package/dist/esm/modules/temporal/calendar.js +0 -138
- package/dist/esm/modules/temporal/calendar.js.map +0 -1
- package/dist/esm/modules/temporal/duration.d.ts.map +0 -1
- package/dist/esm/modules/temporal/duration.js +0 -60
- package/dist/esm/modules/temporal/duration.js.map +0 -1
- package/dist/esm/modules/temporal/locale.d.ts.map +0 -1
- package/dist/esm/modules/temporal/locale.js.map +0 -1
- package/dist/esm/modules/temporal/pattern.d.ts.map +0 -1
- package/dist/esm/modules/temporal/pattern.js.map +0 -1
- package/dist/esm/modules/temporal/tokens.d.ts +0 -78
- package/dist/esm/modules/temporal/tokens.d.ts.map +0 -1
- package/dist/esm/modules/temporal/tokens.js +0 -133
- package/dist/esm/modules/temporal/tokens.js.map +0 -1
|
@@ -2,15 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TemporalHelper = void 0;
|
|
4
4
|
const http_1 = require("../../common/constants/http");
|
|
5
|
-
const base_1 = require("../base");
|
|
6
5
|
const error_1 = require("../error");
|
|
7
|
-
const
|
|
8
|
-
const intl_1 = require("./adapters/intl");
|
|
9
|
-
const native_1 = require("./adapters/native");
|
|
6
|
+
const abstract_1 = require("./abstract");
|
|
10
7
|
const calendar_1 = require("./calendar");
|
|
11
8
|
const constants_1 = require("./common/constants");
|
|
12
9
|
const duration_1 = require("./duration");
|
|
13
|
-
const locale_1 = require("./locale");
|
|
14
10
|
const pattern_1 = require("./pattern");
|
|
15
11
|
/** `2026-09-19`, `2026-09-19T12:00`, `2026-09-19 12:00:00.021+07:00`, `...Z` - an offset only after a time. */
|
|
16
12
|
const ISO_8601 = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(Z|[+-]\d{2}(?::?\d{2}(?::?\d{2})?)?)?)?$/i;
|
|
@@ -20,7 +16,22 @@ const DAY_MILLISECONDS = 86_400_000;
|
|
|
20
16
|
/** 0001-01-01T00:00:00.000Z and 9999-12-31T23:59:59.999Z. */
|
|
21
17
|
const MIN_INSTANT = -62_135_596_800_000;
|
|
22
18
|
const MAX_INSTANT = 253_402_300_799_999;
|
|
23
|
-
|
|
19
|
+
/** Months in each calendar unit `diff` counts by months. */
|
|
20
|
+
const MONTHS_IN = {
|
|
21
|
+
[constants_1.TemporalUnits.MONTH]: 1,
|
|
22
|
+
[constants_1.TemporalUnits.QUARTER]: 3,
|
|
23
|
+
[constants_1.TemporalUnits.YEAR]: 12,
|
|
24
|
+
};
|
|
25
|
+
/** What each wall-clock field `set` takes. The day is clamped to the month separately. */
|
|
26
|
+
const FIELD_RANGES = {
|
|
27
|
+
year: [calendar_1.TemporalCalendar.MIN_YEAR, calendar_1.TemporalCalendar.MAX_YEAR],
|
|
28
|
+
month: [1, 12],
|
|
29
|
+
day: [1, 31],
|
|
30
|
+
hour: [0, 23],
|
|
31
|
+
minute: [0, 59],
|
|
32
|
+
second: [0, 59],
|
|
33
|
+
millisecond: [0, 999],
|
|
34
|
+
};
|
|
24
35
|
/** `formatIntl` builds one formatter per locale, options and zone; capped so caller-fed options cannot grow it. */
|
|
25
36
|
const MAX_INTL_FORMATTERS = 128;
|
|
26
37
|
/** `relative` without a unit says it in the largest whole one, down to seconds. */
|
|
@@ -33,7 +44,6 @@ const RELATIVE_UNITS = [
|
|
|
33
44
|
constants_1.TemporalUnits.MINUTE,
|
|
34
45
|
constants_1.TemporalUnits.SECOND,
|
|
35
46
|
];
|
|
36
|
-
const OUT_OF_RANGE = `outside the years ${calendar_1.MIN_TEMPORAL_YEAR}-${calendar_1.MAX_TEMPORAL_YEAR}`;
|
|
37
47
|
/**
|
|
38
48
|
* Dates in one time zone, through whichever library you choose: pass an adapter - the runtime's
|
|
39
49
|
* `Temporal` (the default where the runtime has it, `Intl` everywhere else), your own dayjs, your own Luxon. The adapter only reports a zone's UTC
|
|
@@ -44,179 +54,40 @@ const OUT_OF_RANGE = `outside the years ${calendar_1.MIN_TEMPORAL_YEAR}-${calend
|
|
|
44
54
|
* swapping the adapter never touches a call site. The zone is yours to set: without one this helper
|
|
45
55
|
* computes in UTC, never in the host's zone. Years run from 1 to 9999.
|
|
46
56
|
*/
|
|
47
|
-
class TemporalHelper extends
|
|
48
|
-
/** Validated once per process: `Intl` answers the same for a zone name every time. */
|
|
49
|
-
static { this.knownTimeZones = new Set(); }
|
|
57
|
+
class TemporalHelper extends abstract_1.AbstractTemporalHelper {
|
|
50
58
|
static { this.intlFormatters = new Map(); }
|
|
51
59
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
60
|
+
* A date picker hands back a `Date` meaning "this wall clock in the host's zone". This returns the
|
|
61
|
+
* instant that shows the same year, month, day and time in the helper's zone. `sourceTz` defaults
|
|
62
|
+
* to the host's. A skipped wall time resolves forward, a repeated one to the earlier instant.
|
|
54
63
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
fromWallClock(opts) {
|
|
65
|
+
return this.moveWallClock({
|
|
66
|
+
value: opts.value,
|
|
67
|
+
from: opts.sourceTz ?? TemporalHelper.getHostTz(),
|
|
68
|
+
to: this.resolveTz({ tz: opts.tz }),
|
|
60
69
|
});
|
|
61
|
-
this.locale = TemporalHelper.ensureLocale({ locale: opts?.locale ?? constants_1.DEFAULT_TEMPORAL_LOCALE });
|
|
62
|
-
this.adapter = opts?.adapter ?? TemporalHelper.defaultAdapter();
|
|
63
|
-
}
|
|
64
|
-
/** The runtime's `Temporal` where it has one; `Intl`, which every runtime has, everywhere else. */
|
|
65
|
-
static defaultAdapter() {
|
|
66
|
-
return (0, guards_1.isTemporalNamespace)(Reflect.get(globalThis, 'Temporal'))
|
|
67
|
-
? new native_1.NativeTemporalAdapter()
|
|
68
|
-
: new intl_1.IntlTemporalAdapter();
|
|
69
|
-
}
|
|
70
|
-
static ensureLocale(opts) {
|
|
71
|
-
locale_1.TemporalLocale.of({ locale: opts.locale });
|
|
72
|
-
return opts.locale;
|
|
73
|
-
}
|
|
74
|
-
/** A parse or input error the caller may treat as "not a date"; anything else is a bug and still throws. */
|
|
75
|
-
static isRefusal(error) {
|
|
76
|
-
return (0, error_1.isApplicationError)(error) && error.statusCode === http_1.HTTP.ResultCodes.RS_4.BadRequest;
|
|
77
|
-
}
|
|
78
|
-
static ensureTimeZone(opts) {
|
|
79
|
-
const { timeZone, statusCode } = opts;
|
|
80
|
-
if (TemporalHelper.knownTimeZones.has(timeZone)) {
|
|
81
|
-
return timeZone;
|
|
82
|
-
}
|
|
83
|
-
try {
|
|
84
|
-
new Intl.DateTimeFormat('en-US', { timeZone });
|
|
85
|
-
}
|
|
86
|
-
catch (error) {
|
|
87
|
-
throw (0, error_1.getError)({
|
|
88
|
-
statusCode,
|
|
89
|
-
message: `[TemporalHelper] unknown time zone '${timeZone}' | ${error instanceof Error ? error.message : String(error)}`,
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
if (TemporalHelper.knownTimeZones.size < MAX_KNOWN_TIME_ZONES) {
|
|
93
|
-
TemporalHelper.knownTimeZones.add(timeZone);
|
|
94
|
-
}
|
|
95
|
-
return timeZone;
|
|
96
|
-
}
|
|
97
|
-
static ensureUnit(opts) {
|
|
98
|
-
const { unit, amount } = opts;
|
|
99
|
-
if (!constants_1.TemporalUnits.isValid(unit)) {
|
|
100
|
-
throw (0, error_1.getError)({
|
|
101
|
-
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
102
|
-
message: `[TemporalHelper] unknown unit '${unit}' | Supported: ${[...constants_1.TemporalUnits.SCHEME_SET].join(', ')}`,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
if (amount !== undefined && !Number.isInteger(amount)) {
|
|
106
|
-
throw (0, error_1.getError)({
|
|
107
|
-
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
108
|
-
message: `[TemporalHelper] amount must be an integer - received ${amount}`,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
/** Every result passes here: an overflowing `add` is refused, never an Invalid Date. */
|
|
113
|
-
static ensureInstant(opts) {
|
|
114
|
-
const { epoch } = opts;
|
|
115
|
-
if (!(epoch >= MIN_INSTANT && epoch <= MAX_INSTANT)) {
|
|
116
|
-
throw (0, error_1.getError)({
|
|
117
|
-
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
118
|
-
message: `[TemporalHelper] ${Number.isNaN(epoch) ? 'invalid date' : OUT_OF_RANGE} - received ${epoch}`,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
return new Date(epoch);
|
|
122
|
-
}
|
|
123
|
-
static ensureYear(opts) {
|
|
124
|
-
if (!(0, calendar_1.isSupportedYear)(opts.parts.year)) {
|
|
125
|
-
throw (0, error_1.getError)({
|
|
126
|
-
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
127
|
-
message: `[TemporalHelper] year ${opts.parts.year} is ${OUT_OF_RANGE}`,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
resolveTimeZone(opts) {
|
|
132
|
-
return opts.timeZone === undefined
|
|
133
|
-
? this.timeZone
|
|
134
|
-
: TemporalHelper.ensureTimeZone({
|
|
135
|
-
timeZone: opts.timeZone,
|
|
136
|
-
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
/** The adapter's one answer, rounded: an offset is whole milliseconds, a library's float may not be. */
|
|
140
|
-
offsetAt(opts) {
|
|
141
|
-
return Math.round(this.adapter.getOffsetMilliseconds({ value: new Date(opts.epoch), timeZone: opts.timeZone }));
|
|
142
|
-
}
|
|
143
|
-
zonedParts(opts) {
|
|
144
|
-
const parts = (0, calendar_1.wallClockAt)({ epoch: opts.epoch, offsetMilliseconds: this.offsetAt(opts) });
|
|
145
|
-
TemporalHelper.ensureYear({ parts });
|
|
146
|
-
return parts;
|
|
147
70
|
}
|
|
148
71
|
/**
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* read with the offset from before the jump, so it moves past the gap.
|
|
72
|
+
* The reverse of `fromWallClock`, to feed a picker: a `Date` whose wall clock in `targetTz` (default:
|
|
73
|
+
* the host's) reads what the helper's zone reads for `value`.
|
|
152
74
|
*/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const offsets = before === after ? [before] : [before, after];
|
|
159
|
-
const instants = [];
|
|
160
|
-
for (const offset of offsets) {
|
|
161
|
-
const candidate = local - offset;
|
|
162
|
-
if (this.offsetAt({ epoch: candidate, timeZone }) === offset) {
|
|
163
|
-
instants.push(candidate);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
instants.sort((left, right) => left - right);
|
|
167
|
-
return { instants, forward: local - before };
|
|
168
|
-
}
|
|
169
|
-
/** The instant wall-clock `parts` name: a skipped time moves forward, a repeated one takes the earlier. */
|
|
170
|
-
earliestOf(opts) {
|
|
171
|
-
const { instants, forward } = this.instantsOf(opts);
|
|
172
|
-
return instants[0] ?? forward;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* `[start, end)` of the unit holding `epoch`. A day or longer starts at its first instant. An hour
|
|
176
|
-
* or less repeats when the clock goes back, so it starts at the latest start not after `epoch`,
|
|
177
|
-
* and ends where the wall clock next shows either the following unit or this one's start again.
|
|
178
|
-
*/
|
|
179
|
-
unitBounds(opts) {
|
|
180
|
-
const { epoch, unit, timeZone } = opts;
|
|
181
|
-
const startParts = (0, calendar_1.truncateTo)({ parts: this.zonedParts({ epoch, timeZone }), unit });
|
|
182
|
-
const nextParts = (0, calendar_1.shiftWallClock)({ parts: startParts, amount: 1, unit });
|
|
183
|
-
TemporalHelper.ensureYear({ parts: nextParts });
|
|
184
|
-
const starts = this.instantsOf({ parts: startParts, timeZone });
|
|
185
|
-
if (calendar_1.EXACT_UNIT_MILLISECONDS[unit] === undefined) {
|
|
186
|
-
const start = starts.instants[0] ?? starts.forward;
|
|
187
|
-
return { start, end: this.earliestOf({ parts: nextParts, timeZone }) };
|
|
188
|
-
}
|
|
189
|
-
const started = starts.instants.filter(instant => instant <= epoch);
|
|
190
|
-
const start = started.at(-1) ?? starts.instants[0] ?? starts.forward;
|
|
191
|
-
const nexts = this.instantsOf({ parts: nextParts, timeZone });
|
|
192
|
-
const following = nexts.instants.find(instant => instant > start) ?? nexts.forward;
|
|
193
|
-
const repeated = starts.instants.find(instant => instant > start);
|
|
194
|
-
return { start, end: repeated === undefined ? following : Math.min(repeated, following) };
|
|
195
|
-
}
|
|
196
|
-
getTimeZone() {
|
|
197
|
-
return this.timeZone;
|
|
198
|
-
}
|
|
199
|
-
getLocale() {
|
|
200
|
-
return this.locale;
|
|
201
|
-
}
|
|
202
|
-
now() {
|
|
203
|
-
return new Date();
|
|
204
|
-
}
|
|
205
|
-
/** The instant a value names. An ISO string without an offset is read as wall clock in the zone. */
|
|
206
|
-
toDate(opts) {
|
|
207
|
-
const { value } = opts;
|
|
208
|
-
if (typeof value === 'string') {
|
|
209
|
-
return this.parse({ value, timeZone: opts.timeZone });
|
|
210
|
-
}
|
|
211
|
-
return TemporalHelper.ensureInstant({
|
|
212
|
-
epoch: value instanceof Date ? value.getTime() : value,
|
|
75
|
+
toWallClock(opts) {
|
|
76
|
+
return this.moveWallClock({
|
|
77
|
+
value: opts.value,
|
|
78
|
+
from: this.resolveTz({ tz: opts.tz }),
|
|
79
|
+
to: opts.targetTz ?? TemporalHelper.getHostTz(),
|
|
213
80
|
});
|
|
214
81
|
}
|
|
215
|
-
/**
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
82
|
+
/** A helper like this one, with another locale or zone: same adapter, same `names`. */
|
|
83
|
+
clone(opts) {
|
|
84
|
+
return new TemporalHelper({
|
|
85
|
+
adapter: this.adapter,
|
|
86
|
+
tz: opts.tz ?? this.tz,
|
|
87
|
+
locale: opts.locale ?? this.locale,
|
|
88
|
+
names: this.names,
|
|
89
|
+
scope: this.scope,
|
|
90
|
+
});
|
|
220
91
|
}
|
|
221
92
|
/**
|
|
222
93
|
* Reads a string. With a `pattern` (`YYYY YY MM M DD D HH H mm m ss s SSS Z ZZ`, text in
|
|
@@ -225,7 +96,7 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
225
96
|
*/
|
|
226
97
|
parse(opts) {
|
|
227
98
|
const { value, pattern } = opts;
|
|
228
|
-
const
|
|
99
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
229
100
|
const read = pattern ? pattern_1.TemporalPattern.parse({ pattern, value }) : this.readIso({ value });
|
|
230
101
|
if (!read) {
|
|
231
102
|
throw (0, error_1.getError)({
|
|
@@ -235,15 +106,18 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
235
106
|
: `[TemporalHelper] '${value}' is not ISO 8601 | Pass a pattern for any other shape`,
|
|
236
107
|
});
|
|
237
108
|
}
|
|
238
|
-
if (!
|
|
109
|
+
if (!calendar_1.TemporalCalendar.isRealDateTime({ parts: read.parts })) {
|
|
239
110
|
throw (0, error_1.getError)({
|
|
240
111
|
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
241
112
|
message: `[TemporalHelper] '${value}' is not a real date and time`,
|
|
242
113
|
});
|
|
243
114
|
}
|
|
244
115
|
const epoch = read.offsetMilliseconds === undefined
|
|
245
|
-
? this.earliestOf({ parts: read.parts,
|
|
246
|
-
:
|
|
116
|
+
? this.earliestOf({ parts: read.parts, tz })
|
|
117
|
+
: calendar_1.TemporalCalendar.epochAtOffset({
|
|
118
|
+
parts: read.parts,
|
|
119
|
+
offsetMilliseconds: read.offsetMilliseconds,
|
|
120
|
+
});
|
|
247
121
|
return TemporalHelper.ensureInstant({ epoch });
|
|
248
122
|
}
|
|
249
123
|
readIso(opts) {
|
|
@@ -280,9 +154,9 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
280
154
|
/** `parse`, answering `null` where `parse` refuses the value. A pattern that does not compile still throws. */
|
|
281
155
|
tryParse(opts) {
|
|
282
156
|
// Outside the try: a bad zone is the caller's bug, as a broken pattern is.
|
|
283
|
-
const
|
|
157
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
284
158
|
try {
|
|
285
|
-
return this.parse({ ...opts,
|
|
159
|
+
return this.parse({ ...opts, tz });
|
|
286
160
|
}
|
|
287
161
|
catch (error) {
|
|
288
162
|
if (TemporalHelper.isRefusal(error)) {
|
|
@@ -293,35 +167,56 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
293
167
|
}
|
|
294
168
|
/** Whether the value names an instant in years 1-9999 - a string read as `parse` reads it. */
|
|
295
169
|
isValid(opts) {
|
|
296
|
-
const { value, pattern,
|
|
170
|
+
const { value, pattern, tz } = opts;
|
|
297
171
|
if (typeof value === 'string') {
|
|
298
|
-
return this.tryParse({ value, pattern,
|
|
172
|
+
return this.tryParse({ value, pattern, tz }) !== null;
|
|
173
|
+
}
|
|
174
|
+
if (!(value instanceof Date) && typeof value !== 'number') {
|
|
175
|
+
return false;
|
|
299
176
|
}
|
|
300
177
|
const epoch = value instanceof Date ? value.getTime() : value;
|
|
301
178
|
return epoch >= MIN_INSTANT && epoch <= MAX_INSTANT;
|
|
302
179
|
}
|
|
303
180
|
/**
|
|
304
|
-
* Writes the value in the zone. Without a `pattern`: ISO 8601 with the zone's offset. The
|
|
305
|
-
*
|
|
181
|
+
* Writes the value in the zone. Without a `pattern`: ISO 8601 with the zone's offset. The tokens
|
|
182
|
+
* `MMMM MMM dddd ddd dd A a hh h LL L` are spelled in `locale`. With a `fallback`, a value that is
|
|
183
|
+
* not a date - null included - writes the fallback; without one, it is a 400.
|
|
306
184
|
*/
|
|
307
185
|
format(opts) {
|
|
186
|
+
const { value, fallback } = opts;
|
|
187
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
188
|
+
const locale = opts.locale ?? this.locale;
|
|
189
|
+
let date;
|
|
190
|
+
if (fallback !== undefined) {
|
|
191
|
+
date = this.tryToDate({ value, tz });
|
|
192
|
+
}
|
|
193
|
+
else if (value === null || value === undefined) {
|
|
194
|
+
throw TemporalHelper.notADate({ value });
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
date = this.toDate({ value, tz });
|
|
198
|
+
}
|
|
199
|
+
if (date === null) {
|
|
200
|
+
return fallback ?? '';
|
|
201
|
+
}
|
|
308
202
|
return pattern_1.TemporalPattern.format({
|
|
309
203
|
pattern: opts.pattern ?? constants_1.DEFAULT_TEMPORAL_PATTERN,
|
|
310
|
-
parts: this.
|
|
311
|
-
locale
|
|
204
|
+
parts: this.zonedParts({ epoch: date.getTime(), tz }),
|
|
205
|
+
locale,
|
|
206
|
+
names: this.namesOf({ locale }),
|
|
312
207
|
});
|
|
313
208
|
}
|
|
314
209
|
/** Writes the value with `Intl.DateTimeFormat` options, in the zone - for what the pattern tokens cannot say. */
|
|
315
210
|
formatIntl(opts) {
|
|
316
|
-
const
|
|
211
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
317
212
|
const locale = opts.locale === undefined
|
|
318
213
|
? this.locale
|
|
319
214
|
: TemporalHelper.ensureLocale({ locale: opts.locale });
|
|
320
|
-
const date = this.toDate({ value: opts.value,
|
|
321
|
-
const key = `${locale}|${
|
|
215
|
+
const date = this.toDate({ value: opts.value, tz });
|
|
216
|
+
const key = `${locale}|${tz}|${JSON.stringify(opts.options ?? {})}`;
|
|
322
217
|
let formatter = TemporalHelper.intlFormatters.get(key);
|
|
323
218
|
if (!formatter) {
|
|
324
|
-
formatter = new Intl.DateTimeFormat(locale, { ...opts.options, timeZone });
|
|
219
|
+
formatter = new Intl.DateTimeFormat(locale, { ...opts.options, timeZone: tz });
|
|
325
220
|
if (TemporalHelper.intlFormatters.size < MAX_INTL_FORMATTERS) {
|
|
326
221
|
TemporalHelper.intlFormatters.set(key, formatter);
|
|
327
222
|
}
|
|
@@ -336,19 +231,21 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
336
231
|
add(opts) {
|
|
337
232
|
const { amount, unit } = opts;
|
|
338
233
|
TemporalHelper.ensureUnit({ unit, amount });
|
|
339
|
-
const
|
|
340
|
-
const date = this.toDate({ value: opts.value,
|
|
234
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
235
|
+
const date = this.toDate({ value: opts.value, tz });
|
|
341
236
|
if (amount === 0) {
|
|
342
237
|
return date;
|
|
343
238
|
}
|
|
344
|
-
const exact = calendar_1.EXACT_UNIT_MILLISECONDS[unit];
|
|
239
|
+
const exact = calendar_1.TemporalCalendar.EXACT_UNIT_MILLISECONDS[unit];
|
|
345
240
|
if (exact !== undefined) {
|
|
346
241
|
return TemporalHelper.ensureInstant({ epoch: date.getTime() + amount * exact });
|
|
347
242
|
}
|
|
348
|
-
const parts =
|
|
349
|
-
|
|
243
|
+
const parts = calendar_1.TemporalCalendar.wallClockOf({
|
|
244
|
+
parts: this.zonedParts({ epoch: date.getTime(), tz }),
|
|
245
|
+
});
|
|
246
|
+
const shifted = calendar_1.TemporalCalendar.shift({ parts, amount, unit });
|
|
350
247
|
TemporalHelper.ensureYear({ parts: shifted });
|
|
351
|
-
return TemporalHelper.ensureInstant({ epoch: this.earliestOf({ parts: shifted,
|
|
248
|
+
return TemporalHelper.ensureInstant({ epoch: this.earliestOf({ parts: shifted, tz }) });
|
|
352
249
|
}
|
|
353
250
|
subtract(opts) {
|
|
354
251
|
return this.add({ ...opts, amount: -opts.amount });
|
|
@@ -357,24 +254,24 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
357
254
|
startOf(opts) {
|
|
358
255
|
const { unit } = opts;
|
|
359
256
|
TemporalHelper.ensureUnit({ unit });
|
|
360
|
-
const
|
|
361
|
-
const date = this.toDate({ value: opts.value,
|
|
257
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
258
|
+
const date = this.toDate({ value: opts.value, tz });
|
|
362
259
|
if (unit === constants_1.TemporalUnits.MILLISECOND) {
|
|
363
260
|
return date;
|
|
364
261
|
}
|
|
365
|
-
const { start } = this.unitBounds({ epoch: date.getTime(), unit,
|
|
262
|
+
const { start } = this.unitBounds({ epoch: date.getTime(), unit, tz });
|
|
366
263
|
return TemporalHelper.ensureInstant({ epoch: start });
|
|
367
264
|
}
|
|
368
265
|
/** The last millisecond of the unit containing the value, in the zone. */
|
|
369
266
|
endOf(opts) {
|
|
370
267
|
const { unit } = opts;
|
|
371
268
|
TemporalHelper.ensureUnit({ unit });
|
|
372
|
-
const
|
|
373
|
-
const date = this.toDate({ value: opts.value,
|
|
269
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
270
|
+
const date = this.toDate({ value: opts.value, tz });
|
|
374
271
|
if (unit === constants_1.TemporalUnits.MILLISECOND) {
|
|
375
272
|
return date;
|
|
376
273
|
}
|
|
377
|
-
const { end } = this.unitBounds({ epoch: date.getTime(), unit,
|
|
274
|
+
const { end } = this.unitBounds({ epoch: date.getTime(), unit, tz });
|
|
378
275
|
return TemporalHelper.ensureInstant({ epoch: end - 1 });
|
|
379
276
|
}
|
|
380
277
|
/** Monday to Friday, read on the wall clock of the zone. */
|
|
@@ -392,70 +289,118 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
392
289
|
value: opts.value,
|
|
393
290
|
amount: opts.step,
|
|
394
291
|
unit: constants_1.TemporalUnits.DAY,
|
|
395
|
-
|
|
292
|
+
tz: opts.tz,
|
|
396
293
|
});
|
|
397
|
-
while (!this.isWeekday({ value: candidate,
|
|
294
|
+
while (!this.isWeekday({ value: candidate, tz: opts.tz })) {
|
|
398
295
|
candidate = this.add({
|
|
399
296
|
value: candidate,
|
|
400
297
|
amount: opts.step,
|
|
401
298
|
unit: constants_1.TemporalUnits.DAY,
|
|
402
|
-
|
|
299
|
+
tz: opts.tz,
|
|
403
300
|
});
|
|
404
301
|
}
|
|
405
302
|
return candidate;
|
|
406
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* The value with wall-clock fields replaced in the zone - `{ hour: 9, minute: 0 }` is 09:00 that day.
|
|
306
|
+
* `month` is 1-12. The day is clamped to the month's last day, so setting February on the 31st
|
|
307
|
+
* lands on the 28th or 29th. A wall time a daylight-saving jump skips resolves forward, as `parse` does.
|
|
308
|
+
*/
|
|
309
|
+
set(opts) {
|
|
310
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
311
|
+
const date = this.toDate({ value: opts.value, tz });
|
|
312
|
+
const wall = calendar_1.TemporalCalendar.wallClockOf({
|
|
313
|
+
parts: this.zonedParts({ epoch: date.getTime(), tz }),
|
|
314
|
+
});
|
|
315
|
+
const next = { ...wall };
|
|
316
|
+
for (const [field, [min, max]] of Object.entries(FIELD_RANGES)) {
|
|
317
|
+
const given = Reflect.get(opts, field);
|
|
318
|
+
if (given === undefined) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (typeof given !== 'number' || !Number.isInteger(given) || given < min || given > max) {
|
|
322
|
+
throw (0, error_1.getError)({
|
|
323
|
+
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
324
|
+
message: `[TemporalHelper] ${field} must be an integer from ${min} to ${max} - received ${String(given)}`,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
Reflect.set(next, field, given);
|
|
328
|
+
}
|
|
329
|
+
next.day = Math.min(next.day, calendar_1.TemporalCalendar.daysInMonth({ year: next.year, month: next.month }));
|
|
330
|
+
return TemporalHelper.ensureInstant({ epoch: this.earliestOf({ parts: next, tz }) });
|
|
331
|
+
}
|
|
332
|
+
/** `value` is before `other` - at the unit's granularity in the zone when `unit` is given. */
|
|
333
|
+
isBefore(opts) {
|
|
334
|
+
return this.compare(opts) < 0;
|
|
335
|
+
}
|
|
336
|
+
isAfter(opts) {
|
|
337
|
+
return this.compare(opts) > 0;
|
|
338
|
+
}
|
|
339
|
+
/** In the same unit - `unit: 'day'` is the same calendar day in the zone. */
|
|
340
|
+
isSame(opts) {
|
|
341
|
+
return this.compare(opts) === 0;
|
|
342
|
+
}
|
|
343
|
+
isSameOrBefore(opts) {
|
|
344
|
+
return this.compare(opts) <= 0;
|
|
345
|
+
}
|
|
346
|
+
isSameOrAfter(opts) {
|
|
347
|
+
return this.compare(opts) >= 0;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Whether `value` lies between `from` and `to`, in either order. `inclusivity` says which ends count:
|
|
351
|
+
* `()` (the default) neither, `[]` both, `[)` the start, `(]` the end.
|
|
352
|
+
*/
|
|
353
|
+
isBetween(opts) {
|
|
354
|
+
const { value, from, to, unit, inclusivity = constants_1.TemporalInclusivities.EXCLUSIVE, tz } = opts;
|
|
355
|
+
if (!constants_1.TemporalInclusivities.isValid(inclusivity)) {
|
|
356
|
+
throw (0, error_1.getError)({
|
|
357
|
+
statusCode: http_1.HTTP.ResultCodes.RS_4.BadRequest,
|
|
358
|
+
message: `[TemporalHelper] unknown inclusivity '${inclusivity}' | Supported: ${[...constants_1.TemporalInclusivities.SCHEME_SET].join(', ')}`,
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
const isStartIncluded = inclusivity.startsWith('[');
|
|
362
|
+
const isEndIncluded = inclusivity.endsWith(']');
|
|
363
|
+
const fromOrder = this.compare({ value, other: from, unit, tz });
|
|
364
|
+
const toOrder = this.compare({ value, other: to, unit, tz });
|
|
365
|
+
const isAfterStart = isStartIncluded ? fromOrder >= 0 : fromOrder > 0;
|
|
366
|
+
const isBeforeEnd = isEndIncluded ? toOrder <= 0 : toOrder < 0;
|
|
367
|
+
// The range given backwards: `to` is the earlier end.
|
|
368
|
+
const isAfterEnd = isEndIncluded ? toOrder >= 0 : toOrder > 0;
|
|
369
|
+
const isBeforeStart = isStartIncluded ? fromOrder <= 0 : fromOrder < 0;
|
|
370
|
+
return (isAfterStart && isBeforeEnd) || (isAfterEnd && isBeforeStart);
|
|
371
|
+
}
|
|
407
372
|
/**
|
|
408
373
|
* How many whole units `value` is past `other` - negative when it is before - truncated toward
|
|
409
|
-
* zero. Hours and smaller
|
|
410
|
-
*
|
|
411
|
-
*
|
|
374
|
+
* zero, counted as dayjs counts. Hours and smaller are elapsed time. Days and weeks are calendar
|
|
375
|
+
* days in the zone: the wall clocks' difference, so a 23-hour daylight-saving day is one day.
|
|
376
|
+
* Months, quarters and years are anchored on the date with the later day of the month, then
|
|
377
|
+
* truncated, so `diff(a, b)` is always `-diff(b, a)`.
|
|
412
378
|
*/
|
|
413
379
|
diff(opts) {
|
|
414
380
|
const { unit } = opts;
|
|
415
381
|
TemporalHelper.ensureUnit({ unit });
|
|
416
|
-
const
|
|
417
|
-
const value = this.toDate({ value: opts.value,
|
|
418
|
-
const other = this.toDate({ value: opts.other,
|
|
419
|
-
|
|
382
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
383
|
+
const value = this.toDate({ value: opts.value, tz }).getTime();
|
|
384
|
+
const other = this.toDate({ value: opts.other, tz }).getTime();
|
|
385
|
+
// `+ 0` turns a truncated `-0` into `0`.
|
|
386
|
+
const exact = calendar_1.TemporalCalendar.EXACT_UNIT_MILLISECONDS[unit];
|
|
420
387
|
if (exact !== undefined) {
|
|
421
|
-
// `+ 0` turns a truncated `-0` into `0`.
|
|
422
388
|
return Math.trunc((value - other) / exact) + 0;
|
|
423
389
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
(0, calendar_1.epochAtOffset)({ parts: (0, calendar_1.wallClockOf)({ parts: earlier }), offsetMilliseconds: 0 })) /
|
|
439
|
-
DAY_MILLISECONDS);
|
|
440
|
-
guess = unit === constants_1.TemporalUnits.WEEK ? Math.trunc(days / 7) : Math.trunc(days);
|
|
441
|
-
}
|
|
442
|
-
const direction = Math.sign(value - other);
|
|
443
|
-
const start = (0, calendar_1.wallClockOf)({ parts: earlier });
|
|
444
|
-
const passes = (amount) => {
|
|
445
|
-
// A move past years 1-9999 passes every value inside them, and `add` would refuse it.
|
|
446
|
-
if (!(0, calendar_1.isSupportedYear)((0, calendar_1.shiftWallClock)({ parts: start, amount, unit }).year)) {
|
|
447
|
-
return true;
|
|
448
|
-
}
|
|
449
|
-
const moved = this.add({ value: other, amount, unit, timeZone }).getTime();
|
|
450
|
-
return direction > 0 ? moved > value : moved < value;
|
|
451
|
-
};
|
|
452
|
-
while (guess !== 0 && passes(guess)) {
|
|
453
|
-
guess -= direction;
|
|
454
|
-
}
|
|
455
|
-
while (!passes(guess + direction)) {
|
|
456
|
-
guess += direction;
|
|
457
|
-
}
|
|
458
|
-
return guess + 0;
|
|
390
|
+
const months = MONTHS_IN[unit];
|
|
391
|
+
if (months !== undefined) {
|
|
392
|
+
return Math.trunc(this.monthGap({ value, other, tz }) / months) + 0;
|
|
393
|
+
}
|
|
394
|
+
const wallClocks = calendar_1.TemporalCalendar.epochAtOffset({
|
|
395
|
+
parts: calendar_1.TemporalCalendar.wallClockOf({ parts: this.zonedParts({ epoch: value, tz }) }),
|
|
396
|
+
offsetMilliseconds: 0,
|
|
397
|
+
}) -
|
|
398
|
+
calendar_1.TemporalCalendar.epochAtOffset({
|
|
399
|
+
parts: calendar_1.TemporalCalendar.wallClockOf({ parts: this.zonedParts({ epoch: other, tz }) }),
|
|
400
|
+
offsetMilliseconds: 0,
|
|
401
|
+
});
|
|
402
|
+
const days = wallClocks / DAY_MILLISECONDS;
|
|
403
|
+
return Math.trunc(unit === constants_1.TemporalUnits.WEEK ? days / 7 : days) + 0;
|
|
459
404
|
}
|
|
460
405
|
/**
|
|
461
406
|
* `-1`, `0` or `1` as `value` is before, in, or after the unit that holds `other`, in the zone.
|
|
@@ -463,13 +408,13 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
463
408
|
*/
|
|
464
409
|
compare(opts) {
|
|
465
410
|
const { unit } = opts;
|
|
466
|
-
const
|
|
411
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
467
412
|
const value = unit === undefined
|
|
468
|
-
? this.toDate({ value: opts.value,
|
|
469
|
-
: this.startOf({ value: opts.value, unit,
|
|
413
|
+
? this.toDate({ value: opts.value, tz })
|
|
414
|
+
: this.startOf({ value: opts.value, unit, tz });
|
|
470
415
|
const other = unit === undefined
|
|
471
|
-
? this.toDate({ value: opts.other,
|
|
472
|
-
: this.startOf({ value: opts.other, unit,
|
|
416
|
+
? this.toDate({ value: opts.other, tz })
|
|
417
|
+
: this.startOf({ value: opts.other, unit, tz });
|
|
473
418
|
const delta = value.getTime() - other.getTime();
|
|
474
419
|
return delta < 0 ? -1 : delta > 0 ? 1 : 0;
|
|
475
420
|
}
|
|
@@ -481,12 +426,12 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
481
426
|
*/
|
|
482
427
|
relative(opts) {
|
|
483
428
|
const { unit, numeric = 'always', style = 'long' } = opts;
|
|
484
|
-
const
|
|
429
|
+
const tz = this.resolveTz({ tz: opts.tz });
|
|
485
430
|
const locale = opts.locale === undefined
|
|
486
431
|
? this.locale
|
|
487
432
|
: TemporalHelper.ensureLocale({ locale: opts.locale });
|
|
488
|
-
const value = this.toDate({ value: opts.value,
|
|
489
|
-
const base = opts.base === undefined ? this.now() : this.toDate({ value: opts.base,
|
|
433
|
+
const value = this.toDate({ value: opts.value, tz });
|
|
434
|
+
const base = opts.base === undefined ? this.now() : this.toDate({ value: opts.base, tz });
|
|
490
435
|
let amount = 0;
|
|
491
436
|
let said = constants_1.TemporalUnits.SECOND;
|
|
492
437
|
if (unit !== undefined) {
|
|
@@ -498,16 +443,16 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
498
443
|
});
|
|
499
444
|
}
|
|
500
445
|
amount = this.diff({
|
|
501
|
-
value: this.startOf({ value, unit,
|
|
502
|
-
other: this.startOf({ value: base, unit,
|
|
446
|
+
value: this.startOf({ value, unit, tz }),
|
|
447
|
+
other: this.startOf({ value: base, unit, tz }),
|
|
503
448
|
unit,
|
|
504
|
-
|
|
449
|
+
tz,
|
|
505
450
|
});
|
|
506
451
|
said = unit;
|
|
507
452
|
}
|
|
508
453
|
else {
|
|
509
454
|
for (const candidate of RELATIVE_UNITS) {
|
|
510
|
-
const counted = this.diff({ value, other: base, unit: candidate,
|
|
455
|
+
const counted = this.diff({ value, other: base, unit: candidate, tz });
|
|
511
456
|
if (counted !== 0 || candidate === constants_1.TemporalUnits.SECOND) {
|
|
512
457
|
amount = counted;
|
|
513
458
|
said = candidate;
|
|
@@ -529,7 +474,13 @@ class TemporalHelper extends base_1.BaseHelper {
|
|
|
529
474
|
const locale = opts.locale === undefined
|
|
530
475
|
? this.locale
|
|
531
476
|
: TemporalHelper.ensureLocale({ locale: opts.locale });
|
|
532
|
-
return duration_1.TemporalDuration.format({
|
|
477
|
+
return duration_1.TemporalDuration.format({
|
|
478
|
+
milliseconds: opts.milliseconds,
|
|
479
|
+
style: opts.style,
|
|
480
|
+
pattern: opts.pattern,
|
|
481
|
+
maxUnits: opts.maxUnits,
|
|
482
|
+
locale,
|
|
483
|
+
});
|
|
533
484
|
}
|
|
534
485
|
}
|
|
535
486
|
exports.TemporalHelper = TemporalHelper;
|