temporal-fmt 0.9.2 → 0.9.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/README.md +480 -9
- package/dist/calendarUtils.cjs +259 -4
- package/dist/calendarUtils.cjs.map +1 -1
- package/dist/calendarUtils.js +33 -1
- package/dist/chunk-4N3WCGEY.js +183 -0
- package/dist/{chunk-4JWGUR4O.js.map → chunk-4N3WCGEY.js.map} +1 -1
- package/dist/chunk-5UTV5VP6.js +984 -0
- package/dist/chunk-5UTV5VP6.js.map +1 -0
- package/dist/chunk-ACKKWH5Z.js +578 -0
- package/dist/{chunk-2JHEV7ZF.js.map → chunk-ACKKWH5Z.js.map} +1 -1
- package/dist/chunk-EGUUO6LE.js +439 -0
- package/dist/chunk-EGUUO6LE.js.map +1 -0
- package/dist/chunk-FBPHNRVW.js +2939 -0
- package/dist/chunk-FBPHNRVW.js.map +1 -0
- package/dist/chunk-GPB4JHGI.js +65 -0
- package/dist/chunk-GPB4JHGI.js.map +1 -0
- package/dist/chunk-H7YQX25T.js +170 -0
- package/dist/{chunk-J2AQNXF2.js.map → chunk-H7YQX25T.js.map} +1 -1
- package/dist/chunk-HXY2GUUM.js +182 -0
- package/dist/{chunk-EHLRZULM.js.map → chunk-HXY2GUUM.js.map} +1 -1
- package/dist/chunk-L24NPTAJ.js +328 -0
- package/dist/chunk-L24NPTAJ.js.map +1 -0
- package/dist/chunk-M3GDTHMT.js +169 -0
- package/dist/chunk-M3GDTHMT.js.map +1 -0
- package/dist/chunk-MKPDLQKD.js +51 -0
- package/dist/chunk-MKPDLQKD.js.map +1 -0
- package/dist/chunk-TSLPIURC.js +242 -0
- package/dist/{chunk-VQXUMFB2.js.map → chunk-TSLPIURC.js.map} +1 -1
- package/dist/chunk-UOPAV3WX.js +75 -0
- package/dist/chunk-UOPAV3WX.js.map +1 -0
- package/dist/chunk-VNIUIQA4.js +398 -0
- package/dist/chunk-VNIUIQA4.js.map +1 -0
- package/dist/chunk-YEUASGDK.js +9 -0
- package/dist/chunk-YEUASGDK.js.map +1 -0
- package/dist/chunk-ZQZF5EXW.js +29 -0
- package/dist/chunk-ZQZF5EXW.js.map +1 -0
- package/dist/config.d.cts +4 -2
- package/dist/config.d.ts +4 -2
- package/dist/duration.cjs +638 -26
- package/dist/duration.cjs.map +1 -1
- package/dist/duration.js +28 -1
- package/dist/format.cjs +833 -35
- package/dist/format.cjs.map +1 -1
- package/dist/format.js +20 -1
- package/dist/index.cjs +7698 -163
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -24
- package/dist/index.d.ts +108 -24
- package/dist/index.js +1536 -58
- package/dist/index.js.map +1 -1
- package/dist/interval.cjs +5480 -35
- package/dist/interval.cjs.map +1 -1
- package/dist/interval.js +46 -1
- package/dist/localeRegistry.cjs +375 -32
- package/dist/localeRegistry.cjs.map +1 -1
- package/dist/localeRegistry.js +11 -1
- package/dist/modApi.d.cts +131 -0
- package/dist/modApi.d.ts +131 -0
- package/dist/parse.cjs +1797 -70
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +20 -1
- package/dist/pattern.d.cts +1 -0
- package/dist/pattern.d.ts +1 -0
- package/dist/recurrence.cjs +452 -20
- package/dist/recurrence.cjs.map +1 -1
- package/dist/recurrence.js +19 -1
- package/dist/relativeTime.cjs +268 -21
- package/dist/relativeTime.cjs.map +1 -1
- package/dist/relativeTime.js +14 -1
- package/dist/runtime.d.cts +201 -0
- package/dist/runtime.d.ts +201 -0
- package/dist/timezone.cjs +387 -20
- package/dist/timezone.cjs.map +1 -1
- package/dist/timezone.js +26 -1
- package/package.json +4 -6
- package/scripts/cli.mjs +27 -5
- package/dist/chunk-2JHEV7ZF.js +0 -7
- package/dist/chunk-3MZLTVP3.js +0 -2
- package/dist/chunk-3MZLTVP3.js.map +0 -1
- package/dist/chunk-4JWGUR4O.js +0 -11
- package/dist/chunk-5U5WJ465.js +0 -36
- package/dist/chunk-5U5WJ465.js.map +0 -1
- package/dist/chunk-C5YESWFT.js +0 -2
- package/dist/chunk-C5YESWFT.js.map +0 -1
- package/dist/chunk-C6ZZ62ET.js +0 -2
- package/dist/chunk-C6ZZ62ET.js.map +0 -1
- package/dist/chunk-EHLRZULM.js +0 -5
- package/dist/chunk-F4RGUDA3.js +0 -2
- package/dist/chunk-F4RGUDA3.js.map +0 -1
- package/dist/chunk-J2AQNXF2.js +0 -2
- package/dist/chunk-NBXF7V5B.js +0 -2
- package/dist/chunk-NBXF7V5B.js.map +0 -1
- package/dist/chunk-R52YOKI3.js +0 -7
- package/dist/chunk-R52YOKI3.js.map +0 -1
- package/dist/chunk-UJR6DHXY.js +0 -2
- package/dist/chunk-UJR6DHXY.js.map +0 -1
- package/dist/chunk-VQXUMFB2.js +0 -21
- package/dist/chunk-XH46JNPK.js +0 -2
- package/dist/chunk-XH46JNPK.js.map +0 -1
- package/dist/chunk-YB6YAG7E.js +0 -35
- package/dist/chunk-YB6YAG7E.js.map +0 -1
- package/dist/chunk-ZGMTY52O.js +0 -2
- package/dist/chunk-ZGMTY52O.js.map +0 -1
|
@@ -0,0 +1,2939 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getNextTransition,
|
|
3
|
+
getPreviousTransition,
|
|
4
|
+
possibleInstantsFor,
|
|
5
|
+
resolveZoned
|
|
6
|
+
} from "./chunk-H7YQX25T.js";
|
|
7
|
+
import {
|
|
8
|
+
balanceDuration,
|
|
9
|
+
ceil,
|
|
10
|
+
compareDuration,
|
|
11
|
+
floor,
|
|
12
|
+
formatDurationToParts,
|
|
13
|
+
formatISODuration,
|
|
14
|
+
parseDuration,
|
|
15
|
+
parseISODuration,
|
|
16
|
+
subtractDuration,
|
|
17
|
+
truncate
|
|
18
|
+
} from "./chunk-ACKKWH5Z.js";
|
|
19
|
+
import {
|
|
20
|
+
_handlerFor,
|
|
21
|
+
compileFormat,
|
|
22
|
+
format,
|
|
23
|
+
formatToParts
|
|
24
|
+
} from "./chunk-4N3WCGEY.js";
|
|
25
|
+
import {
|
|
26
|
+
getLocale,
|
|
27
|
+
hasLocale
|
|
28
|
+
} from "./chunk-UOPAV3WX.js";
|
|
29
|
+
import {
|
|
30
|
+
UNPADDED_NUMERIC_TOKENS,
|
|
31
|
+
compileParser,
|
|
32
|
+
parse
|
|
33
|
+
} from "./chunk-5UTV5VP6.js";
|
|
34
|
+
import {
|
|
35
|
+
tokenize
|
|
36
|
+
} from "./chunk-M3GDTHMT.js";
|
|
37
|
+
import {
|
|
38
|
+
DEFAULT_LOCALE,
|
|
39
|
+
TOKENS
|
|
40
|
+
} from "./chunk-L24NPTAJ.js";
|
|
41
|
+
import {
|
|
42
|
+
getTemporal
|
|
43
|
+
} from "./chunk-ZQZF5EXW.js";
|
|
44
|
+
import {
|
|
45
|
+
MAX_FORMAT_LENGTH
|
|
46
|
+
} from "./chunk-YEUASGDK.js";
|
|
47
|
+
import {
|
|
48
|
+
FormatSyntaxError,
|
|
49
|
+
InvalidDateError,
|
|
50
|
+
normalizeLocaleTag
|
|
51
|
+
} from "./chunk-EGUUO6LE.js";
|
|
52
|
+
import {
|
|
53
|
+
between,
|
|
54
|
+
clamp,
|
|
55
|
+
compare,
|
|
56
|
+
formatRRule,
|
|
57
|
+
isAfter,
|
|
58
|
+
isBefore,
|
|
59
|
+
isBetween,
|
|
60
|
+
isEqual,
|
|
61
|
+
isSameDay,
|
|
62
|
+
isSameMonth,
|
|
63
|
+
isSameQuarter,
|
|
64
|
+
isSameWeek,
|
|
65
|
+
isSameYear,
|
|
66
|
+
isToday,
|
|
67
|
+
isTomorrow,
|
|
68
|
+
isWeekday,
|
|
69
|
+
isYesterday,
|
|
70
|
+
parseRRule
|
|
71
|
+
} from "./chunk-VNIUIQA4.js";
|
|
72
|
+
import {
|
|
73
|
+
add
|
|
74
|
+
} from "./chunk-TSLPIURC.js";
|
|
75
|
+
import {
|
|
76
|
+
asDateFieldView,
|
|
77
|
+
getMonth,
|
|
78
|
+
getWeekday,
|
|
79
|
+
isLeapMonth,
|
|
80
|
+
isLeapYear,
|
|
81
|
+
monthsInYear,
|
|
82
|
+
weekOfYear,
|
|
83
|
+
weekYear
|
|
84
|
+
} from "./chunk-HXY2GUUM.js";
|
|
85
|
+
|
|
86
|
+
// src/relativeGrammar.ts
|
|
87
|
+
var MAX_REGISTERED_GRAMMARS = 100;
|
|
88
|
+
var registeredGrammars = [];
|
|
89
|
+
function registerRelativeGrammar(grammar) {
|
|
90
|
+
if (typeof grammar.language !== "string" || grammar.language.length === 0) {
|
|
91
|
+
throw new Error("temporal-fmt: registerRelativeGrammar requires a non-empty language string.");
|
|
92
|
+
}
|
|
93
|
+
if (!Array.isArray(grammar.matchers) || grammar.matchers.length === 0) {
|
|
94
|
+
throw new Error("temporal-fmt: registerRelativeGrammar requires at least one matcher.");
|
|
95
|
+
}
|
|
96
|
+
const existingIdx = registeredGrammars.findIndex((g) => g.language === grammar.language);
|
|
97
|
+
if (existingIdx >= 0) {
|
|
98
|
+
registeredGrammars[existingIdx] = grammar;
|
|
99
|
+
} else {
|
|
100
|
+
if (registeredGrammars.length >= MAX_REGISTERED_GRAMMARS) {
|
|
101
|
+
throw new RangeError(`temporal-fmt: registerRelativeGrammar reached the ${MAX_REGISTERED_GRAMMARS}-grammar limit.`);
|
|
102
|
+
}
|
|
103
|
+
registeredGrammars.push(grammar);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function tryRegisteredGrammar(language, input, reference) {
|
|
107
|
+
for (const grammar of registeredGrammars) {
|
|
108
|
+
if (grammar.language !== language) continue;
|
|
109
|
+
for (const matcher of grammar.matchers) {
|
|
110
|
+
const match = matcher(input);
|
|
111
|
+
if (match === null) continue;
|
|
112
|
+
const temporal = getTemporal();
|
|
113
|
+
if (match.resolve) {
|
|
114
|
+
const fields = match.resolve(reference);
|
|
115
|
+
return temporal.PlainDate.from(fields, { overflow: "reject" });
|
|
116
|
+
}
|
|
117
|
+
return temporal.PlainDate.from(
|
|
118
|
+
{ year: match.year ?? reference.year, month: match.month ?? reference.month, day: match.day ?? reference.day },
|
|
119
|
+
{ overflow: "reject" }
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function listRegisteredGrammars() {
|
|
126
|
+
return registeredGrammars.map((g) => g.language);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/parseRelative.ts
|
|
130
|
+
function normalizeForMatch(s) {
|
|
131
|
+
return s.toLowerCase().replace(/ä/g, "ae").replace(/ö/g, "oe").replace(/ü/g, "ue").replace(/ß/g, "ss").normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
132
|
+
}
|
|
133
|
+
function levenshtein(a, b) {
|
|
134
|
+
/* c8 ignore start @preserve -- unreachable through the only call
|
|
135
|
+
* site (fuzzyCorrectEnglish): `a` is always a word that already
|
|
136
|
+
* failed the `vocabulary.includes(word)` exact-match check, so
|
|
137
|
+
* a === b never holds against any `b` drawn from that same
|
|
138
|
+
* vocabulary; and neither `a` (split from a non-empty normalized
|
|
139
|
+
* string) nor `b` (a vocabulary entry) is ever empty. Kept as
|
|
140
|
+
* general-purpose guards in case levenshtein() gets a second caller
|
|
141
|
+
* later. */
|
|
142
|
+
if (a === b) return 0;
|
|
143
|
+
if (a.length === 0) return b.length;
|
|
144
|
+
if (b.length === 0) return a.length;
|
|
145
|
+
/* c8 ignore stop @preserve */
|
|
146
|
+
let prev = new Array(b.length + 1);
|
|
147
|
+
let curr = new Array(b.length + 1);
|
|
148
|
+
for (let j = 0; j <= b.length; j++) prev[j] = j;
|
|
149
|
+
for (let i = 1; i <= a.length; i++) {
|
|
150
|
+
curr[0] = i;
|
|
151
|
+
for (let j = 1; j <= b.length; j++) {
|
|
152
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
153
|
+
curr[j] = Math.min(
|
|
154
|
+
prev[j] + 1,
|
|
155
|
+
// deletion
|
|
156
|
+
curr[j - 1] + 1,
|
|
157
|
+
// insertion
|
|
158
|
+
prev[j - 1] + cost
|
|
159
|
+
// substitution
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
[prev, curr] = [curr, prev];
|
|
163
|
+
}
|
|
164
|
+
return prev[b.length];
|
|
165
|
+
}
|
|
166
|
+
var FUZZY_MAX_DISTANCE = 2;
|
|
167
|
+
var MAX_RELATIVE_INPUT_LENGTH = 4096;
|
|
168
|
+
var MAX_RELATIVE_WORDS = 32;
|
|
169
|
+
function buildEnglishFuzzyVocabulary() {
|
|
170
|
+
return [
|
|
171
|
+
...ENGLISH_WEEKDAYS,
|
|
172
|
+
...ENGLISH_MONTHS,
|
|
173
|
+
...ENGLISH_MONTH_SHORT,
|
|
174
|
+
"today",
|
|
175
|
+
"tomorrow",
|
|
176
|
+
"yesterday",
|
|
177
|
+
"next",
|
|
178
|
+
"last",
|
|
179
|
+
"this",
|
|
180
|
+
"in",
|
|
181
|
+
"ago",
|
|
182
|
+
"day",
|
|
183
|
+
"days",
|
|
184
|
+
"week",
|
|
185
|
+
"weeks",
|
|
186
|
+
"month",
|
|
187
|
+
"months",
|
|
188
|
+
"year",
|
|
189
|
+
"years"
|
|
190
|
+
].map(normalizeForMatch);
|
|
191
|
+
}
|
|
192
|
+
var englishFuzzyVocabulary;
|
|
193
|
+
function getEnglishFuzzyVocabulary() {
|
|
194
|
+
if (!englishFuzzyVocabulary) englishFuzzyVocabulary = Object.freeze(buildEnglishFuzzyVocabulary());
|
|
195
|
+
return englishFuzzyVocabulary;
|
|
196
|
+
}
|
|
197
|
+
function fuzzyCorrectEnglish(normalized) {
|
|
198
|
+
const vocabulary = getEnglishFuzzyVocabulary();
|
|
199
|
+
const words = normalized.split(" ");
|
|
200
|
+
if (normalized.length > MAX_RELATIVE_INPUT_LENGTH || words.length > MAX_RELATIVE_WORDS) {
|
|
201
|
+
throw new RangeError(
|
|
202
|
+
`temporal-fmt: parseRelative fuzzy input is too large (maximum ${MAX_RELATIVE_INPUT_LENGTH} characters and ${MAX_RELATIVE_WORDS} words).`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
let changed = false;
|
|
206
|
+
const corrected = words.map((word) => {
|
|
207
|
+
if (/^\d+(?:st|nd|rd|th)?$/.test(word)) return word;
|
|
208
|
+
if (vocabulary.includes(word)) return word;
|
|
209
|
+
let best;
|
|
210
|
+
let bestDist = FUZZY_MAX_DISTANCE + 1;
|
|
211
|
+
for (const candidate of vocabulary) {
|
|
212
|
+
const dist = levenshtein(word, candidate);
|
|
213
|
+
if (dist < bestDist) {
|
|
214
|
+
bestDist = dist;
|
|
215
|
+
best = candidate;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (best !== void 0 && bestDist <= FUZZY_MAX_DISTANCE) {
|
|
219
|
+
changed = true;
|
|
220
|
+
return best;
|
|
221
|
+
}
|
|
222
|
+
return word;
|
|
223
|
+
});
|
|
224
|
+
return changed ? corrected.join(" ") : void 0;
|
|
225
|
+
}
|
|
226
|
+
function readYear(reference) {
|
|
227
|
+
if (typeof reference.year !== "number") {
|
|
228
|
+
throw new Error("temporal-fmt: parseRelative reference date is missing year.");
|
|
229
|
+
}
|
|
230
|
+
return reference.year;
|
|
231
|
+
}
|
|
232
|
+
function readMonth(reference) {
|
|
233
|
+
if (typeof reference.month !== "number") {
|
|
234
|
+
throw new Error("temporal-fmt: parseRelative reference date is missing month.");
|
|
235
|
+
}
|
|
236
|
+
return reference.month;
|
|
237
|
+
}
|
|
238
|
+
function readDay(reference) {
|
|
239
|
+
if (typeof reference.day !== "number") {
|
|
240
|
+
throw new Error("temporal-fmt: parseRelative reference date is missing day.");
|
|
241
|
+
}
|
|
242
|
+
return reference.day;
|
|
243
|
+
}
|
|
244
|
+
function extractDayOfWeek(reference) {
|
|
245
|
+
const dow = reference.dayOfWeek;
|
|
246
|
+
if (typeof dow !== "number") {
|
|
247
|
+
throw new Error(
|
|
248
|
+
"temporal-fmt: parseRelative needs a reference date exposing dayOfWeek (a Temporal.PlainDate / PlainDateTime / ZonedDateTime)."
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
return dow;
|
|
252
|
+
}
|
|
253
|
+
function nameAlternation(names) {
|
|
254
|
+
const normalized = names.map(normalizeForMatch);
|
|
255
|
+
const sorted = [...normalized].sort((a, b) => b.length - a.length);
|
|
256
|
+
return sorted.map((n) => n.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|");
|
|
257
|
+
}
|
|
258
|
+
function buildPlainDate(temporal, year, month, day) {
|
|
259
|
+
return temporal.PlainDate.from({ year, month, day }, { overflow: "reject" });
|
|
260
|
+
}
|
|
261
|
+
function addDays(temporal, reference, days) {
|
|
262
|
+
const refDate = temporal.PlainDate.from({
|
|
263
|
+
year: readYear(reference),
|
|
264
|
+
month: readMonth(reference),
|
|
265
|
+
day: readDay(reference)
|
|
266
|
+
});
|
|
267
|
+
return refDate.add({ days });
|
|
268
|
+
}
|
|
269
|
+
function addUnits(temporal, reference, count, unit) {
|
|
270
|
+
const refDate = temporal.PlainDate.from({
|
|
271
|
+
year: readYear(reference),
|
|
272
|
+
month: readMonth(reference),
|
|
273
|
+
day: readDay(reference)
|
|
274
|
+
});
|
|
275
|
+
const duration = {};
|
|
276
|
+
if (unit === "day") duration.days = count;
|
|
277
|
+
if (unit === "week") duration.weeks = count;
|
|
278
|
+
if (unit === "month") duration.months = count;
|
|
279
|
+
if (unit === "year") duration.years = count;
|
|
280
|
+
return refDate.add(duration);
|
|
281
|
+
}
|
|
282
|
+
function weekdayOffset(rel, refDow, targetDow) {
|
|
283
|
+
if (rel === "next") {
|
|
284
|
+
let diff = targetDow - refDow;
|
|
285
|
+
if (diff <= 0) diff += 7;
|
|
286
|
+
return diff;
|
|
287
|
+
}
|
|
288
|
+
if (rel === "last") {
|
|
289
|
+
let diff = targetDow - refDow;
|
|
290
|
+
if (diff >= 0) diff -= 7;
|
|
291
|
+
return diff;
|
|
292
|
+
}
|
|
293
|
+
return targetDow - refDow;
|
|
294
|
+
}
|
|
295
|
+
function resolveToNextOccurrence(temporal, reference, month, day) {
|
|
296
|
+
const refYear = readYear(reference);
|
|
297
|
+
const refDate = temporal.PlainDate.from({
|
|
298
|
+
year: refYear,
|
|
299
|
+
month: readMonth(reference),
|
|
300
|
+
day: readDay(reference)
|
|
301
|
+
});
|
|
302
|
+
if (!temporal.PlainDate.compare) {
|
|
303
|
+
throw new Error("temporal-fmt: parseRelative needs Temporal.PlainDate.compare to resolve month-day phrases; the active implementation does not expose it.");
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
const thisYear = temporal.PlainDate.from({ year: refYear, month, day }, { overflow: "reject" });
|
|
307
|
+
if (temporal.PlainDate.compare(thisYear, refDate) >= 0) {
|
|
308
|
+
return thisYear;
|
|
309
|
+
}
|
|
310
|
+
return temporal.PlainDate.from({ year: refYear + 1, month, day }, { overflow: "reject" });
|
|
311
|
+
} catch (err) {
|
|
312
|
+
try {
|
|
313
|
+
return temporal.PlainDate.from({ year: refYear + 1, month, day }, { overflow: "reject" });
|
|
314
|
+
} catch {
|
|
315
|
+
throw new Error(
|
|
316
|
+
`temporal-fmt: parseRelative can't resolve month ${month} day ${day} \u2014 it isn't a valid date in either ${refYear} or ${refYear + 1}. Original error: ${err.message}`
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function weekdayIndexFromName(name, names) {
|
|
322
|
+
const normalized = normalizeForMatch(name);
|
|
323
|
+
const idx = names.findIndex((n) => normalizeForMatch(n) === normalized);
|
|
324
|
+
/* c8 ignore start @preserve -- unreachable: every caller passes a
|
|
325
|
+
* name captured by nameAlternation(names), which builds its regex
|
|
326
|
+
* alternation from this same list under the same normalizeForMatch
|
|
327
|
+
* transform. The regex can't match anything findIndex() wouldn't
|
|
328
|
+
* also find here. Defensive throw kept for the type checker and as
|
|
329
|
+
* a tripwire if that invariant ever breaks. Ignore comment sits on
|
|
330
|
+
* the `if` itself, not just the throw inside it — c8 tracks the
|
|
331
|
+
* branch outcome (was the true side ever taken) separately from the
|
|
332
|
+
* statements inside, so excluding only the inner throw still leaves
|
|
333
|
+
* the branch itself flagged as uncovered. */
|
|
334
|
+
if (idx < 0) {
|
|
335
|
+
throw new Error(`temporal-fmt: parseRelative internal error \u2014 weekday "${name}" not in names list.`);
|
|
336
|
+
}
|
|
337
|
+
/* c8 ignore stop @preserve */
|
|
338
|
+
return idx + 1;
|
|
339
|
+
}
|
|
340
|
+
function monthIndexFromName(name, longNames, shortNames = []) {
|
|
341
|
+
const normalized = normalizeForMatch(name);
|
|
342
|
+
const longIdx = longNames.findIndex((n) => normalizeForMatch(n) === normalized);
|
|
343
|
+
if (longIdx >= 0) return longIdx + 1;
|
|
344
|
+
const shortIdx = shortNames.findIndex((n) => normalizeForMatch(n) === normalized);
|
|
345
|
+
if (shortIdx >= 0) return shortIdx + 1;
|
|
346
|
+
/* c8 ignore start @preserve -- unreachable: every caller passes a name
|
|
347
|
+
* captured by nameAlternation([...longNames, ...shortNames]), so the
|
|
348
|
+
* regex alternation and these two findIndex() scans are built from
|
|
349
|
+
* the same lists under the same normalizeForMatch transform. Kept as
|
|
350
|
+
* a tripwire for the type checker in case that invariant ever breaks. */
|
|
351
|
+
throw new Error(`temporal-fmt: parseRelative internal error \u2014 month "${name}" not in names list.`);
|
|
352
|
+
/* c8 ignore stop @preserve */
|
|
353
|
+
}
|
|
354
|
+
var ENGLISH_WEEKDAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
355
|
+
var ENGLISH_MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
356
|
+
var ENGLISH_MONTH_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
357
|
+
var ENGLISH_GRAMMAR = {
|
|
358
|
+
supportedHint: 'Supported: weekday refs ("next Tuesday"), day offsets ("today"/"tomorrow"/"yesterday"), unit offsets ("in 3 days", "2 weeks ago"), and month-day ("March 5th").',
|
|
359
|
+
matchers: [
|
|
360
|
+
// today / tomorrow / yesterday — exact match, most rigid shape.
|
|
361
|
+
// Checked first because they're the most common phrase class.
|
|
362
|
+
{
|
|
363
|
+
pattern: /^today$/i,
|
|
364
|
+
resolve: (_m, ctx) => buildPlainDate(ctx.temporal, readYear(ctx.reference), readMonth(ctx.reference), readDay(ctx.reference))
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
pattern: /^tomorrow$/i,
|
|
368
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, 1)
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
pattern: /^yesterday$/i,
|
|
372
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, -1)
|
|
373
|
+
},
|
|
374
|
+
// weekday references: "next/last/this Tuesday". Capture the relative
|
|
375
|
+
// word and the weekday name separately, then resolve via +7 / -7.
|
|
376
|
+
{
|
|
377
|
+
pattern: new RegExp(`^(next|last|this)\\s+(${nameAlternation(ENGLISH_WEEKDAYS)})$`, "i"),
|
|
378
|
+
resolve: (m, ctx) => {
|
|
379
|
+
const rel = m[1].toLowerCase();
|
|
380
|
+
const targetDow = weekdayIndexFromName(m[2], ENGLISH_WEEKDAYS);
|
|
381
|
+
const refDow = extractDayOfWeek(ctx.reference);
|
|
382
|
+
return addDays(ctx.temporal, ctx.reference, weekdayOffset(rel, refDow, targetDow));
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
// unit offsets: "in 3 days", "2 weeks ago", "in 1 month", "1 year ago".
|
|
386
|
+
// Two shapes share this matcher — leading "in" (future) or trailing
|
|
387
|
+
// "ago" (past). Both lead with <number> <unit>.
|
|
388
|
+
{
|
|
389
|
+
pattern: /^(in\s+)?(\d+)\s+(day|week|month|year)s?(?:\s+ago)?$/i,
|
|
390
|
+
resolve: (m, ctx) => {
|
|
391
|
+
const inPrefix = m[1];
|
|
392
|
+
const count = m[2];
|
|
393
|
+
const unitName = m[3].toLowerCase();
|
|
394
|
+
const hasIn = !!inPrefix;
|
|
395
|
+
const hasAgo = /\bago\b/i.test(m[0]);
|
|
396
|
+
if (!hasIn && !hasAgo) {
|
|
397
|
+
throw new Error(
|
|
398
|
+
`temporal-fmt: parseRelative can't tell whether "${m[0]}" is past or future \u2014 use "in ${count} ${unitName}s" or "${count} ${unitName}s ago".`
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
const sign = hasIn ? 1 : -1;
|
|
402
|
+
return addUnits(ctx.temporal, ctx.reference, sign * Number(count), unitName);
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
// month-day without year, e.g. "March 5th", "March 5", "March 5, 2026"
|
|
406
|
+
// (year is ignored if present). The ordinal suffix is decorative —
|
|
407
|
+
// strip it. The day-of-month is a 1- or 2-digit number.
|
|
408
|
+
{
|
|
409
|
+
pattern: new RegExp(`^(${nameAlternation([...ENGLISH_MONTHS, ...ENGLISH_MONTH_SHORT])})\\s+(\\d{1,2})(?:st|nd|rd|th)?(?:,?\\s*(\\d{4}))?$`, "i"),
|
|
410
|
+
resolve: (m, ctx) => {
|
|
411
|
+
const month = monthIndexFromName(m[1], ENGLISH_MONTHS, ENGLISH_MONTH_SHORT);
|
|
412
|
+
const day = Number(m[2]);
|
|
413
|
+
return resolveToNextOccurrence(ctx.temporal, ctx.reference, month, day);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
};
|
|
418
|
+
var SPANISH_WEEKDAYS = ["lunes", "martes", "mi\xE9rcoles", "jueves", "viernes", "s\xE1bado", "domingo"];
|
|
419
|
+
var SPANISH_MONTHS = ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"];
|
|
420
|
+
var SPANISH_MONTH_SHORT = ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sept", "oct", "nov", "dic"];
|
|
421
|
+
var SPANISH_GRAMMAR = {
|
|
422
|
+
supportedHint: 'Frases soportadas: referencias de d\xEDa de la semana ("el pr\xF3ximo lunes", "el lunes pasado", "este martes"), offsets de d\xEDa ("hoy"/"ma\xF1ana"/"ayer"), offsets de unidad ("en 3 d\xEDas", "hace 2 semanas"), y mes-d\xEDa ("5 de marzo").',
|
|
423
|
+
matchers: [
|
|
424
|
+
{
|
|
425
|
+
pattern: /^hoy$/i,
|
|
426
|
+
resolve: (_m, ctx) => buildPlainDate(ctx.temporal, readYear(ctx.reference), readMonth(ctx.reference), readDay(ctx.reference))
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
pattern: /^ma[ñn]ana$/i,
|
|
430
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, 1)
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
pattern: /^ayer$/i,
|
|
434
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, -1)
|
|
435
|
+
},
|
|
436
|
+
// weekday references. Spanish has three common shapes, all meaning
|
|
437
|
+
// the same thing per rel word:
|
|
438
|
+
// "el próximo lunes" / "próximo lunes" → next
|
|
439
|
+
// "el lunes próximo" → next (suffix variant)
|
|
440
|
+
// "el lunes pasado" / "lunes pasado" → last
|
|
441
|
+
// "este lunes" → this
|
|
442
|
+
// Capture the rel word from whichever shape matched, then resolve
|
|
443
|
+
// the same way English does.
|
|
444
|
+
{
|
|
445
|
+
pattern: new RegExp(
|
|
446
|
+
`^(?:el\\s+)?(?:(pr[o\xF3]ximo|pasado)\\s+(${nameAlternation(SPANISH_WEEKDAYS)})|(${nameAlternation(SPANISH_WEEKDAYS)})\\s+(pr[o\xF3]ximo|pasado)|este\\s+(${nameAlternation(SPANISH_WEEKDAYS)}))$`,
|
|
447
|
+
"i"
|
|
448
|
+
),
|
|
449
|
+
resolve: (m, ctx) => {
|
|
450
|
+
let relWord;
|
|
451
|
+
let weekdayName;
|
|
452
|
+
if (m[1] && m[2]) {
|
|
453
|
+
relWord = m[1];
|
|
454
|
+
weekdayName = m[2];
|
|
455
|
+
} else if (m[3] && m[4]) {
|
|
456
|
+
weekdayName = m[3];
|
|
457
|
+
relWord = m[4];
|
|
458
|
+
} else {
|
|
459
|
+
relWord = "este";
|
|
460
|
+
weekdayName = m[5];
|
|
461
|
+
}
|
|
462
|
+
const rel = normalizeForMatch(relWord) === "proximo" ? "next" : relWord.toLowerCase() === "este" ? "this" : "last";
|
|
463
|
+
const targetDow = weekdayIndexFromName(weekdayName, SPANISH_WEEKDAYS);
|
|
464
|
+
const refDow = extractDayOfWeek(ctx.reference);
|
|
465
|
+
return addDays(ctx.temporal, ctx.reference, weekdayOffset(rel, refDow, targetDow));
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
// unit offsets. Spanish uses distinct markers:
|
|
469
|
+
// "en 3 días" / "dentro de 3 días" → future
|
|
470
|
+
// "hace 2 semanas" → past
|
|
471
|
+
// Both shapes lead with the marker, unlike English where one
|
|
472
|
+
// shape leads and the other trails.
|
|
473
|
+
{
|
|
474
|
+
pattern: new RegExp(
|
|
475
|
+
`^(?:(en|dentro\\s+de)\\s+(\\d+)\\s+(d[i\xED]a|semana|mes|a[\xF1n]o)s?|(\\d+)\\s+(d[i\xED]a|semana|mes|a[\xF1n]o)s?\\s+(hace))$`,
|
|
476
|
+
"i"
|
|
477
|
+
),
|
|
478
|
+
resolve: (m, ctx) => {
|
|
479
|
+
let count;
|
|
480
|
+
let unitWord;
|
|
481
|
+
let sign;
|
|
482
|
+
if (m[1] && m[2] && m[3]) {
|
|
483
|
+
count = m[2];
|
|
484
|
+
unitWord = m[3];
|
|
485
|
+
sign = 1;
|
|
486
|
+
} else {
|
|
487
|
+
count = m[4];
|
|
488
|
+
unitWord = m[5];
|
|
489
|
+
sign = -1;
|
|
490
|
+
}
|
|
491
|
+
const unit = unitWordToEnglish(unitWord);
|
|
492
|
+
return addUnits(ctx.temporal, ctx.reference, sign * Number(count), unit);
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
// "hace 2 semanas" — the primary past-offset shape. Matcher kept
|
|
496
|
+
// separate from the future "en/dentro de" matcher above because
|
|
497
|
+
// Spanish word order differs between the two (marker-first for
|
|
498
|
+
// past, marker-first for future too, but with different markers).
|
|
499
|
+
{
|
|
500
|
+
pattern: new RegExp(`^hace\\s+(\\d+)\\s+(d[i\xED]a|semana|mes|a[\xF1n]o)s?$`, "i"),
|
|
501
|
+
resolve: (m, ctx) => {
|
|
502
|
+
const count = Number(m[1]);
|
|
503
|
+
const unit = unitWordToEnglish(m[2]);
|
|
504
|
+
return addUnits(ctx.temporal, ctx.reference, -count, unit);
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
// bare "N <unit>" without "en" / "hace" — throw, since direction
|
|
508
|
+
// is ambiguous. Matched AFTER the directional shapes so the
|
|
509
|
+
// directional ones win when their marker is present.
|
|
510
|
+
{
|
|
511
|
+
pattern: new RegExp(`^(\\d+)\\s+(d[i\xED]a|semana|mes|a[\xF1n]o)s?$`, "i"),
|
|
512
|
+
resolve: (m, _ctx) => {
|
|
513
|
+
throw new Error(
|
|
514
|
+
`temporal-fmt: parseRelative no puede decidir si "${m[0]}" es pasado o futuro \u2014 usa "en ${m[1]} ${m[2]}s" o "hace ${m[1]} ${m[2]}s".`
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
// month-day: "5 de marzo" (day first), "5 de marzo de 2026" (year
|
|
519
|
+
// ignored if present). Day is 1-2 digits, with optional trailing
|
|
520
|
+
// "." (rare in Spanish but tolerated).
|
|
521
|
+
{
|
|
522
|
+
pattern: new RegExp(
|
|
523
|
+
`^(\\d{1,2})\\.?\\s+de\\s+(${nameAlternation([...SPANISH_MONTHS, ...SPANISH_MONTH_SHORT])})(?:\\s+de\\s+(\\d{4}))?$`,
|
|
524
|
+
"i"
|
|
525
|
+
),
|
|
526
|
+
resolve: (m, ctx) => {
|
|
527
|
+
const day = Number(m[1]);
|
|
528
|
+
const month = monthIndexFromName(m[2], SPANISH_MONTHS, SPANISH_MONTH_SHORT);
|
|
529
|
+
return resolveToNextOccurrence(ctx.temporal, ctx.reference, month, day);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
]
|
|
533
|
+
};
|
|
534
|
+
var FRENCH_WEEKDAYS = ["lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche"];
|
|
535
|
+
var FRENCH_MONTHS = ["janvier", "f\xE9vrier", "mars", "avril", "mai", "juin", "juillet", "ao\xFBt", "septembre", "octobre", "novembre", "d\xE9cembre"];
|
|
536
|
+
var FRENCH_MONTH_SHORT = ["janv.", "f\xE9vr.", "mars", "avr.", "mai", "juin", "juil.", "ao\xFBt", "sept.", "oct.", "nov.", "d\xE9c."];
|
|
537
|
+
var FRENCH_GRAMMAR = {
|
|
538
|
+
supportedHint: `Phrases prises en charge : r\xE9f\xE9rences de jour de la semaine ("lundi prochain", "mardi dernier", "ce mercredi"), d\xE9calages de jour ("aujourd'hui"/"demain"/"hier"), d\xE9calages d'unit\xE9 ("dans 3 jours", "il y a 2 semaines"), et mois-jour ("5 mars").`,
|
|
539
|
+
matchers: [
|
|
540
|
+
{
|
|
541
|
+
pattern: /^aujourd'hui$/i,
|
|
542
|
+
resolve: (_m, ctx) => buildPlainDate(ctx.temporal, readYear(ctx.reference), readMonth(ctx.reference), readDay(ctx.reference))
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
pattern: /^demain$/i,
|
|
546
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, 1)
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
pattern: /^hier$/i,
|
|
550
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, -1)
|
|
551
|
+
},
|
|
552
|
+
// weekday references: "lundi prochain" (next), "lundi dernier"
|
|
553
|
+
// (last), "ce lundi" (this). The relative word follows the
|
|
554
|
+
// weekday for next/last, precedes it for this.
|
|
555
|
+
{
|
|
556
|
+
pattern: new RegExp(
|
|
557
|
+
`^(?:(${nameAlternation(FRENCH_WEEKDAYS)})\\s+(prochain|dernier)|ce\\s+(${nameAlternation(FRENCH_WEEKDAYS)}))$`,
|
|
558
|
+
"i"
|
|
559
|
+
),
|
|
560
|
+
resolve: (m, ctx) => {
|
|
561
|
+
let rel;
|
|
562
|
+
let weekdayName;
|
|
563
|
+
if (m[1] && m[2]) {
|
|
564
|
+
weekdayName = m[1];
|
|
565
|
+
rel = m[2].toLowerCase() === "prochain" ? "next" : "last";
|
|
566
|
+
} else {
|
|
567
|
+
rel = "this";
|
|
568
|
+
weekdayName = m[3];
|
|
569
|
+
}
|
|
570
|
+
const targetDow = weekdayIndexFromName(weekdayName, FRENCH_WEEKDAYS);
|
|
571
|
+
const refDow = extractDayOfWeek(ctx.reference);
|
|
572
|
+
return addDays(ctx.temporal, ctx.reference, weekdayOffset(rel, refDow, targetDow));
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
// past: "il y a 2 semaines" — multi-word marker.
|
|
576
|
+
{
|
|
577
|
+
pattern: new RegExp(`^il\\s+y\\s+a\\s+(\\d+)\\s+(jour|semaine|mois|an|ann[e\xE9e]e)s?$`, "i"),
|
|
578
|
+
resolve: (m, ctx) => {
|
|
579
|
+
const count = Number(m[1]);
|
|
580
|
+
const unit = unitWordToEnglish(m[2]);
|
|
581
|
+
return addUnits(ctx.temporal, ctx.reference, -count, unit);
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
// future: "dans 3 jours"
|
|
585
|
+
{
|
|
586
|
+
pattern: new RegExp(`^dans\\s+(\\d+)\\s+(jour|semaine|mois|an|ann[e\xE9e]e)s?$`, "i"),
|
|
587
|
+
resolve: (m, ctx) => {
|
|
588
|
+
const count = Number(m[1]);
|
|
589
|
+
const unit = unitWordToEnglish(m[2]);
|
|
590
|
+
return addUnits(ctx.temporal, ctx.reference, count, unit);
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
// bare "N <unit>" without marker — throw.
|
|
594
|
+
{
|
|
595
|
+
pattern: new RegExp(`^(\\d+)\\s+(jour|semaine|mois|an|ann[e\xE9e]e)s?$`, "i"),
|
|
596
|
+
resolve: (m, _ctx) => {
|
|
597
|
+
throw new Error(
|
|
598
|
+
`temporal-fmt: parseRelative ne peut pas d\xE9terminer si "${m[0]}" est pass\xE9 ou futur \u2014 utilisez "dans ${m[1]} ${m[2]}s" ou "il y a ${m[1]} ${m[2]}s".`
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
},
|
|
602
|
+
// month-day: "5 mars" (day first, no separator word). Year ignored.
|
|
603
|
+
{
|
|
604
|
+
pattern: new RegExp(
|
|
605
|
+
`^(\\d{1,2})\\s+(${nameAlternation([...FRENCH_MONTHS, ...FRENCH_MONTH_SHORT])})(?:\\s+(\\d{4}))?$`,
|
|
606
|
+
"i"
|
|
607
|
+
),
|
|
608
|
+
resolve: (m, ctx) => {
|
|
609
|
+
const day = Number(m[1]);
|
|
610
|
+
const month = monthIndexFromName(m[2], FRENCH_MONTHS, FRENCH_MONTH_SHORT);
|
|
611
|
+
return resolveToNextOccurrence(ctx.temporal, ctx.reference, month, day);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
]
|
|
615
|
+
};
|
|
616
|
+
var GERMAN_WEEKDAYS = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"];
|
|
617
|
+
var GERMAN_MONTHS = ["Januar", "Februar", "M\xE4rz", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
|
|
618
|
+
var GERMAN_MONTH_SHORT = ["Jan", "Feb", "M\xE4r", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
|
|
619
|
+
var GERMAN_GRAMMAR = {
|
|
620
|
+
supportedHint: 'Unterst\xFCtzte Phrasen: Wochentag-Bez\xFCge ("n\xE4chsten Dienstag", "letzten Freitag", "diesen Montag"), Tages-Offsets ("heute"/"morgen"/"gestern"), Einheiten-Offsets ("in 3 Tagen", "vor 2 Wochen"), und Monat-Tag ("5. M\xE4rz").',
|
|
621
|
+
matchers: [
|
|
622
|
+
{
|
|
623
|
+
pattern: /^heute$/i,
|
|
624
|
+
resolve: (_m, ctx) => buildPlainDate(ctx.temporal, readYear(ctx.reference), readMonth(ctx.reference), readDay(ctx.reference))
|
|
625
|
+
},
|
|
626
|
+
{
|
|
627
|
+
pattern: /^morgen$/i,
|
|
628
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, 1)
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
pattern: /^gestern$/i,
|
|
632
|
+
resolve: (_m, ctx) => addDays(ctx.temporal, ctx.reference, -1)
|
|
633
|
+
},
|
|
634
|
+
// weekday references: "nächsten Dienstag" (next), "letzten
|
|
635
|
+
// Dienstag" (last), "diesen Dienstag" (this). Adjective precedes
|
|
636
|
+
// the weekday; case varies (nächsten/letzten/diesen all take the
|
|
637
|
+
// weak-declension -en/-en/-en ending when no article, which is
|
|
638
|
+
// convenient — one regex alternation covers all three.
|
|
639
|
+
{
|
|
640
|
+
pattern: new RegExp(`^(n(?:ae|a|\xE4)chsten|letzten|diesen)\\s+(${nameAlternation(GERMAN_WEEKDAYS)})$`, "i"),
|
|
641
|
+
resolve: (m, ctx) => {
|
|
642
|
+
const adj = normalizeForMatch(m[1]);
|
|
643
|
+
const rel = adj === "nachsten" || adj === "naechsten" ? "next" : adj === "diesen" ? "this" : "last";
|
|
644
|
+
const targetDow = weekdayIndexFromName(m[2], GERMAN_WEEKDAYS);
|
|
645
|
+
const refDow = extractDayOfWeek(ctx.reference);
|
|
646
|
+
return addDays(ctx.temporal, ctx.reference, weekdayOffset(rel, refDow, targetDow));
|
|
647
|
+
}
|
|
648
|
+
},
|
|
649
|
+
// past: "vor 2 Wochen"
|
|
650
|
+
{
|
|
651
|
+
pattern: new RegExp(`^vor\\s+(\\d+)\\s+(Tag(?:e|n|en)?|Woche(?:n)?|Monat(?:e|n|en)?|Jahr(?:e|n|en)?)$`, "i"),
|
|
652
|
+
resolve: (m, ctx) => {
|
|
653
|
+
const count = Number(m[1]);
|
|
654
|
+
const unit = unitWordToEnglish(m[2]);
|
|
655
|
+
return addUnits(ctx.temporal, ctx.reference, -count, unit);
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
// future: "in 3 Tagen"
|
|
659
|
+
{
|
|
660
|
+
pattern: new RegExp(`^in\\s+(\\d+)\\s+(Tag(?:e|n|en)?|Woche(?:n)?|Monat(?:e|n|en)?|Jahr(?:e|n|en)?)$`, "i"),
|
|
661
|
+
resolve: (m, ctx) => {
|
|
662
|
+
const count = Number(m[1]);
|
|
663
|
+
const unit = unitWordToEnglish(m[2]);
|
|
664
|
+
return addUnits(ctx.temporal, ctx.reference, count, unit);
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
// bare "N <unit>" without "in" or "vor" — throw.
|
|
668
|
+
{
|
|
669
|
+
pattern: new RegExp(`^(\\d+)\\s+(Tag(?:e|n|en)?|Woche(?:n)?|Monat(?:e|n|en)?|Jahr(?:e|n|en)?)$`, "i"),
|
|
670
|
+
resolve: (m, _ctx) => {
|
|
671
|
+
throw new Error(
|
|
672
|
+
`temporal-fmt: parseRelative kann nicht erkennen, ob "${m[0]}" Vergangenheit oder Zukunft ist \u2014 verwende "in ${m[1]} ${m[2]}" oder "vor ${m[1]} ${m[2]}".`
|
|
673
|
+
);
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
// month-day: "5. März" (day-first with period). Year ignored.
|
|
677
|
+
{
|
|
678
|
+
pattern: new RegExp(
|
|
679
|
+
`^(\\d{1,2})\\.?\\s+(${nameAlternation([...GERMAN_MONTHS, ...GERMAN_MONTH_SHORT, "Maerz", "Maer"])})(?:\\s+(\\d{4}))?$`,
|
|
680
|
+
"i"
|
|
681
|
+
),
|
|
682
|
+
resolve: (m, ctx) => {
|
|
683
|
+
const day = Number(m[1]);
|
|
684
|
+
const month = monthIndexFromName(m[2], GERMAN_MONTHS, GERMAN_MONTH_SHORT);
|
|
685
|
+
return resolveToNextOccurrence(ctx.temporal, ctx.reference, month, day);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
]
|
|
689
|
+
};
|
|
690
|
+
var GRAMMARS = {
|
|
691
|
+
en: ENGLISH_GRAMMAR,
|
|
692
|
+
es: SPANISH_GRAMMAR,
|
|
693
|
+
fr: FRENCH_GRAMMAR,
|
|
694
|
+
de: GERMAN_GRAMMAR
|
|
695
|
+
};
|
|
696
|
+
function grammarForLocale(locale) {
|
|
697
|
+
if (!locale) return ENGLISH_GRAMMAR;
|
|
698
|
+
try {
|
|
699
|
+
const tag = new Intl.Locale(locale.replace(/_/g, "-"));
|
|
700
|
+
const lang = tag.language.toLowerCase();
|
|
701
|
+
return GRAMMARS[lang] ?? ENGLISH_GRAMMAR;
|
|
702
|
+
} catch {
|
|
703
|
+
return ENGLISH_GRAMMAR;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
function languageOf(locale) {
|
|
707
|
+
if (!locale) return "en";
|
|
708
|
+
try {
|
|
709
|
+
return new Intl.Locale(locale.replace(/_/g, "-")).language.toLowerCase();
|
|
710
|
+
} catch {
|
|
711
|
+
return "en";
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
function unitWordToEnglish(word) {
|
|
715
|
+
const w = normalizeForMatch(word);
|
|
716
|
+
if (w === "day" || w === "week" || w === "month" || w === "year") return w;
|
|
717
|
+
if (w === "dia") return "day";
|
|
718
|
+
if (w === "semana") return "week";
|
|
719
|
+
if (w === "mes") return "month";
|
|
720
|
+
if (w === "ano" || w === "a\xF1o") return "year";
|
|
721
|
+
if (w === "jour") return "day";
|
|
722
|
+
if (w === "semaine") return "week";
|
|
723
|
+
if (w === "mois") return "month";
|
|
724
|
+
if (w === "an" || w === "annee") return "year";
|
|
725
|
+
if (w === "tag" || w === "tagen") return "day";
|
|
726
|
+
if (w === "woche" || w === "wochen") return "week";
|
|
727
|
+
if (w === "monat" || w === "monaten") return "month";
|
|
728
|
+
if (w === "jahr" || w === "jahren") return "year";
|
|
729
|
+
/* c8 ignore start @preserve -- unreachable: every caller passes a word
|
|
730
|
+
* captured by a regex alternation built from exactly these unit-word
|
|
731
|
+
* forms (day/week/month/year across en/es/fr/de), so the branches
|
|
732
|
+
* above already cover every string that can reach this function.
|
|
733
|
+
* Kept as a tripwire for the type checker in case a grammar adds a
|
|
734
|
+
* unit word here without a matching regex update. */
|
|
735
|
+
throw new Error(`temporal-fmt: parseRelative internal error \u2014 unrecognized unit word "${word}".`);
|
|
736
|
+
/* c8 ignore stop @preserve */
|
|
737
|
+
}
|
|
738
|
+
function parseRelative(input, referenceDate, options = {}) {
|
|
739
|
+
const reference = referenceDate;
|
|
740
|
+
const temporal = getTemporal();
|
|
741
|
+
const trimmed = (input ?? "").trim().replace(/\s+/g, " ");
|
|
742
|
+
if (trimmed.length === 0) {
|
|
743
|
+
throw new Error("temporal-fmt: parseRelative got an empty input string.");
|
|
744
|
+
}
|
|
745
|
+
if (trimmed.length > MAX_RELATIVE_INPUT_LENGTH) {
|
|
746
|
+
throw new RangeError(
|
|
747
|
+
`temporal-fmt: parseRelative input is too large (maximum ${MAX_RELATIVE_INPUT_LENGTH} characters).`
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
const normalized = normalizeForMatch(trimmed);
|
|
751
|
+
const grammar = grammarForLocale(options.locale);
|
|
752
|
+
const ctx = { temporal, reference };
|
|
753
|
+
const registered = tryRegisteredGrammar(languageOf(options.locale), trimmed, {
|
|
754
|
+
year: reference.year,
|
|
755
|
+
month: reference.month,
|
|
756
|
+
day: reference.day,
|
|
757
|
+
dayOfWeek: reference.dayOfWeek
|
|
758
|
+
});
|
|
759
|
+
if (registered !== null) {
|
|
760
|
+
return registered;
|
|
761
|
+
}
|
|
762
|
+
const tryMatch = (text) => {
|
|
763
|
+
for (const matcher of grammar.matchers) {
|
|
764
|
+
const match = text.match(matcher.pattern);
|
|
765
|
+
if (match) {
|
|
766
|
+
return matcher.resolve(match, ctx);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return NO_MATCH;
|
|
770
|
+
};
|
|
771
|
+
const exactResult = tryMatch(normalized);
|
|
772
|
+
if (exactResult !== NO_MATCH) {
|
|
773
|
+
return exactResult;
|
|
774
|
+
}
|
|
775
|
+
if (options.fuzzy) {
|
|
776
|
+
if (grammar !== ENGLISH_GRAMMAR) {
|
|
777
|
+
throw new Error(
|
|
778
|
+
`temporal-fmt: parseRelative's { fuzzy: true } option currently only supports English. Pass no locale (or locale: 'en'), or omit { fuzzy: true } for this locale.`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
const corrected = fuzzyCorrectEnglish(normalized);
|
|
782
|
+
if (corrected !== void 0) {
|
|
783
|
+
const fuzzyResult = tryMatch(corrected);
|
|
784
|
+
if (fuzzyResult !== NO_MATCH) {
|
|
785
|
+
return fuzzyResult;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
throw new Error(
|
|
790
|
+
`temporal-fmt: parseRelative doesn't recognize "${trimmed}". ` + grammar.supportedHint
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
var NO_MATCH = /* @__PURE__ */ Symbol("temporal-fmt: parseRelative no match");
|
|
794
|
+
|
|
795
|
+
// src/tokenMetadata.ts
|
|
796
|
+
var TYPES_WITH = {
|
|
797
|
+
year: ["PlainDate", "PlainDateTime", "ZonedDateTime", "PlainYearMonth"],
|
|
798
|
+
month: ["PlainDate", "PlainDateTime", "ZonedDateTime", "PlainYearMonth", "PlainMonthDay"],
|
|
799
|
+
day: ["PlainDate", "PlainDateTime", "ZonedDateTime", "PlainMonthDay"],
|
|
800
|
+
hour: ["PlainTime", "PlainDateTime", "ZonedDateTime", "Instant"],
|
|
801
|
+
minute: ["PlainTime", "PlainDateTime", "ZonedDateTime", "Instant"],
|
|
802
|
+
second: ["PlainTime", "PlainDateTime", "ZonedDateTime", "Instant"],
|
|
803
|
+
millisecond: ["PlainTime", "PlainDateTime", "ZonedDateTime", "Instant"],
|
|
804
|
+
dayOfWeek: ["PlainDate", "PlainDateTime", "ZonedDateTime"],
|
|
805
|
+
timeZoneId: ["ZonedDateTime"],
|
|
806
|
+
offset: ["ZonedDateTime"]
|
|
807
|
+
};
|
|
808
|
+
var TOKEN_METADATA = {
|
|
809
|
+
yyyy: {
|
|
810
|
+
meaning: "Four-digit year (preserves sign for BCE; no truncation).",
|
|
811
|
+
formatCapable: true,
|
|
812
|
+
parseCapable: true,
|
|
813
|
+
localeSensitive: false,
|
|
814
|
+
calendarSensitive: true,
|
|
815
|
+
timezoneSensitive: false,
|
|
816
|
+
supportedTypes: TYPES_WITH.year,
|
|
817
|
+
roundTripSafe: true
|
|
818
|
+
},
|
|
819
|
+
yy: {
|
|
820
|
+
meaning: "Two-digit year (year % 100). Throws on negative years.",
|
|
821
|
+
formatCapable: true,
|
|
822
|
+
parseCapable: true,
|
|
823
|
+
localeSensitive: false,
|
|
824
|
+
calendarSensitive: true,
|
|
825
|
+
timezoneSensitive: false,
|
|
826
|
+
supportedTypes: TYPES_WITH.year,
|
|
827
|
+
roundTripSafe: false
|
|
828
|
+
},
|
|
829
|
+
y: {
|
|
830
|
+
meaning: "Unpadded year, any width (preserves sign for BCE; no truncation, no minimum digits). Cannot sit directly next to another digit-reading token or a literal starting with a digit \u2014 there would be no way to tell where it ends.",
|
|
831
|
+
formatCapable: true,
|
|
832
|
+
parseCapable: true,
|
|
833
|
+
localeSensitive: false,
|
|
834
|
+
calendarSensitive: true,
|
|
835
|
+
timezoneSensitive: false,
|
|
836
|
+
supportedTypes: TYPES_WITH.year,
|
|
837
|
+
roundTripSafe: true
|
|
838
|
+
},
|
|
839
|
+
MMMM: {
|
|
840
|
+
meaning: 'Long month name (locale-aware, e.g. "January", "janvier").',
|
|
841
|
+
formatCapable: true,
|
|
842
|
+
parseCapable: true,
|
|
843
|
+
localeSensitive: true,
|
|
844
|
+
calendarSensitive: true,
|
|
845
|
+
timezoneSensitive: false,
|
|
846
|
+
supportedTypes: TYPES_WITH.month,
|
|
847
|
+
roundTripSafe: true
|
|
848
|
+
},
|
|
849
|
+
MMM: {
|
|
850
|
+
meaning: 'Short month name (locale-aware, e.g. "Jan", "janv.").',
|
|
851
|
+
formatCapable: true,
|
|
852
|
+
parseCapable: true,
|
|
853
|
+
localeSensitive: true,
|
|
854
|
+
calendarSensitive: true,
|
|
855
|
+
timezoneSensitive: false,
|
|
856
|
+
supportedTypes: TYPES_WITH.month,
|
|
857
|
+
roundTripSafe: true
|
|
858
|
+
},
|
|
859
|
+
MM: {
|
|
860
|
+
meaning: "Two-digit month (01-12, zero-padded).",
|
|
861
|
+
formatCapable: true,
|
|
862
|
+
parseCapable: true,
|
|
863
|
+
localeSensitive: false,
|
|
864
|
+
calendarSensitive: true,
|
|
865
|
+
timezoneSensitive: false,
|
|
866
|
+
supportedTypes: TYPES_WITH.month,
|
|
867
|
+
roundTripSafe: true
|
|
868
|
+
},
|
|
869
|
+
M: {
|
|
870
|
+
meaning: "One- or two-digit month (1-12, no padding).",
|
|
871
|
+
formatCapable: true,
|
|
872
|
+
parseCapable: true,
|
|
873
|
+
localeSensitive: false,
|
|
874
|
+
calendarSensitive: true,
|
|
875
|
+
timezoneSensitive: false,
|
|
876
|
+
supportedTypes: TYPES_WITH.month,
|
|
877
|
+
roundTripSafe: true
|
|
878
|
+
},
|
|
879
|
+
dd: {
|
|
880
|
+
meaning: "Two-digit day-of-month (01-31, zero-padded).",
|
|
881
|
+
formatCapable: true,
|
|
882
|
+
parseCapable: true,
|
|
883
|
+
localeSensitive: false,
|
|
884
|
+
calendarSensitive: true,
|
|
885
|
+
timezoneSensitive: false,
|
|
886
|
+
supportedTypes: TYPES_WITH.day,
|
|
887
|
+
roundTripSafe: true
|
|
888
|
+
},
|
|
889
|
+
d: {
|
|
890
|
+
meaning: "One- or two-digit day-of-month (1-31, no padding).",
|
|
891
|
+
formatCapable: true,
|
|
892
|
+
parseCapable: true,
|
|
893
|
+
localeSensitive: false,
|
|
894
|
+
calendarSensitive: true,
|
|
895
|
+
timezoneSensitive: false,
|
|
896
|
+
supportedTypes: TYPES_WITH.day,
|
|
897
|
+
roundTripSafe: true
|
|
898
|
+
},
|
|
899
|
+
EEEE: {
|
|
900
|
+
meaning: 'Long weekday name (locale-aware, e.g. "Monday", "lundi"). Parse cross-checks against the parsed date.',
|
|
901
|
+
formatCapable: true,
|
|
902
|
+
parseCapable: true,
|
|
903
|
+
localeSensitive: true,
|
|
904
|
+
calendarSensitive: true,
|
|
905
|
+
timezoneSensitive: false,
|
|
906
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
907
|
+
roundTripSafe: true
|
|
908
|
+
},
|
|
909
|
+
EEE: {
|
|
910
|
+
meaning: 'Short weekday name (locale-aware, e.g. "Mon", "lun."). Parse cross-checks against the parsed date.',
|
|
911
|
+
formatCapable: true,
|
|
912
|
+
parseCapable: true,
|
|
913
|
+
localeSensitive: true,
|
|
914
|
+
calendarSensitive: true,
|
|
915
|
+
timezoneSensitive: false,
|
|
916
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
917
|
+
roundTripSafe: true
|
|
918
|
+
},
|
|
919
|
+
HH: {
|
|
920
|
+
meaning: "Two-digit hour, 24-hour clock (00-23, zero-padded).",
|
|
921
|
+
formatCapable: true,
|
|
922
|
+
parseCapable: true,
|
|
923
|
+
localeSensitive: false,
|
|
924
|
+
calendarSensitive: false,
|
|
925
|
+
timezoneSensitive: false,
|
|
926
|
+
supportedTypes: TYPES_WITH.hour,
|
|
927
|
+
roundTripSafe: true
|
|
928
|
+
},
|
|
929
|
+
H: {
|
|
930
|
+
meaning: "One- or two-digit hour, 24-hour clock (0-23, no padding).",
|
|
931
|
+
formatCapable: true,
|
|
932
|
+
parseCapable: true,
|
|
933
|
+
localeSensitive: false,
|
|
934
|
+
calendarSensitive: false,
|
|
935
|
+
timezoneSensitive: false,
|
|
936
|
+
supportedTypes: TYPES_WITH.hour,
|
|
937
|
+
roundTripSafe: true
|
|
938
|
+
},
|
|
939
|
+
hh: {
|
|
940
|
+
meaning: "Two-digit hour, 12-hour clock (01-12, zero-padded). Requires `a` token on parse.",
|
|
941
|
+
formatCapable: true,
|
|
942
|
+
parseCapable: true,
|
|
943
|
+
localeSensitive: false,
|
|
944
|
+
calendarSensitive: false,
|
|
945
|
+
timezoneSensitive: false,
|
|
946
|
+
supportedTypes: TYPES_WITH.hour,
|
|
947
|
+
roundTripSafe: true
|
|
948
|
+
},
|
|
949
|
+
h: {
|
|
950
|
+
meaning: "One- or two-digit hour, 12-hour clock (1-12, no padding). Requires `a` token on parse.",
|
|
951
|
+
formatCapable: true,
|
|
952
|
+
parseCapable: true,
|
|
953
|
+
localeSensitive: false,
|
|
954
|
+
calendarSensitive: false,
|
|
955
|
+
timezoneSensitive: false,
|
|
956
|
+
supportedTypes: TYPES_WITH.hour,
|
|
957
|
+
roundTripSafe: true
|
|
958
|
+
},
|
|
959
|
+
mm: {
|
|
960
|
+
meaning: "Two-digit minute (00-59, zero-padded).",
|
|
961
|
+
formatCapable: true,
|
|
962
|
+
parseCapable: true,
|
|
963
|
+
localeSensitive: false,
|
|
964
|
+
calendarSensitive: false,
|
|
965
|
+
timezoneSensitive: false,
|
|
966
|
+
supportedTypes: TYPES_WITH.minute,
|
|
967
|
+
roundTripSafe: true
|
|
968
|
+
},
|
|
969
|
+
m: {
|
|
970
|
+
meaning: "One- or two-digit minute (0-59, no padding).",
|
|
971
|
+
formatCapable: true,
|
|
972
|
+
parseCapable: true,
|
|
973
|
+
localeSensitive: false,
|
|
974
|
+
calendarSensitive: false,
|
|
975
|
+
timezoneSensitive: false,
|
|
976
|
+
supportedTypes: TYPES_WITH.minute,
|
|
977
|
+
roundTripSafe: true
|
|
978
|
+
},
|
|
979
|
+
ss: {
|
|
980
|
+
meaning: "Two-digit second (00-59, zero-padded).",
|
|
981
|
+
formatCapable: true,
|
|
982
|
+
parseCapable: true,
|
|
983
|
+
localeSensitive: false,
|
|
984
|
+
calendarSensitive: false,
|
|
985
|
+
timezoneSensitive: false,
|
|
986
|
+
supportedTypes: TYPES_WITH.second,
|
|
987
|
+
roundTripSafe: true
|
|
988
|
+
},
|
|
989
|
+
s: {
|
|
990
|
+
meaning: "One- or two-digit second (0-59, no padding).",
|
|
991
|
+
formatCapable: true,
|
|
992
|
+
parseCapable: true,
|
|
993
|
+
localeSensitive: false,
|
|
994
|
+
calendarSensitive: false,
|
|
995
|
+
timezoneSensitive: false,
|
|
996
|
+
supportedTypes: TYPES_WITH.second,
|
|
997
|
+
roundTripSafe: true
|
|
998
|
+
},
|
|
999
|
+
S: {
|
|
1000
|
+
meaning: "Fractional second, 1 digit (tenths of a second).",
|
|
1001
|
+
formatCapable: true,
|
|
1002
|
+
parseCapable: true,
|
|
1003
|
+
localeSensitive: false,
|
|
1004
|
+
calendarSensitive: false,
|
|
1005
|
+
timezoneSensitive: false,
|
|
1006
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1007
|
+
roundTripSafe: true
|
|
1008
|
+
},
|
|
1009
|
+
SS: {
|
|
1010
|
+
meaning: "Fractional second, 2 digits (hundredths of a second).",
|
|
1011
|
+
formatCapable: true,
|
|
1012
|
+
parseCapable: true,
|
|
1013
|
+
localeSensitive: false,
|
|
1014
|
+
calendarSensitive: false,
|
|
1015
|
+
timezoneSensitive: false,
|
|
1016
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1017
|
+
roundTripSafe: true
|
|
1018
|
+
},
|
|
1019
|
+
SSS: {
|
|
1020
|
+
meaning: "Fractional second, 3 digits (milliseconds).",
|
|
1021
|
+
formatCapable: true,
|
|
1022
|
+
parseCapable: true,
|
|
1023
|
+
localeSensitive: false,
|
|
1024
|
+
calendarSensitive: false,
|
|
1025
|
+
timezoneSensitive: false,
|
|
1026
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1027
|
+
roundTripSafe: true
|
|
1028
|
+
},
|
|
1029
|
+
SSSS: {
|
|
1030
|
+
meaning: "Fractional second, 4 digits (tens of microseconds).",
|
|
1031
|
+
formatCapable: true,
|
|
1032
|
+
parseCapable: true,
|
|
1033
|
+
localeSensitive: false,
|
|
1034
|
+
calendarSensitive: false,
|
|
1035
|
+
timezoneSensitive: false,
|
|
1036
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1037
|
+
roundTripSafe: true
|
|
1038
|
+
},
|
|
1039
|
+
SSSSS: {
|
|
1040
|
+
meaning: "Fractional second, 5 digits (hundred-thousandths of a second).",
|
|
1041
|
+
formatCapable: true,
|
|
1042
|
+
parseCapable: true,
|
|
1043
|
+
localeSensitive: false,
|
|
1044
|
+
calendarSensitive: false,
|
|
1045
|
+
timezoneSensitive: false,
|
|
1046
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1047
|
+
roundTripSafe: true
|
|
1048
|
+
},
|
|
1049
|
+
SSSSSS: {
|
|
1050
|
+
meaning: "Fractional second, 6 digits (microseconds).",
|
|
1051
|
+
formatCapable: true,
|
|
1052
|
+
parseCapable: true,
|
|
1053
|
+
localeSensitive: false,
|
|
1054
|
+
calendarSensitive: false,
|
|
1055
|
+
timezoneSensitive: false,
|
|
1056
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1057
|
+
roundTripSafe: true
|
|
1058
|
+
},
|
|
1059
|
+
SSSSSSS: {
|
|
1060
|
+
meaning: "Fractional second, 7 digits (tens of nanoseconds).",
|
|
1061
|
+
formatCapable: true,
|
|
1062
|
+
parseCapable: true,
|
|
1063
|
+
localeSensitive: false,
|
|
1064
|
+
calendarSensitive: false,
|
|
1065
|
+
timezoneSensitive: false,
|
|
1066
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1067
|
+
roundTripSafe: true
|
|
1068
|
+
},
|
|
1069
|
+
SSSSSSSS: {
|
|
1070
|
+
meaning: "Fractional second, 8 digits (hundred-millionths of a second).",
|
|
1071
|
+
formatCapable: true,
|
|
1072
|
+
parseCapable: true,
|
|
1073
|
+
localeSensitive: false,
|
|
1074
|
+
calendarSensitive: false,
|
|
1075
|
+
timezoneSensitive: false,
|
|
1076
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1077
|
+
roundTripSafe: true
|
|
1078
|
+
},
|
|
1079
|
+
SSSSSSSSS: {
|
|
1080
|
+
meaning: "Fractional second, 9 digits (nanoseconds).",
|
|
1081
|
+
formatCapable: true,
|
|
1082
|
+
parseCapable: true,
|
|
1083
|
+
localeSensitive: false,
|
|
1084
|
+
calendarSensitive: false,
|
|
1085
|
+
timezoneSensitive: false,
|
|
1086
|
+
supportedTypes: TYPES_WITH.millisecond,
|
|
1087
|
+
roundTripSafe: true
|
|
1088
|
+
},
|
|
1089
|
+
a: {
|
|
1090
|
+
meaning: 'Day period (locale-aware: "AM"/"PM", "\u5348\u524D"/"\u5348\u5F8C", etc.). Required alongside 12-hour tokens on parse.',
|
|
1091
|
+
formatCapable: true,
|
|
1092
|
+
parseCapable: true,
|
|
1093
|
+
localeSensitive: true,
|
|
1094
|
+
calendarSensitive: false,
|
|
1095
|
+
timezoneSensitive: false,
|
|
1096
|
+
supportedTypes: TYPES_WITH.hour,
|
|
1097
|
+
roundTripSafe: true
|
|
1098
|
+
},
|
|
1099
|
+
zzz: {
|
|
1100
|
+
meaning: 'IANA time zone id (e.g. "America/New_York") or fixed offset ("+05:30"). Requires full date+time on parse.',
|
|
1101
|
+
formatCapable: true,
|
|
1102
|
+
parseCapable: true,
|
|
1103
|
+
localeSensitive: false,
|
|
1104
|
+
calendarSensitive: false,
|
|
1105
|
+
timezoneSensitive: true,
|
|
1106
|
+
supportedTypes: TYPES_WITH.timeZoneId,
|
|
1107
|
+
roundTripSafe: true
|
|
1108
|
+
},
|
|
1109
|
+
X: {
|
|
1110
|
+
meaning: "Numeric UTC offset, short (Z for UTC, \xB1HH[MM] otherwise). Minutes omitted when zero.",
|
|
1111
|
+
formatCapable: true,
|
|
1112
|
+
parseCapable: true,
|
|
1113
|
+
localeSensitive: false,
|
|
1114
|
+
calendarSensitive: false,
|
|
1115
|
+
timezoneSensitive: true,
|
|
1116
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1117
|
+
roundTripSafe: true
|
|
1118
|
+
},
|
|
1119
|
+
XX: {
|
|
1120
|
+
meaning: "Numeric UTC offset, no colon (Z for UTC, \xB1HHMM otherwise).",
|
|
1121
|
+
formatCapable: true,
|
|
1122
|
+
parseCapable: true,
|
|
1123
|
+
localeSensitive: false,
|
|
1124
|
+
calendarSensitive: false,
|
|
1125
|
+
timezoneSensitive: true,
|
|
1126
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1127
|
+
roundTripSafe: true
|
|
1128
|
+
},
|
|
1129
|
+
XXX: {
|
|
1130
|
+
meaning: "Numeric UTC offset, with colon (Z for UTC, \xB1HH:MM otherwise).",
|
|
1131
|
+
formatCapable: true,
|
|
1132
|
+
parseCapable: true,
|
|
1133
|
+
localeSensitive: false,
|
|
1134
|
+
calendarSensitive: false,
|
|
1135
|
+
timezoneSensitive: true,
|
|
1136
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1137
|
+
roundTripSafe: true
|
|
1138
|
+
},
|
|
1139
|
+
x: {
|
|
1140
|
+
meaning: "Numeric UTC offset, short, never Z (always \xB1HH[MM]). Lowercase variant of X.",
|
|
1141
|
+
formatCapable: true,
|
|
1142
|
+
parseCapable: true,
|
|
1143
|
+
localeSensitive: false,
|
|
1144
|
+
calendarSensitive: false,
|
|
1145
|
+
timezoneSensitive: true,
|
|
1146
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1147
|
+
roundTripSafe: true
|
|
1148
|
+
},
|
|
1149
|
+
xx: {
|
|
1150
|
+
meaning: "Numeric UTC offset, no colon, never Z (always \xB1HHMM). Lowercase variant of XX.",
|
|
1151
|
+
formatCapable: true,
|
|
1152
|
+
parseCapable: true,
|
|
1153
|
+
localeSensitive: false,
|
|
1154
|
+
calendarSensitive: false,
|
|
1155
|
+
timezoneSensitive: true,
|
|
1156
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1157
|
+
roundTripSafe: true
|
|
1158
|
+
},
|
|
1159
|
+
xxx: {
|
|
1160
|
+
meaning: "Numeric UTC offset, with colon, never Z (always \xB1HH:MM). Lowercase variant of XXX.",
|
|
1161
|
+
formatCapable: true,
|
|
1162
|
+
parseCapable: true,
|
|
1163
|
+
localeSensitive: false,
|
|
1164
|
+
calendarSensitive: false,
|
|
1165
|
+
timezoneSensitive: true,
|
|
1166
|
+
supportedTypes: TYPES_WITH.offset,
|
|
1167
|
+
roundTripSafe: true
|
|
1168
|
+
},
|
|
1169
|
+
do: {
|
|
1170
|
+
meaning: 'Ordinal day-of-month with English suffix ("1st", "2nd", "3rd", "4th", ... 21st, 22nd, ...). Format-only \u2014 not parseable.',
|
|
1171
|
+
formatCapable: true,
|
|
1172
|
+
parseCapable: false,
|
|
1173
|
+
localeSensitive: false,
|
|
1174
|
+
calendarSensitive: true,
|
|
1175
|
+
timezoneSensitive: false,
|
|
1176
|
+
supportedTypes: TYPES_WITH.day,
|
|
1177
|
+
roundTripSafe: false
|
|
1178
|
+
},
|
|
1179
|
+
Q: {
|
|
1180
|
+
meaning: "Quarter as a digit (1-4). Derived from month.",
|
|
1181
|
+
formatCapable: true,
|
|
1182
|
+
parseCapable: true,
|
|
1183
|
+
localeSensitive: false,
|
|
1184
|
+
calendarSensitive: true,
|
|
1185
|
+
timezoneSensitive: false,
|
|
1186
|
+
supportedTypes: TYPES_WITH.month,
|
|
1187
|
+
roundTripSafe: true
|
|
1188
|
+
},
|
|
1189
|
+
QQQ: {
|
|
1190
|
+
meaning: 'Quarter with "Q" prefix ("Q1".."Q4"). Derived from month.',
|
|
1191
|
+
formatCapable: true,
|
|
1192
|
+
parseCapable: true,
|
|
1193
|
+
localeSensitive: false,
|
|
1194
|
+
calendarSensitive: true,
|
|
1195
|
+
timezoneSensitive: false,
|
|
1196
|
+
supportedTypes: TYPES_WITH.month,
|
|
1197
|
+
roundTripSafe: true
|
|
1198
|
+
},
|
|
1199
|
+
ww: {
|
|
1200
|
+
meaning: "ISO 8601 week number (01-53). Format-only \u2014 week alone can't reconstruct a date.",
|
|
1201
|
+
formatCapable: true,
|
|
1202
|
+
parseCapable: false,
|
|
1203
|
+
localeSensitive: false,
|
|
1204
|
+
calendarSensitive: true,
|
|
1205
|
+
timezoneSensitive: false,
|
|
1206
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
1207
|
+
roundTripSafe: false
|
|
1208
|
+
},
|
|
1209
|
+
RRRR: {
|
|
1210
|
+
meaning: "ISO 8601 week-numbering year (4-digit, may differ from calendar year at year boundaries). Format-only.",
|
|
1211
|
+
formatCapable: true,
|
|
1212
|
+
parseCapable: false,
|
|
1213
|
+
localeSensitive: false,
|
|
1214
|
+
calendarSensitive: true,
|
|
1215
|
+
timezoneSensitive: false,
|
|
1216
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
1217
|
+
roundTripSafe: false
|
|
1218
|
+
},
|
|
1219
|
+
D: {
|
|
1220
|
+
meaning: "Day of year, unpadded (1-366). Format-only \u2014 parsing requires resolving against a year.",
|
|
1221
|
+
formatCapable: true,
|
|
1222
|
+
parseCapable: false,
|
|
1223
|
+
localeSensitive: false,
|
|
1224
|
+
calendarSensitive: true,
|
|
1225
|
+
timezoneSensitive: false,
|
|
1226
|
+
supportedTypes: TYPES_WITH.day,
|
|
1227
|
+
roundTripSafe: false
|
|
1228
|
+
},
|
|
1229
|
+
DD: {
|
|
1230
|
+
meaning: "Day of year, 2-digit minimum (01-366). Format-only.",
|
|
1231
|
+
formatCapable: true,
|
|
1232
|
+
parseCapable: false,
|
|
1233
|
+
localeSensitive: false,
|
|
1234
|
+
calendarSensitive: true,
|
|
1235
|
+
timezoneSensitive: false,
|
|
1236
|
+
supportedTypes: TYPES_WITH.day,
|
|
1237
|
+
roundTripSafe: false
|
|
1238
|
+
},
|
|
1239
|
+
DDD: {
|
|
1240
|
+
meaning: "Day of year, 3-digit zero-padded (001-366). Format-only.",
|
|
1241
|
+
formatCapable: true,
|
|
1242
|
+
parseCapable: false,
|
|
1243
|
+
localeSensitive: false,
|
|
1244
|
+
calendarSensitive: true,
|
|
1245
|
+
timezoneSensitive: false,
|
|
1246
|
+
supportedTypes: TYPES_WITH.day,
|
|
1247
|
+
roundTripSafe: false
|
|
1248
|
+
},
|
|
1249
|
+
LLLL: {
|
|
1250
|
+
meaning: "Stand-alone long month name (nominative case in Slavic locales). Identical to MMMM in most locales.",
|
|
1251
|
+
formatCapable: true,
|
|
1252
|
+
parseCapable: false,
|
|
1253
|
+
localeSensitive: true,
|
|
1254
|
+
calendarSensitive: true,
|
|
1255
|
+
timezoneSensitive: false,
|
|
1256
|
+
supportedTypes: TYPES_WITH.month,
|
|
1257
|
+
roundTripSafe: true
|
|
1258
|
+
},
|
|
1259
|
+
LLL: {
|
|
1260
|
+
meaning: "Stand-alone short month name. Identical to MMM in most locales.",
|
|
1261
|
+
formatCapable: true,
|
|
1262
|
+
parseCapable: false,
|
|
1263
|
+
localeSensitive: true,
|
|
1264
|
+
calendarSensitive: true,
|
|
1265
|
+
timezoneSensitive: false,
|
|
1266
|
+
supportedTypes: TYPES_WITH.month,
|
|
1267
|
+
roundTripSafe: true
|
|
1268
|
+
},
|
|
1269
|
+
cccc: {
|
|
1270
|
+
meaning: "Stand-alone long weekday name. Identical to EEEE in most locales.",
|
|
1271
|
+
formatCapable: true,
|
|
1272
|
+
parseCapable: false,
|
|
1273
|
+
localeSensitive: true,
|
|
1274
|
+
calendarSensitive: true,
|
|
1275
|
+
timezoneSensitive: false,
|
|
1276
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
1277
|
+
roundTripSafe: true
|
|
1278
|
+
},
|
|
1279
|
+
ccc: {
|
|
1280
|
+
meaning: "Stand-alone short weekday name. Identical to EEE in most locales.",
|
|
1281
|
+
formatCapable: true,
|
|
1282
|
+
parseCapable: false,
|
|
1283
|
+
localeSensitive: true,
|
|
1284
|
+
calendarSensitive: true,
|
|
1285
|
+
timezoneSensitive: false,
|
|
1286
|
+
supportedTypes: TYPES_WITH.dayOfWeek,
|
|
1287
|
+
roundTripSafe: true
|
|
1288
|
+
},
|
|
1289
|
+
GGGG: {
|
|
1290
|
+
meaning: 'Long era name (locale-aware, e.g. "Anno Domini"/"Before Christ"). Format-only.',
|
|
1291
|
+
formatCapable: true,
|
|
1292
|
+
parseCapable: false,
|
|
1293
|
+
localeSensitive: true,
|
|
1294
|
+
calendarSensitive: true,
|
|
1295
|
+
timezoneSensitive: false,
|
|
1296
|
+
supportedTypes: TYPES_WITH.year,
|
|
1297
|
+
roundTripSafe: false
|
|
1298
|
+
},
|
|
1299
|
+
G: {
|
|
1300
|
+
meaning: 'Short era name (locale-aware, e.g. "AD"/"BC"). Format-only.',
|
|
1301
|
+
formatCapable: true,
|
|
1302
|
+
parseCapable: false,
|
|
1303
|
+
localeSensitive: true,
|
|
1304
|
+
calendarSensitive: true,
|
|
1305
|
+
timezoneSensitive: false,
|
|
1306
|
+
supportedTypes: TYPES_WITH.year,
|
|
1307
|
+
roundTripSafe: false
|
|
1308
|
+
},
|
|
1309
|
+
zzzz: {
|
|
1310
|
+
meaning: 'Localized long timezone name (e.g. "Eastern Standard Time"). Format-only.',
|
|
1311
|
+
formatCapable: true,
|
|
1312
|
+
parseCapable: false,
|
|
1313
|
+
localeSensitive: true,
|
|
1314
|
+
calendarSensitive: false,
|
|
1315
|
+
timezoneSensitive: true,
|
|
1316
|
+
supportedTypes: TYPES_WITH.timeZoneId,
|
|
1317
|
+
roundTripSafe: false
|
|
1318
|
+
},
|
|
1319
|
+
z: {
|
|
1320
|
+
meaning: 'Localized short timezone name (e.g. "EST"). Format-only.',
|
|
1321
|
+
formatCapable: true,
|
|
1322
|
+
parseCapable: false,
|
|
1323
|
+
localeSensitive: true,
|
|
1324
|
+
calendarSensitive: false,
|
|
1325
|
+
timezoneSensitive: true,
|
|
1326
|
+
supportedTypes: TYPES_WITH.timeZoneId,
|
|
1327
|
+
roundTripSafe: false
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
var ALL_TOKEN_NAMES = Object.keys(TOKEN_METADATA);
|
|
1331
|
+
|
|
1332
|
+
// src/analyze.ts
|
|
1333
|
+
function tokenizeFormat(formatStr) {
|
|
1334
|
+
return tokenize(formatStr);
|
|
1335
|
+
}
|
|
1336
|
+
function listTokens() {
|
|
1337
|
+
return TOKENS.map(([name]) => ({ name, metadata: TOKEN_METADATA[name] }));
|
|
1338
|
+
}
|
|
1339
|
+
function tokenInfo(name) {
|
|
1340
|
+
return TOKEN_METADATA[name];
|
|
1341
|
+
}
|
|
1342
|
+
function analyzeFormat(formatStr) {
|
|
1343
|
+
if (formatStr.length > MAX_FORMAT_LENGTH) {
|
|
1344
|
+
throw new Error(
|
|
1345
|
+
`temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters (got ${formatStr.length}).`
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
const pieces = tokenize(formatStr);
|
|
1349
|
+
const tokens = [];
|
|
1350
|
+
const requiredFields = /* @__PURE__ */ new Set();
|
|
1351
|
+
const compatibleTypesSet = /* @__PURE__ */ new Set();
|
|
1352
|
+
let parseable = true;
|
|
1353
|
+
let localeSensitive = false;
|
|
1354
|
+
let calendarSensitive = false;
|
|
1355
|
+
let timezoneSensitive = false;
|
|
1356
|
+
let roundTripSafe = true;
|
|
1357
|
+
const warnings = [];
|
|
1358
|
+
let offset = 0;
|
|
1359
|
+
const unpaddedRun = [];
|
|
1360
|
+
const flushRun = () => {
|
|
1361
|
+
if (unpaddedRun.length >= 2) {
|
|
1362
|
+
warnings.push({
|
|
1363
|
+
code: "AMBIGUOUS_NUMERIC_RUN",
|
|
1364
|
+
message: `Adjacent unpadded numeric tokens "${unpaddedRun.join("")}" with no separator can be ambiguous to parse. Add a separator or use the padded form (e.g. "MM" instead of "M").`
|
|
1365
|
+
});
|
|
1366
|
+
}
|
|
1367
|
+
unpaddedRun.length = 0;
|
|
1368
|
+
};
|
|
1369
|
+
for (const piece of pieces) {
|
|
1370
|
+
if (piece.kind === "literal") {
|
|
1371
|
+
offset += piece.value.length;
|
|
1372
|
+
flushRun();
|
|
1373
|
+
continue;
|
|
1374
|
+
}
|
|
1375
|
+
const metadata = TOKEN_METADATA[piece.value];
|
|
1376
|
+
if (!metadata) {
|
|
1377
|
+
warnings.push({
|
|
1378
|
+
code: "UNKNOWN_TOKEN_NO_METADATA",
|
|
1379
|
+
message: `Token "${piece.value}" is recognized by the tokenizer but has no metadata entry in tokenMetadata.ts \u2014 this is a bug in temporal-fmt.`
|
|
1380
|
+
});
|
|
1381
|
+
offset += piece.value.length;
|
|
1382
|
+
continue;
|
|
1383
|
+
}
|
|
1384
|
+
tokens.push({ name: piece.value, position: offset, metadata });
|
|
1385
|
+
const handler = _handlerFor(piece.value);
|
|
1386
|
+
if (handler) {
|
|
1387
|
+
requiredFields.add(handler.field);
|
|
1388
|
+
}
|
|
1389
|
+
if (tokens.length === 1) {
|
|
1390
|
+
for (const t of metadata.supportedTypes) compatibleTypesSet.add(t);
|
|
1391
|
+
} else {
|
|
1392
|
+
const stillCompatible = /* @__PURE__ */ new Set();
|
|
1393
|
+
for (const t of compatibleTypesSet) {
|
|
1394
|
+
if (metadata.supportedTypes.includes(t)) stillCompatible.add(t);
|
|
1395
|
+
}
|
|
1396
|
+
compatibleTypesSet.clear();
|
|
1397
|
+
for (const t of stillCompatible) compatibleTypesSet.add(t);
|
|
1398
|
+
}
|
|
1399
|
+
if (!metadata.parseCapable) {
|
|
1400
|
+
parseable = false;
|
|
1401
|
+
warnings.push({
|
|
1402
|
+
code: "FORMAT_ONLY_TOKEN",
|
|
1403
|
+
message: `Token "${piece.value}" is format-only \u2014 it can't be parsed back into a value. Use a parse-capable variant (e.g. "d" instead of "do") if you need round-trip.`
|
|
1404
|
+
});
|
|
1405
|
+
}
|
|
1406
|
+
if (metadata.localeSensitive) localeSensitive = true;
|
|
1407
|
+
if (metadata.calendarSensitive) calendarSensitive = true;
|
|
1408
|
+
if (metadata.timezoneSensitive) timezoneSensitive = true;
|
|
1409
|
+
if (!metadata.roundTripSafe) roundTripSafe = false;
|
|
1410
|
+
if (UNPADDED_NUMERIC_TOKENS.has(piece.value)) {
|
|
1411
|
+
unpaddedRun.push(piece.value);
|
|
1412
|
+
} else {
|
|
1413
|
+
flushRun();
|
|
1414
|
+
}
|
|
1415
|
+
offset += piece.value.length;
|
|
1416
|
+
}
|
|
1417
|
+
flushRun();
|
|
1418
|
+
const tokenNames = tokens.map((t) => t.name);
|
|
1419
|
+
const has12Hour = tokenNames.some((t) => t === "hh" || t === "h");
|
|
1420
|
+
const has24Hour = tokenNames.some((t) => t === "HH" || t === "H");
|
|
1421
|
+
const hasAPeriod = tokenNames.some((t) => t === "a");
|
|
1422
|
+
if (has12Hour && !hasAPeriod) {
|
|
1423
|
+
warnings.push({
|
|
1424
|
+
code: "TWELVE_HOUR_WITHOUT_A",
|
|
1425
|
+
message: `12-hour token ("hh"/"h") used without an "a" (AM/PM) token \u2014 parse() can't tell AM from PM and throws at runtime.`
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
if (has12Hour && has24Hour) {
|
|
1429
|
+
warnings.push({
|
|
1430
|
+
code: "MIXED_12_AND_24_HOUR",
|
|
1431
|
+
message: "Mixing 24-hour and 12-hour tokens \u2014 parse() refuses to guess which is authoritative and throws at runtime."
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
const hasOffset = tokenNames.some((t) => t === "X" || t === "XX" || t === "XXX" || t === "x" || t === "xx" || t === "xxx");
|
|
1435
|
+
const hasZzz = tokenNames.some((t) => t === "zzz");
|
|
1436
|
+
if (hasOffset && hasZzz) {
|
|
1437
|
+
warnings.push({
|
|
1438
|
+
code: "ZZZ_WITH_OFFSET_TOKEN",
|
|
1439
|
+
message: `Format string has both "zzz" and an offset token \u2014 parse() cross-checks them and throws if the parsed offset disagrees with the zone's actual offset.`
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
if (hasOffset && !requiredFields.has("year")) {
|
|
1443
|
+
warnings.push({
|
|
1444
|
+
code: "OFFSET_WITHOUT_FULL_DATE",
|
|
1445
|
+
message: "Offset token used without a full date \u2014 parse() needs a complete date and time to build a ZonedDateTime and throws at runtime otherwise."
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
return {
|
|
1449
|
+
tokens,
|
|
1450
|
+
requiredFields: [...requiredFields].sort(),
|
|
1451
|
+
compatibleTypes: [...compatibleTypesSet].sort(),
|
|
1452
|
+
parseable,
|
|
1453
|
+
localeSensitive,
|
|
1454
|
+
calendarSensitive,
|
|
1455
|
+
timezoneSensitive,
|
|
1456
|
+
// Ambiguous iff at least one warning fired about an ambiguous run.
|
|
1457
|
+
ambiguous: warnings.some((w) => w.code === "AMBIGUOUS_NUMERIC_RUN"),
|
|
1458
|
+
roundTripSafe: roundTripSafe && parseable,
|
|
1459
|
+
warnings
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
function explainFormat(formatStr) {
|
|
1463
|
+
const analysis = analyzeFormat(formatStr);
|
|
1464
|
+
const lines = [];
|
|
1465
|
+
lines.push(`Format string: "${formatStr}"`);
|
|
1466
|
+
lines.push(`Tokens (${analysis.tokens.length}):`);
|
|
1467
|
+
for (const t of analysis.tokens) {
|
|
1468
|
+
lines.push(` ${t.name} @${t.position} \u2014 ${t.metadata.meaning}`);
|
|
1469
|
+
}
|
|
1470
|
+
if (analysis.requiredFields.length > 0) {
|
|
1471
|
+
lines.push(`Required fields: ${analysis.requiredFields.join(", ")}`);
|
|
1472
|
+
}
|
|
1473
|
+
if (analysis.compatibleTypes.length > 0) {
|
|
1474
|
+
lines.push(`Compatible Temporal types: ${analysis.compatibleTypes.join(", ")}`);
|
|
1475
|
+
}
|
|
1476
|
+
lines.push(`Parseable: ${analysis.parseable ? "yes" : "no"}`);
|
|
1477
|
+
lines.push(`Locale-sensitive: ${analysis.localeSensitive ? "yes" : "no"}`);
|
|
1478
|
+
lines.push(`Calendar-sensitive: ${analysis.calendarSensitive ? "yes" : "no"}`);
|
|
1479
|
+
lines.push(`Timezone-sensitive: ${analysis.timezoneSensitive ? "yes" : "no"}`);
|
|
1480
|
+
lines.push(`Ambiguous: ${analysis.ambiguous ? "yes" : "no"}`);
|
|
1481
|
+
lines.push(`Round-trip safe: ${analysis.roundTripSafe ? "yes" : "no"}`);
|
|
1482
|
+
if (analysis.warnings.length > 0) {
|
|
1483
|
+
lines.push("Warnings:");
|
|
1484
|
+
for (const w of analysis.warnings) {
|
|
1485
|
+
lines.push(` [${w.code}] ${w.message}`);
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
return lines.join("\n");
|
|
1489
|
+
}
|
|
1490
|
+
function isValidFormat(formatStr) {
|
|
1491
|
+
if (formatStr.length > MAX_FORMAT_LENGTH) return false;
|
|
1492
|
+
try {
|
|
1493
|
+
tokenize(formatStr);
|
|
1494
|
+
return true;
|
|
1495
|
+
} catch {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
function validateFormat(formatStr) {
|
|
1500
|
+
const analysis = analyzeFormat(formatStr);
|
|
1501
|
+
return analysis;
|
|
1502
|
+
}
|
|
1503
|
+
function fieldForToken(token) {
|
|
1504
|
+
return _handlerFor(token)?.field;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
// src/serialization.ts
|
|
1508
|
+
function parseISO(input) {
|
|
1509
|
+
const temporal = getTemporal();
|
|
1510
|
+
try {
|
|
1511
|
+
if (/^\d{4}-\d{2}-\d{2}T/.test(input) || /T\d{2}:\d{2}/.test(input)) {
|
|
1512
|
+
if (/[zZ]$/.test(input) || /[+-]\d{2}:?\d{2}$/.test(input)) {
|
|
1513
|
+
let iso = input;
|
|
1514
|
+
if (/[zZ]$/.test(iso)) {
|
|
1515
|
+
iso = iso.slice(0, -1) + "+00:00[UTC]";
|
|
1516
|
+
} else {
|
|
1517
|
+
const offsetMatch = /([+-]\d{2}:?\d{2})$/.exec(iso);
|
|
1518
|
+
if (offsetMatch) {
|
|
1519
|
+
iso = `${iso}[${offsetMatch[1]}]`;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
return temporal.ZonedDateTime.from(iso, { overflow: "reject" });
|
|
1523
|
+
}
|
|
1524
|
+
return temporal.PlainDateTime.from(input, { overflow: "reject" });
|
|
1525
|
+
}
|
|
1526
|
+
if (/^\d{4}-\d{2}-\d{2}/.test(input)) {
|
|
1527
|
+
return temporal.PlainDate.from(input, { overflow: "reject" });
|
|
1528
|
+
}
|
|
1529
|
+
if (/^\d{2}:\d{2}/.test(input)) {
|
|
1530
|
+
return temporal.PlainTime.from(input);
|
|
1531
|
+
}
|
|
1532
|
+
throw new Error(`temporal-fmt: parseISO("${input}") doesn't look like an ISO 8601 string.`);
|
|
1533
|
+
} catch (err) {
|
|
1534
|
+
throw new InvalidDateError({ input, reason: err.message });
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
function formatISO(value) {
|
|
1538
|
+
const v = value;
|
|
1539
|
+
if (typeof v?.toString !== "function") {
|
|
1540
|
+
throw new FormatSyntaxError({ reason: `formatISO() expects a Temporal value with toString(), got ${typeof value}.` });
|
|
1541
|
+
}
|
|
1542
|
+
return v.toString();
|
|
1543
|
+
}
|
|
1544
|
+
function parseRFC3339(input) {
|
|
1545
|
+
const re = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(\.\d+)?([Zz]|[+-]\d{2}:\d{2})$/;
|
|
1546
|
+
const m = re.exec(input);
|
|
1547
|
+
if (!m) {
|
|
1548
|
+
throw new FormatSyntaxError({ input, reason: "does not match RFC 3339 date-time grammar" });
|
|
1549
|
+
}
|
|
1550
|
+
const iso = input.replace(/[tT]/, "T").replace(/[zZ]$/, "+00:00[UTC]");
|
|
1551
|
+
return parseISO(iso);
|
|
1552
|
+
}
|
|
1553
|
+
function formatRFC3339(value) {
|
|
1554
|
+
const s = formatISO(value);
|
|
1555
|
+
if (!/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?(Z|[+-][0-9]{2}:[0-9]{2})$/.test(s)) {
|
|
1556
|
+
throw new FormatSyntaxError({ input: s, reason: "value did not produce RFC 3339-compliant output" });
|
|
1557
|
+
}
|
|
1558
|
+
return s;
|
|
1559
|
+
}
|
|
1560
|
+
function parseRFC2822(input) {
|
|
1561
|
+
const RFC2822_SHAPE = /^(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s+)?\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s+\d{2,4}\s+\d{2}:\d{2}(?::\d{2})?\s+(?:[+-]\d{4}|[A-Za-z]{1,5})$/;
|
|
1562
|
+
if (!RFC2822_SHAPE.test(input.trim())) {
|
|
1563
|
+
throw new FormatSyntaxError({ input, reason: "not a valid RFC 2822 date" });
|
|
1564
|
+
}
|
|
1565
|
+
const ms = Date.parse(input);
|
|
1566
|
+
if (Number.isNaN(ms)) {
|
|
1567
|
+
throw new FormatSyntaxError({ input, reason: "not a valid RFC 2822 date" });
|
|
1568
|
+
}
|
|
1569
|
+
return requireInstant().fromEpochMilliseconds(ms);
|
|
1570
|
+
}
|
|
1571
|
+
function formatRFC2822(value) {
|
|
1572
|
+
const v = value;
|
|
1573
|
+
let ms;
|
|
1574
|
+
if (typeof v?.toEpochMilliseconds === "function") {
|
|
1575
|
+
ms = v.toEpochMilliseconds();
|
|
1576
|
+
} else if (typeof v?.epochMilliseconds === "number") {
|
|
1577
|
+
ms = v.epochMilliseconds;
|
|
1578
|
+
} else if (typeof v?.toInstant === "function") {
|
|
1579
|
+
const inst = v.toInstant();
|
|
1580
|
+
if (typeof inst.epochMilliseconds === "number") {
|
|
1581
|
+
ms = inst.epochMilliseconds;
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
if (ms === void 0) {
|
|
1585
|
+
throw new FormatSyntaxError({ reason: `formatRFC2822() expects a value with epochMilliseconds, toEpochMilliseconds(), or toInstant(), got ${typeof value}.` });
|
|
1586
|
+
}
|
|
1587
|
+
return formatRFC2822FromMs(ms);
|
|
1588
|
+
}
|
|
1589
|
+
function formatRFC2822FromMs(ms) {
|
|
1590
|
+
try {
|
|
1591
|
+
const fmt = new Intl.DateTimeFormat("en-US", {
|
|
1592
|
+
weekday: "short",
|
|
1593
|
+
day: "2-digit",
|
|
1594
|
+
month: "short",
|
|
1595
|
+
year: "numeric",
|
|
1596
|
+
hour: "2-digit",
|
|
1597
|
+
minute: "2-digit",
|
|
1598
|
+
second: "2-digit",
|
|
1599
|
+
timeZone: "UTC",
|
|
1600
|
+
timeZoneName: "shortOffset",
|
|
1601
|
+
hour12: false
|
|
1602
|
+
});
|
|
1603
|
+
const parts = fmt.formatToParts(new Date(ms));
|
|
1604
|
+
const get = (t) => parts.find((p) => p.type === t)?.value ?? "";
|
|
1605
|
+
const tzRaw = get("timeZoneName");
|
|
1606
|
+
const tzMatch = tzRaw?.match(/GMT([+-])(\d+)(?::(\d+))?/);
|
|
1607
|
+
let tz;
|
|
1608
|
+
if (tzMatch) {
|
|
1609
|
+
const sign = tzMatch[1];
|
|
1610
|
+
const hours = tzMatch[2].padStart(2, "0");
|
|
1611
|
+
const minutes = (tzMatch[3] ?? "0").padStart(2, "0");
|
|
1612
|
+
tz = `${sign}${hours}${minutes}`;
|
|
1613
|
+
/* c8 ignore start @preserve -- timeZone is hardcoded to 'UTC' above,
|
|
1614
|
+
which always resolves cleanly, so shortOffset always returns a
|
|
1615
|
+
parseable "GMT+0"-shaped string in this environment's ICU. This
|
|
1616
|
+
branch only guards against an ICU build whose shortOffset output
|
|
1617
|
+
doesn't match the regex; can't trigger it without mocking Intl.
|
|
1618
|
+
The ignore starts before the closing brace of the if-block so it
|
|
1619
|
+
covers the whole else-branch node c8 tracks as a single unit. */
|
|
1620
|
+
} else {
|
|
1621
|
+
tz = "+0000";
|
|
1622
|
+
}
|
|
1623
|
+
/* c8 ignore stop @preserve */
|
|
1624
|
+
let hour = get("hour");
|
|
1625
|
+
/* c8 ignore start @preserve -- hour12:false with a fixed UTC zone
|
|
1626
|
+
never yields "24" in this environment's ICU (midnight formats as
|
|
1627
|
+
"00"). Some ICU versions/locales are documented to emit "24" for
|
|
1628
|
+
hour12:false, so this stays as a defensive normalization; not
|
|
1629
|
+
reachable here without mocking Intl.DateTimeFormat's output. */
|
|
1630
|
+
if (hour === "24") hour = "00";
|
|
1631
|
+
/* c8 ignore stop @preserve */
|
|
1632
|
+
return `${get("weekday")}, ${get("day")} ${get("month")} ${get("year")} ${hour}:${get("minute")}:${get("second")} ${tz}`;
|
|
1633
|
+
/* c8 ignore start @preserve -- Intl.DateTimeFormat is constructed
|
|
1634
|
+
above with a literal, always-valid timeZone: 'UTC' and no other
|
|
1635
|
+
user input reaches the constructor or formatToParts call, so this
|
|
1636
|
+
catch can't be triggered through the public API in a normal Intl
|
|
1637
|
+
environment (e.g. Node with full-icu). Kept as a genuine fallback
|
|
1638
|
+
for runtimes with a broken or absent Intl implementation. */
|
|
1639
|
+
} catch {
|
|
1640
|
+
const d = new Date(ms);
|
|
1641
|
+
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1642
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1643
|
+
const wd = days[d.getUTCDay()];
|
|
1644
|
+
const dd = String(d.getUTCDate()).padStart(2, "0");
|
|
1645
|
+
const mon = months[d.getUTCMonth()];
|
|
1646
|
+
const yyyy = d.getUTCFullYear();
|
|
1647
|
+
const hh = String(d.getUTCHours()).padStart(2, "0");
|
|
1648
|
+
const mm = String(d.getUTCMinutes()).padStart(2, "0");
|
|
1649
|
+
const ss = String(d.getUTCSeconds()).padStart(2, "0");
|
|
1650
|
+
return `${wd}, ${dd} ${mon} ${yyyy} ${hh}:${mm}:${ss} +0000`;
|
|
1651
|
+
}
|
|
1652
|
+
/* c8 ignore stop @preserve */
|
|
1653
|
+
}
|
|
1654
|
+
function parseHTTPDate(input) {
|
|
1655
|
+
const trimmed = input.trim();
|
|
1656
|
+
const ms = Date.parse(trimmed);
|
|
1657
|
+
if (Number.isNaN(ms)) {
|
|
1658
|
+
throw new FormatSyntaxError({ input, reason: "not a valid HTTP-date" });
|
|
1659
|
+
}
|
|
1660
|
+
return requireInstant().fromEpochMilliseconds(ms);
|
|
1661
|
+
}
|
|
1662
|
+
function formatHTTPDate(value) {
|
|
1663
|
+
const instant = value?.toInstant?.() ?? value;
|
|
1664
|
+
const ms = typeof instant === "object" && instant !== null && "epochMilliseconds" in instant ? instant.epochMilliseconds : (() => {
|
|
1665
|
+
throw new FormatSyntaxError({ reason: `formatHTTPDate() expects an Instant or ZonedDateTime, got ${typeof value}.` });
|
|
1666
|
+
})();
|
|
1667
|
+
const d = new Date(ms);
|
|
1668
|
+
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1669
|
+
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
1670
|
+
const wd = days[d.getUTCDay()];
|
|
1671
|
+
const dd = String(d.getUTCDate()).padStart(2, "0");
|
|
1672
|
+
const mon = months[d.getUTCMonth()];
|
|
1673
|
+
const yyyy = d.getUTCFullYear();
|
|
1674
|
+
const hh = String(d.getUTCHours()).padStart(2, "0");
|
|
1675
|
+
const mm = String(d.getUTCMinutes()).padStart(2, "0");
|
|
1676
|
+
const ss = String(d.getUTCSeconds()).padStart(2, "0");
|
|
1677
|
+
return `${wd}, ${dd} ${mon} ${yyyy} ${hh}:${mm}:${ss} GMT`;
|
|
1678
|
+
}
|
|
1679
|
+
function getInstant(value) {
|
|
1680
|
+
const v = value;
|
|
1681
|
+
if (typeof v?.toInstant === "function") {
|
|
1682
|
+
const inst = v.toInstant();
|
|
1683
|
+
if (typeof inst.epochNanoseconds === "bigint") {
|
|
1684
|
+
return { epochMilliseconds: inst.epochMilliseconds, epochNanoseconds: inst.epochNanoseconds };
|
|
1685
|
+
}
|
|
1686
|
+
return { epochMilliseconds: inst.epochMilliseconds, epochNanoseconds: BigInt(inst.epochMilliseconds) * 1000000n };
|
|
1687
|
+
}
|
|
1688
|
+
if (typeof v?.epochNanoseconds === "bigint") {
|
|
1689
|
+
return { epochMilliseconds: Number(v.epochNanoseconds / 1000000n), epochNanoseconds: v.epochNanoseconds };
|
|
1690
|
+
}
|
|
1691
|
+
if (typeof v?.epochMilliseconds === "number") {
|
|
1692
|
+
return { epochMilliseconds: v.epochMilliseconds, epochNanoseconds: BigInt(v.epochMilliseconds) * 1000000n };
|
|
1693
|
+
}
|
|
1694
|
+
throw new FormatSyntaxError({ reason: `expected an Instant or ZonedDateTime, got ${typeof value}.` });
|
|
1695
|
+
}
|
|
1696
|
+
function requireInstant() {
|
|
1697
|
+
const t = getTemporal().Instant;
|
|
1698
|
+
if (!t) throw new Error("temporal-fmt: Temporal.Instant is not available in this implementation.");
|
|
1699
|
+
return t;
|
|
1700
|
+
}
|
|
1701
|
+
function toUnixSeconds(value) {
|
|
1702
|
+
return getInstant(value).epochMilliseconds / 1e3;
|
|
1703
|
+
}
|
|
1704
|
+
function fromUnixSeconds(seconds) {
|
|
1705
|
+
return requireInstant().fromEpochMilliseconds(seconds * 1e3);
|
|
1706
|
+
}
|
|
1707
|
+
function fromUnixMilliseconds(ms) {
|
|
1708
|
+
return requireInstant().fromEpochMilliseconds(ms);
|
|
1709
|
+
}
|
|
1710
|
+
function fromUnixMicroseconds(\u00B5s) {
|
|
1711
|
+
return requireInstant().fromEpochNanoseconds(BigInt(\u00B5s) * 1000n);
|
|
1712
|
+
}
|
|
1713
|
+
function fromUnixNanoseconds(ns) {
|
|
1714
|
+
return requireInstant().fromEpochNanoseconds(ns);
|
|
1715
|
+
}
|
|
1716
|
+
function toUnixMilliseconds(value) {
|
|
1717
|
+
return getInstant(value).epochMilliseconds;
|
|
1718
|
+
}
|
|
1719
|
+
function toUnixMicroseconds(value) {
|
|
1720
|
+
const { epochNanoseconds } = getInstant(value);
|
|
1721
|
+
return Number(epochNanoseconds / 1000n);
|
|
1722
|
+
}
|
|
1723
|
+
function toUnixNanoseconds(value) {
|
|
1724
|
+
return getInstant(value).epochNanoseconds;
|
|
1725
|
+
}
|
|
1726
|
+
function parseSQL(input) {
|
|
1727
|
+
const trimmed = input.trim();
|
|
1728
|
+
const parseImpl = getParseImpl();
|
|
1729
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
|
|
1730
|
+
return parseImpl("yyyy-MM-dd", trimmed);
|
|
1731
|
+
}
|
|
1732
|
+
if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(trimmed)) {
|
|
1733
|
+
return parseImpl("yyyy-MM-dd HH:mm:ss", trimmed);
|
|
1734
|
+
}
|
|
1735
|
+
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(trimmed)) {
|
|
1736
|
+
return parseISO(trimmed);
|
|
1737
|
+
}
|
|
1738
|
+
throw new FormatSyntaxError({ input, reason: "not a recognized SQL date/time format" });
|
|
1739
|
+
}
|
|
1740
|
+
function formatSQL(value) {
|
|
1741
|
+
const v = value;
|
|
1742
|
+
const formatImpl = getFormatImpl();
|
|
1743
|
+
if (typeof v?.hour === "number") {
|
|
1744
|
+
return formatImpl(value, "yyyy-MM-dd HH:mm:ss");
|
|
1745
|
+
}
|
|
1746
|
+
return formatImpl(value, "yyyy-MM-dd");
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// src/config.ts
|
|
1750
|
+
var DEFAULT_CONFIG = {
|
|
1751
|
+
locale: DEFAULT_LOCALE,
|
|
1752
|
+
numberingSystem: "latn",
|
|
1753
|
+
firstDayOfWeek: 1,
|
|
1754
|
+
roundingMode: "nearest",
|
|
1755
|
+
disambiguation: "compatible",
|
|
1756
|
+
overflow: "reject",
|
|
1757
|
+
parseLenient: false,
|
|
1758
|
+
durationShowZeroValues: false
|
|
1759
|
+
};
|
|
1760
|
+
function createConfig(overrides = {}) {
|
|
1761
|
+
const merged = { ...DEFAULT_CONFIG, ...overrides };
|
|
1762
|
+
if (typeof merged.locale !== "string" || merged.locale.length === 0) {
|
|
1763
|
+
throw new Error(`temporal-fmt: config.locale must be a non-empty string (got ${String(merged.locale)}).`);
|
|
1764
|
+
}
|
|
1765
|
+
if (merged.firstDayOfWeek !== 1 && merged.firstDayOfWeek !== 7) {
|
|
1766
|
+
throw new Error(`temporal-fmt: config.firstDayOfWeek must be 1 (Monday) or 7 (Sunday) (got ${merged.firstDayOfWeek}).`);
|
|
1767
|
+
}
|
|
1768
|
+
if (!["nearest", "floor", "ceil", "trunc"].includes(merged.roundingMode)) {
|
|
1769
|
+
throw new Error(`temporal-fmt: config.roundingMode "${merged.roundingMode}" is not recognized.`);
|
|
1770
|
+
}
|
|
1771
|
+
if (!["compatible", "earlier", "later", "reject"].includes(merged.disambiguation)) {
|
|
1772
|
+
throw new Error(`temporal-fmt: config.disambiguation "${merged.disambiguation}" is not recognized.`);
|
|
1773
|
+
}
|
|
1774
|
+
if (!["constrain", "reject"].includes(merged.overflow)) {
|
|
1775
|
+
throw new Error(`temporal-fmt: config.overflow "${merged.overflow}" is not recognized.`);
|
|
1776
|
+
}
|
|
1777
|
+
return Object.freeze(merged);
|
|
1778
|
+
}
|
|
1779
|
+
function mergeWithConfig(config, perCall) {
|
|
1780
|
+
if (!config) return perCall;
|
|
1781
|
+
const extras = {};
|
|
1782
|
+
if (perCall.locale === void 0) extras.locale = config.locale;
|
|
1783
|
+
if (perCall.calendar === void 0 && config.calendar !== void 0) extras.calendar = config.calendar;
|
|
1784
|
+
if (perCall.timezone === void 0 && config.timezone !== void 0) extras.timezone = config.timezone;
|
|
1785
|
+
if (perCall.numberingSystem === void 0) extras.numberingSystem = config.numberingSystem;
|
|
1786
|
+
if (perCall.lenient === void 0 && config.parseLenient) extras.lenient = true;
|
|
1787
|
+
return { ...perCall, ...extras };
|
|
1788
|
+
}
|
|
1789
|
+
|
|
1790
|
+
// src/businessCalendar.ts
|
|
1791
|
+
function createBusinessCalendar(options = {}) {
|
|
1792
|
+
const weekend = new Set(options.weekend ?? [6, 7]);
|
|
1793
|
+
const workingHours = { ...options.workingHours ?? {} };
|
|
1794
|
+
for (let i = 1; i <= 7; i++) {
|
|
1795
|
+
if (workingHours[i] === void 0) {
|
|
1796
|
+
workingHours[i] = weekend.has(i) ? 0 : 8;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
return {
|
|
1800
|
+
weekend,
|
|
1801
|
+
holidays: options.holidays,
|
|
1802
|
+
workingHours,
|
|
1803
|
+
halfDays: new Set(options.halfDays ?? [])
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
function isBusinessDay(cal, value) {
|
|
1807
|
+
const v = value;
|
|
1808
|
+
let dow = v.dayOfWeek;
|
|
1809
|
+
if (typeof v.year === "number" && typeof v.month === "number" && typeof v.day === "number") {
|
|
1810
|
+
const d = new Date(Date.UTC(v.year, v.month - 1, v.day));
|
|
1811
|
+
const jsDow = d.getUTCDay();
|
|
1812
|
+
dow = jsDow === 0 ? 7 : jsDow;
|
|
1813
|
+
}
|
|
1814
|
+
if (typeof dow !== "number") {
|
|
1815
|
+
throw new Error("temporal-fmt: isBusinessDay() needs a value with dayOfWeek (or year/month/day to compute it).");
|
|
1816
|
+
}
|
|
1817
|
+
if (cal.weekend.has(dow)) return false;
|
|
1818
|
+
if (cal.holidays && cal.holidays.isHoliday(value)) return false;
|
|
1819
|
+
return true;
|
|
1820
|
+
}
|
|
1821
|
+
function nextBusinessDay(cal, value) {
|
|
1822
|
+
let candidate = add(value, 1, "days");
|
|
1823
|
+
for (let i = 0; i < 14; i++) {
|
|
1824
|
+
if (isBusinessDay(cal, candidate)) return candidate;
|
|
1825
|
+
candidate = add(candidate, 1, "days");
|
|
1826
|
+
}
|
|
1827
|
+
throw new Error("temporal-fmt: nextBusinessDay() gave up after 14 days \u2014 likely a misconfigured calendar (e.g. all days are weekends or holidays).");
|
|
1828
|
+
}
|
|
1829
|
+
function previousBusinessDay(cal, value) {
|
|
1830
|
+
let candidate = add(value, -1, "days");
|
|
1831
|
+
for (let i = 0; i < 14; i++) {
|
|
1832
|
+
if (isBusinessDay(cal, candidate)) return candidate;
|
|
1833
|
+
candidate = add(candidate, -1, "days");
|
|
1834
|
+
}
|
|
1835
|
+
throw new Error("temporal-fmt: previousBusinessDay() gave up after 14 days \u2014 likely a misconfigured calendar.");
|
|
1836
|
+
}
|
|
1837
|
+
var MAX_BUSINESS_DAY_TRAVERSAL = 1e5;
|
|
1838
|
+
function assertBusinessDayCount(days) {
|
|
1839
|
+
if (!Number.isSafeInteger(days)) {
|
|
1840
|
+
throw new RangeError(
|
|
1841
|
+
`temporal-fmt: business-day count must be a finite safe integer (got ${days}).`
|
|
1842
|
+
);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
function compareDateFields(a, b) {
|
|
1846
|
+
const av = a;
|
|
1847
|
+
const bv = b;
|
|
1848
|
+
const ay = av.year * 1e4 + av.month * 100 + av.day;
|
|
1849
|
+
const by = bv.year * 1e4 + bv.month * 100 + bv.day;
|
|
1850
|
+
return ay - by;
|
|
1851
|
+
}
|
|
1852
|
+
function addBusinessDays(cal, value, days) {
|
|
1853
|
+
assertBusinessDayCount(days);
|
|
1854
|
+
if (days === 0) return value;
|
|
1855
|
+
const sign = days > 0 ? 1 : -1;
|
|
1856
|
+
const absDays = Math.abs(days);
|
|
1857
|
+
if (absDays > MAX_BUSINESS_DAY_TRAVERSAL) {
|
|
1858
|
+
throw new RangeError(
|
|
1859
|
+
`temporal-fmt: addBusinessDays() exceeded the ${MAX_BUSINESS_DAY_TRAVERSAL}-day limit.`
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1862
|
+
let candidate = value;
|
|
1863
|
+
for (let i = 0; i < absDays; i++) {
|
|
1864
|
+
candidate = sign > 0 ? nextBusinessDay(cal, candidate) : previousBusinessDay(cal, candidate);
|
|
1865
|
+
}
|
|
1866
|
+
return candidate;
|
|
1867
|
+
}
|
|
1868
|
+
function subtractBusinessDays(cal, value, days) {
|
|
1869
|
+
assertBusinessDayCount(days);
|
|
1870
|
+
return addBusinessDays(cal, value, -days);
|
|
1871
|
+
}
|
|
1872
|
+
function differenceInBusinessDays(cal, a, b) {
|
|
1873
|
+
const rawDirection = compareDateFields(b, a);
|
|
1874
|
+
if (rawDirection === 0) return 0;
|
|
1875
|
+
const direction = rawDirection > 0 ? 1 : -1;
|
|
1876
|
+
let candidate = a;
|
|
1877
|
+
let count = 0;
|
|
1878
|
+
let traversedDays = 0;
|
|
1879
|
+
while (compareDateFields(candidate, b) !== 0) {
|
|
1880
|
+
candidate = add(candidate, direction, "days");
|
|
1881
|
+
traversedDays++;
|
|
1882
|
+
if (traversedDays > MAX_BUSINESS_DAY_TRAVERSAL) {
|
|
1883
|
+
throw new RangeError(
|
|
1884
|
+
`temporal-fmt: differenceInBusinessDays() exceeded the ${MAX_BUSINESS_DAY_TRAVERSAL}-day traversal limit.`
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1887
|
+
if (isBusinessDay(cal, candidate)) count += direction;
|
|
1888
|
+
}
|
|
1889
|
+
return count;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
// src/holidays.ts
|
|
1893
|
+
var MAX_HOLIDAY_YEAR_RANGE = 5e3;
|
|
1894
|
+
function createHolidayCalendar(specs) {
|
|
1895
|
+
const cache = /* @__PURE__ */ new Map();
|
|
1896
|
+
function forYear(year) {
|
|
1897
|
+
let list = cache.get(year);
|
|
1898
|
+
if (list) return list;
|
|
1899
|
+
list = specs.map((s) => {
|
|
1900
|
+
let md;
|
|
1901
|
+
if (s.compute) {
|
|
1902
|
+
md = s.compute(year);
|
|
1903
|
+
} else {
|
|
1904
|
+
md = { month: s.month, day: s.day };
|
|
1905
|
+
}
|
|
1906
|
+
return { ...md, name: s.name };
|
|
1907
|
+
});
|
|
1908
|
+
cache.set(year, list);
|
|
1909
|
+
return list;
|
|
1910
|
+
}
|
|
1911
|
+
return {
|
|
1912
|
+
isHoliday(value) {
|
|
1913
|
+
const v = value;
|
|
1914
|
+
if (typeof v.year !== "number" || typeof v.month !== "number" || typeof v.day !== "number") {
|
|
1915
|
+
throw new Error("temporal-fmt: isHoliday() needs a value with year/month/day.");
|
|
1916
|
+
}
|
|
1917
|
+
const list = forYear(v.year);
|
|
1918
|
+
return list.some((h) => h.month === v.month && h.day === v.day);
|
|
1919
|
+
},
|
|
1920
|
+
holidaysBetween(start, end) {
|
|
1921
|
+
const sv = start;
|
|
1922
|
+
const ev = end;
|
|
1923
|
+
if (typeof sv?.year !== "number" || typeof ev?.year !== "number") {
|
|
1924
|
+
throw new Error("temporal-fmt: holidaysBetween() needs start/end values with year/month/day.");
|
|
1925
|
+
}
|
|
1926
|
+
if (ev.year - sv.year > MAX_HOLIDAY_YEAR_RANGE) {
|
|
1927
|
+
throw new RangeError(
|
|
1928
|
+
`temporal-fmt: holidaysBetween() year range (${sv.year}\u2013${ev.year}) exceeds the ${MAX_HOLIDAY_YEAR_RANGE}-year limit. Split the query into smaller ranges.`
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
const result = [];
|
|
1932
|
+
for (let y = sv.year; y <= ev.year; y++) {
|
|
1933
|
+
const list = forYear(y);
|
|
1934
|
+
for (const h of list) {
|
|
1935
|
+
const date = { year: y, month: h.month, day: h.day };
|
|
1936
|
+
if (compare(date, sv) >= 0 && compare(date, ev) <= 0) {
|
|
1937
|
+
result.push({ year: y, month: h.month, day: h.day });
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return result;
|
|
1942
|
+
}
|
|
1943
|
+
};
|
|
1944
|
+
}
|
|
1945
|
+
function nextHoliday(cal, value) {
|
|
1946
|
+
let candidate = add(value, 1, "days");
|
|
1947
|
+
for (let i = 0; i < 365 * 5; i++) {
|
|
1948
|
+
if (cal.isHoliday(candidate)) return candidate;
|
|
1949
|
+
candidate = add(candidate, 1, "days");
|
|
1950
|
+
}
|
|
1951
|
+
return void 0;
|
|
1952
|
+
}
|
|
1953
|
+
function previousHoliday(cal, value) {
|
|
1954
|
+
let candidate = add(value, -1, "days");
|
|
1955
|
+
for (let i = 0; i < 365 * 5; i++) {
|
|
1956
|
+
if (cal.isHoliday(candidate)) return candidate;
|
|
1957
|
+
candidate = add(candidate, -1, "days");
|
|
1958
|
+
}
|
|
1959
|
+
return void 0;
|
|
1960
|
+
}
|
|
1961
|
+
function holidaysBetween(cal, start, end) {
|
|
1962
|
+
return cal.holidaysBetween(start, end);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
// src/ideData.ts
|
|
1966
|
+
function tokenFamily(name) {
|
|
1967
|
+
if (/^y+$/.test(name)) return "Year";
|
|
1968
|
+
if (/^[ML]+$/.test(name)) return "Month";
|
|
1969
|
+
if (/^[decD]+$/.test(name)) return "Day";
|
|
1970
|
+
if (/^[Ec]+$/.test(name)) return "Weekday";
|
|
1971
|
+
if (/^[Qq]+$/.test(name)) return "Quarter";
|
|
1972
|
+
if (/^[Gg]+$/.test(name)) return "Era";
|
|
1973
|
+
if (/^[Hh]+$/.test(name)) return "Hour";
|
|
1974
|
+
if (/^m+$/.test(name)) return "Minute";
|
|
1975
|
+
if (/^s+$/.test(name)) return "Second";
|
|
1976
|
+
if (/^S+$/.test(name)) return "Fractional Second";
|
|
1977
|
+
if (name === "a") return "Day Period";
|
|
1978
|
+
if (name === "zzz") return "Time Zone";
|
|
1979
|
+
if (/^[Xx]+$/.test(name)) return "UTC Offset";
|
|
1980
|
+
if (name === "do") return "Ordinal Day";
|
|
1981
|
+
if (name === "ww" || name === "RRRR") return "ISO Week";
|
|
1982
|
+
return "Other";
|
|
1983
|
+
}
|
|
1984
|
+
function getAutocompleteData() {
|
|
1985
|
+
return ALL_TOKEN_NAMES.map((name) => {
|
|
1986
|
+
const meta = TOKEN_METADATA[name];
|
|
1987
|
+
return {
|
|
1988
|
+
label: name,
|
|
1989
|
+
detail: meta.meaning,
|
|
1990
|
+
documentation: [
|
|
1991
|
+
meta.meaning,
|
|
1992
|
+
``,
|
|
1993
|
+
`Format-capable: ${meta.formatCapable}`,
|
|
1994
|
+
`Parse-capable: ${meta.parseCapable}`,
|
|
1995
|
+
`Locale-sensitive: ${meta.localeSensitive}`,
|
|
1996
|
+
`Calendar-sensitive: ${meta.calendarSensitive}`,
|
|
1997
|
+
`Timezone-sensitive: ${meta.timezoneSensitive}`,
|
|
1998
|
+
`Round-trip safe: ${meta.roundTripSafe}`,
|
|
1999
|
+
`Supported types: ${meta.supportedTypes.join(", ")}`
|
|
2000
|
+
].join("\n"),
|
|
2001
|
+
family: tokenFamily(name)
|
|
2002
|
+
};
|
|
2003
|
+
});
|
|
2004
|
+
}
|
|
2005
|
+
function getHoverDocs() {
|
|
2006
|
+
const result = {};
|
|
2007
|
+
for (const name of ALL_TOKEN_NAMES) {
|
|
2008
|
+
const meta = TOKEN_METADATA[name];
|
|
2009
|
+
result[name] = {
|
|
2010
|
+
signature: name,
|
|
2011
|
+
summary: meta.meaning,
|
|
2012
|
+
details: [
|
|
2013
|
+
// every entry in TOKEN_METADATA currently has formatCapable:
|
|
2014
|
+
// true (verified: 51/51). The 'no' branch reflects real,
|
|
2015
|
+
// intended behavior for a future format-incapable token —
|
|
2016
|
+
// there's no such token today, so this isn't reachable data,
|
|
2017
|
+
// not dead logic. Every other field on this line has real
|
|
2018
|
+
// true/false variance across the token table and is exercised
|
|
2019
|
+
// by this same loop running over ALL_TOKEN_NAMES.
|
|
2020
|
+
/* c8 ignore next */
|
|
2021
|
+
`Format-capable: ${meta.formatCapable ? "yes" : "no"}`,
|
|
2022
|
+
`Parse-capable: ${meta.parseCapable ? "yes" : "no"}`,
|
|
2023
|
+
`Locale-sensitive: ${meta.localeSensitive ? "yes" : "no"}`,
|
|
2024
|
+
`Calendar-sensitive: ${meta.calendarSensitive ? "yes" : "no"}`,
|
|
2025
|
+
`Timezone-sensitive: ${meta.timezoneSensitive ? "yes" : "no"}`,
|
|
2026
|
+
`Round-trip safe: ${meta.roundTripSafe ? "yes" : "no"}`,
|
|
2027
|
+
`Supported types: ${meta.supportedTypes.join(", ")}`
|
|
2028
|
+
].join("\n")
|
|
2029
|
+
};
|
|
2030
|
+
}
|
|
2031
|
+
return result;
|
|
2032
|
+
}
|
|
2033
|
+
function getInlineDiagnostics(formatStr) {
|
|
2034
|
+
const analysis = analyzeFormat(formatStr);
|
|
2035
|
+
const diagnostics = [];
|
|
2036
|
+
for (const warning of analysis.warnings) {
|
|
2037
|
+
let message = warning.message;
|
|
2038
|
+
let suggestion;
|
|
2039
|
+
if (warning.code === "TWELVE_HOUR_WITHOUT_A") {
|
|
2040
|
+
suggestion = 'Add an "a" token (e.g. "h:mm a") or use "H:mm" for 24-hour.';
|
|
2041
|
+
} else if (warning.code === "MIXED_12_AND_24_HOUR") {
|
|
2042
|
+
suggestion = 'Pick one form: "HH:mm" for 24-hour or "h:mm a" for 12-hour.';
|
|
2043
|
+
} else if (warning.code === "AMBIGUOUS_NUMERIC_RUN") {
|
|
2044
|
+
suggestion = 'Add a separator or use padded forms (e.g. "MM" instead of "M").';
|
|
2045
|
+
} else if (warning.code === "FORMAT_ONLY_TOKEN") {
|
|
2046
|
+
suggestion = 'Use a parse-capable variant (e.g. "d" instead of "do").';
|
|
2047
|
+
}
|
|
2048
|
+
diagnostics.push({
|
|
2049
|
+
startColumn: 0,
|
|
2050
|
+
endColumn: formatStr.length,
|
|
2051
|
+
severity: "warning",
|
|
2052
|
+
message,
|
|
2053
|
+
code: warning.code,
|
|
2054
|
+
suggestion
|
|
2055
|
+
});
|
|
2056
|
+
}
|
|
2057
|
+
return diagnostics;
|
|
2058
|
+
}
|
|
2059
|
+
var DAYJS_TO_TEMPORAL_FMT = [
|
|
2060
|
+
{ from: "YYYY", to: "yyyy" },
|
|
2061
|
+
{ from: "YY", to: "yy" },
|
|
2062
|
+
{ from: "MMMM", to: "MMMM" },
|
|
2063
|
+
{ from: "MMM", to: "MMM" },
|
|
2064
|
+
{ from: "MM", to: "MM" },
|
|
2065
|
+
{ from: "M", to: "M" },
|
|
2066
|
+
{ from: "DD", to: "dd" },
|
|
2067
|
+
{ from: "D", to: "d" },
|
|
2068
|
+
{ from: "Do", to: null, notes: `Ordinal day (AdvancedFormat) \u2014 use temporal-fmt's own "do" token instead.` },
|
|
2069
|
+
{ from: "dddd", to: "EEEE" },
|
|
2070
|
+
{ from: "ddd", to: "EEE" },
|
|
2071
|
+
{ from: "dd", to: null, notes: 'Min-name weekday (e.g. "Tu") \u2014 temporal-fmt has no equivalent width.' },
|
|
2072
|
+
{ from: "d", to: null, notes: 'Numeric weekday (0-6) \u2014 no temporal-fmt equivalent; not the same as "d" here, which is day-of-month.' },
|
|
2073
|
+
{ from: "HH", to: "HH" },
|
|
2074
|
+
{ from: "H", to: "H" },
|
|
2075
|
+
{ from: "hh", to: "hh" },
|
|
2076
|
+
{ from: "h", to: "h" },
|
|
2077
|
+
{ from: "kk", to: null, notes: "Hour 1-24 (AdvancedFormat) \u2014 no temporal-fmt equivalent." },
|
|
2078
|
+
{ from: "k", to: null, notes: "Hour 1-24 (AdvancedFormat) \u2014 no temporal-fmt equivalent." },
|
|
2079
|
+
{ from: "mm", to: "mm" },
|
|
2080
|
+
{ from: "m", to: "m" },
|
|
2081
|
+
{ from: "ss", to: "ss" },
|
|
2082
|
+
{ from: "s", to: "s" },
|
|
2083
|
+
{ from: "SSS", to: "SSS" },
|
|
2084
|
+
{ from: "A", to: "a", notes: "Uppercase AM/PM in Day.js \u2014 temporal-fmt is always lowercase." },
|
|
2085
|
+
{ from: "a", to: "a" },
|
|
2086
|
+
{ from: "ZZ", to: "XX", notes: "Numeric UTC offset, no colon." },
|
|
2087
|
+
{ from: "Z", to: "XXX", notes: "Numeric UTC offset with colon." },
|
|
2088
|
+
{ from: "X", to: null, notes: "Unix timestamp (seconds) \u2014 use fromUnixSeconds() instead." },
|
|
2089
|
+
{ from: "x", to: null, notes: "Unix timestamp (ms) \u2014 use fromUnixMilliseconds() instead." },
|
|
2090
|
+
{ from: "Qo", to: null, notes: "Ordinal quarter (AdvancedFormat) \u2014 no temporal-fmt equivalent." },
|
|
2091
|
+
{ from: "Q", to: "Q" },
|
|
2092
|
+
{ from: "Mo", to: null, notes: "Ordinal month (AdvancedFormat) \u2014 no temporal-fmt equivalent." },
|
|
2093
|
+
{ from: "ww", to: "ww" },
|
|
2094
|
+
{ from: "wo", to: null, notes: "Ordinal ISO week (AdvancedFormat) \u2014 no temporal-fmt equivalent." },
|
|
2095
|
+
{ from: "w", to: null, notes: `Unpadded ISO week \u2014 temporal-fmt's "ww" is always 2-digit.` },
|
|
2096
|
+
{ from: "gggg", to: "RRRR", notes: "Week-numbering year, not the calendar year \u2014 same caveat as temporal-fmt's RRRR." },
|
|
2097
|
+
{ from: "L", to: null, notes: "Localized date format (AdvancedFormat) \u2014 write the format string out explicitly." },
|
|
2098
|
+
{ from: "LL", to: null, notes: "Localized date format (AdvancedFormat) \u2014 write the format string out explicitly." },
|
|
2099
|
+
{ from: "LLL", to: null, notes: "Localized date format (AdvancedFormat) \u2014 write the format string out explicitly." },
|
|
2100
|
+
{ from: "LLLL", to: null, notes: "Localized date format (AdvancedFormat) \u2014 write the format string out explicitly." },
|
|
2101
|
+
{ from: "LT", to: null, notes: "Localized time format (AdvancedFormat) \u2014 write the format string out explicitly." },
|
|
2102
|
+
{ from: "LTS", to: null, notes: "Localized time format (AdvancedFormat) \u2014 write the format string out explicitly." }
|
|
2103
|
+
];
|
|
2104
|
+
var DATE_FNS_TO_TEMPORAL_FMT = [
|
|
2105
|
+
{ from: "yyyy", to: "yyyy" },
|
|
2106
|
+
{ from: "yy", to: "yy" },
|
|
2107
|
+
{ from: "y", to: null, notes: 'Unpadded calendar year, opt-in via useAdditionalWeekYearTokens \u2014 temporal-fmt has no unpadded-year token; use "yyyy".' },
|
|
2108
|
+
{ from: "MMMM", to: "MMMM" },
|
|
2109
|
+
{ from: "MMM", to: "MMM" },
|
|
2110
|
+
{ from: "MM", to: "MM" },
|
|
2111
|
+
{ from: "M", to: "M" },
|
|
2112
|
+
{ from: "LLLL", to: "LLLL" },
|
|
2113
|
+
{ from: "LLL", to: "LLL" },
|
|
2114
|
+
{ from: "dd", to: "dd" },
|
|
2115
|
+
{ from: "d", to: "d" },
|
|
2116
|
+
{ from: "do", to: "do" },
|
|
2117
|
+
{ from: "DDD", to: "DDD" },
|
|
2118
|
+
{ from: "DD", to: "DD" },
|
|
2119
|
+
{ from: "D", to: "D", notes: `Day-of-year, opt-in via useAdditionalDayOfYearTokens \u2014 matches temporal-fmt's own "D" already.` },
|
|
2120
|
+
{ from: "EEEE", to: "EEEE" },
|
|
2121
|
+
{ from: "EEE", to: "EEE" },
|
|
2122
|
+
{ from: "eeee", to: null, notes: "Locale-aware numeric weekday \u2014 no temporal-fmt equivalent." },
|
|
2123
|
+
{ from: "cccc", to: "cccc" },
|
|
2124
|
+
{ from: "ccc", to: "ccc" },
|
|
2125
|
+
{ from: "HH", to: "HH" },
|
|
2126
|
+
{ from: "H", to: "H" },
|
|
2127
|
+
{ from: "hh", to: "hh" },
|
|
2128
|
+
{ from: "h", to: "h" },
|
|
2129
|
+
{ from: "mm", to: "mm" },
|
|
2130
|
+
{ from: "m", to: "m" },
|
|
2131
|
+
{ from: "ss", to: "ss" },
|
|
2132
|
+
{ from: "s", to: "s" },
|
|
2133
|
+
{ from: "SSS", to: "SSS" },
|
|
2134
|
+
{ from: "a", to: "a" },
|
|
2135
|
+
{ from: "aaa", to: "a" },
|
|
2136
|
+
{ from: "XXX", to: "XXX" },
|
|
2137
|
+
{ from: "XX", to: "XX" },
|
|
2138
|
+
{ from: "X", to: "X", notes: `Opt-in via useAdditionalDayOfYearTokens-adjacent rules in date-fns v3+; matches temporal-fmt's own "X" already.` },
|
|
2139
|
+
{ from: "xxx", to: "xxx" },
|
|
2140
|
+
{ from: "xx", to: "xx" },
|
|
2141
|
+
{ from: "x", to: "x" },
|
|
2142
|
+
{ from: "zzzz", to: "zzzz" },
|
|
2143
|
+
{ from: "zzz", to: "zzz" },
|
|
2144
|
+
{ from: "z", to: "z" },
|
|
2145
|
+
{ from: "QQQ", to: "QQQ" },
|
|
2146
|
+
{ from: "Q", to: "Q" },
|
|
2147
|
+
{ from: "GGGG", to: "GGGG" },
|
|
2148
|
+
{ from: "GGG", to: null, notes: 'Abbreviated era \u2014 temporal-fmt only has "G" (short) and "GGGG" (long).' },
|
|
2149
|
+
{ from: "GG", to: null, notes: 'Abbreviated era \u2014 temporal-fmt only has "G" (short) and "GGGG" (long).' },
|
|
2150
|
+
{ from: "G", to: "G" },
|
|
2151
|
+
{ from: "ww", to: "ww" },
|
|
2152
|
+
{ from: "w", to: null, notes: `Unpadded local week number \u2014 temporal-fmt's "ww" is ISO-week and always 2-digit.` },
|
|
2153
|
+
{ from: "RRRR", to: "RRRR" },
|
|
2154
|
+
{ from: "R", to: null, notes: `Unpadded ISO week-numbering year \u2014 temporal-fmt's "RRRR" is always 4-digit.` },
|
|
2155
|
+
{ from: "Y", to: null, notes: 'Week-numbering year (locale week rules), opt-in \u2014 no temporal-fmt equivalent; "RRRR" is ISO week-numbering, a different rule set.' },
|
|
2156
|
+
{ from: "PPPP", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2157
|
+
{ from: "PPP", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2158
|
+
{ from: "PP", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2159
|
+
{ from: "P", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2160
|
+
{ from: "pppp", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2161
|
+
{ from: "ppp", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2162
|
+
{ from: "pp", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." },
|
|
2163
|
+
{ from: "p", to: null, notes: "Localized composite format \u2014 write the format string out explicitly." }
|
|
2164
|
+
];
|
|
2165
|
+
function previewFormat(formatStr, sample) {
|
|
2166
|
+
const value = sample ?? {
|
|
2167
|
+
year: 2026,
|
|
2168
|
+
month: 8,
|
|
2169
|
+
day: 4,
|
|
2170
|
+
hour: 15,
|
|
2171
|
+
minute: 45,
|
|
2172
|
+
second: 30,
|
|
2173
|
+
millisecond: 123,
|
|
2174
|
+
dayOfWeek: 2,
|
|
2175
|
+
timeZoneId: "UTC",
|
|
2176
|
+
offset: "+00:00",
|
|
2177
|
+
calendarId: "iso8601"
|
|
2178
|
+
};
|
|
2179
|
+
return format(value, formatStr, { locale: "en-US" });
|
|
2180
|
+
}
|
|
2181
|
+
function getDocUrl(tokenName) {
|
|
2182
|
+
void tokenName;
|
|
2183
|
+
return "README.md#token-reference";
|
|
2184
|
+
}
|
|
2185
|
+
|
|
2186
|
+
// src/codemod.ts
|
|
2187
|
+
function splitOnBrackets(source) {
|
|
2188
|
+
const pieces = [];
|
|
2189
|
+
let i = 0;
|
|
2190
|
+
while (i < source.length) {
|
|
2191
|
+
if (source[i] === "[") {
|
|
2192
|
+
const end = source.indexOf("]", i + 1);
|
|
2193
|
+
if (end === -1) {
|
|
2194
|
+
pieces.push({ kind: "token", value: source.slice(i) });
|
|
2195
|
+
break;
|
|
2196
|
+
}
|
|
2197
|
+
pieces.push({ kind: "literal", value: source.slice(i + 1, end) });
|
|
2198
|
+
i = end + 1;
|
|
2199
|
+
} else {
|
|
2200
|
+
let j = i;
|
|
2201
|
+
while (j < source.length && source[j] !== "[") j += 1;
|
|
2202
|
+
pieces.push({ kind: "token", value: source.slice(i, j) });
|
|
2203
|
+
i = j;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
return pieces;
|
|
2207
|
+
}
|
|
2208
|
+
function splitIntoRuns(span, sortedFrom) {
|
|
2209
|
+
const pieces = [];
|
|
2210
|
+
let i = 0;
|
|
2211
|
+
while (i < span.length) {
|
|
2212
|
+
const match = sortedFrom.find((tok) => span.startsWith(tok, i));
|
|
2213
|
+
if (match) {
|
|
2214
|
+
pieces.push({ kind: "token", value: match });
|
|
2215
|
+
i += match.length;
|
|
2216
|
+
continue;
|
|
2217
|
+
}
|
|
2218
|
+
const last = pieces[pieces.length - 1];
|
|
2219
|
+
if (last && last.kind === "literal") {
|
|
2220
|
+
last.value += span[i];
|
|
2221
|
+
} else {
|
|
2222
|
+
pieces.push({ kind: "literal", value: span[i] });
|
|
2223
|
+
}
|
|
2224
|
+
i += 1;
|
|
2225
|
+
}
|
|
2226
|
+
return pieces;
|
|
2227
|
+
}
|
|
2228
|
+
function translate(source, table, sourceLibLabel) {
|
|
2229
|
+
const byFrom = new Map(table.map((hint) => [hint.from, hint.to]));
|
|
2230
|
+
const sortedFrom = [...byFrom.keys()].sort((a, b) => b.length - a.length);
|
|
2231
|
+
const bracketPieces = splitOnBrackets(source);
|
|
2232
|
+
let out = "";
|
|
2233
|
+
for (const piece of bracketPieces) {
|
|
2234
|
+
if (piece.kind === "literal") {
|
|
2235
|
+
out += `'${piece.value.replace(/'/g, "''")}'`;
|
|
2236
|
+
continue;
|
|
2237
|
+
}
|
|
2238
|
+
for (const run of splitIntoRuns(piece.value, sortedFrom)) {
|
|
2239
|
+
if (run.kind === "token") {
|
|
2240
|
+
const mapped = byFrom.get(run.value);
|
|
2241
|
+
if (mapped === void 0 || mapped === null) {
|
|
2242
|
+
throw new Error(
|
|
2243
|
+
`temporal-fmt: "${run.value}" has no ${sourceLibLabel} -> temporal-fmt mapping (in format string "${source}"). Write the equivalent temporal-fmt token in by hand, or wrap it in brackets if it was meant as literal text.`
|
|
2244
|
+
);
|
|
2245
|
+
}
|
|
2246
|
+
out += mapped;
|
|
2247
|
+
} else if (/[a-zA-Z]/.test(run.value)) {
|
|
2248
|
+
out += `'${run.value.replace(/'/g, "''")}'`;
|
|
2249
|
+
} else {
|
|
2250
|
+
out += run.value;
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
return out;
|
|
2255
|
+
}
|
|
2256
|
+
function translateDayjsFormatString(formatStr) {
|
|
2257
|
+
return translate(formatStr, DAYJS_TO_TEMPORAL_FMT, "Day.js");
|
|
2258
|
+
}
|
|
2259
|
+
function translateDateFnsFormatString(formatStr) {
|
|
2260
|
+
return translate(formatStr, DATE_FNS_TO_TEMPORAL_FMT, "date-fns");
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
// src/runtime.ts
|
|
2264
|
+
var formatOverride;
|
|
2265
|
+
var parseOverride;
|
|
2266
|
+
function getFormatImpl() {
|
|
2267
|
+
return formatOverride ? formatOverride.impl : format;
|
|
2268
|
+
}
|
|
2269
|
+
function getParseImpl() {
|
|
2270
|
+
return parseOverride ? parseOverride.impl : parse;
|
|
2271
|
+
}
|
|
2272
|
+
var OverrideConflictError = class extends Error {
|
|
2273
|
+
constructor(point, existingOwner, attemptedBy) {
|
|
2274
|
+
super(
|
|
2275
|
+
`temporal-fmt: "${point}" is already overridden by mod "${existingOwner}" \u2014 mod "${attemptedBy}" can't also override it. Only one mod may hold each override point; if "${attemptedBy}" needs "${existingOwner}"'s behavior included, that logic needs to move into whichever mod ends up owning the override, not be layered through a second overrideFormat()/overrideParse() call.`
|
|
2276
|
+
);
|
|
2277
|
+
this.point = point;
|
|
2278
|
+
this.existingOwner = existingOwner;
|
|
2279
|
+
this.attemptedBy = attemptedBy;
|
|
2280
|
+
this.name = "OverrideConflictError";
|
|
2281
|
+
}
|
|
2282
|
+
point;
|
|
2283
|
+
existingOwner;
|
|
2284
|
+
attemptedBy;
|
|
2285
|
+
};
|
|
2286
|
+
function setFormatOverride(impl, installedBy) {
|
|
2287
|
+
if (formatOverride) throw new OverrideConflictError("format", formatOverride.installedBy, installedBy);
|
|
2288
|
+
formatOverride = { impl, installedBy };
|
|
2289
|
+
}
|
|
2290
|
+
function setParseOverride(impl, installedBy) {
|
|
2291
|
+
if (parseOverride) throw new OverrideConflictError("parse", parseOverride.installedBy, installedBy);
|
|
2292
|
+
parseOverride = { impl, installedBy };
|
|
2293
|
+
}
|
|
2294
|
+
function createOverridable(base, pointName) {
|
|
2295
|
+
let current;
|
|
2296
|
+
return {
|
|
2297
|
+
get: () => current ? current.impl : base,
|
|
2298
|
+
set: (impl, installedBy) => {
|
|
2299
|
+
if (current) throw new OverrideConflictError(pointName, current.installedBy, installedBy);
|
|
2300
|
+
current = { impl, installedBy };
|
|
2301
|
+
},
|
|
2302
|
+
/* c8 ignore start @preserve -- reset() is only ever called from
|
|
2303
|
+
* _resetGeneratedOverridesForTesting(), which itself is a
|
|
2304
|
+
* vitest-only escape hatch not exported from dist/index.js (see its
|
|
2305
|
+
* own doc comment below) — so this function has no path reachable
|
|
2306
|
+
* from test/*.test.js, which imports only the public dist/index.js
|
|
2307
|
+
* surface. Covered instead by vitest/modApi.unit.test.ts's afterEach
|
|
2308
|
+
* hook, which calls _resetGeneratedOverridesForTesting() directly
|
|
2309
|
+
* against src/runtime.js on every run. */
|
|
2310
|
+
reset: () => {
|
|
2311
|
+
current = void 0;
|
|
2312
|
+
}
|
|
2313
|
+
/* c8 ignore stop @preserve */
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
var compileFormatRegistry = createOverridable(compileFormat, "compileFormat");
|
|
2317
|
+
var compileParserRegistry = createOverridable(compileParser, "compileParser");
|
|
2318
|
+
var parseRelativeRegistry = createOverridable(parseRelative, "parseRelative");
|
|
2319
|
+
var explainFormatRegistry = createOverridable(explainFormat, "explainFormat");
|
|
2320
|
+
var tokenizeFormatRegistry = createOverridable(tokenizeFormat, "tokenizeFormat");
|
|
2321
|
+
var listTokensRegistry = createOverridable(listTokens, "listTokens");
|
|
2322
|
+
var tokenInfoRegistry = createOverridable(tokenInfo, "tokenInfo");
|
|
2323
|
+
var isValidFormatRegistry = createOverridable(isValidFormat, "isValidFormat");
|
|
2324
|
+
var validateFormatRegistry = createOverridable(validateFormat, "validateFormat");
|
|
2325
|
+
var fieldForTokenRegistry = createOverridable(fieldForToken, "fieldForToken");
|
|
2326
|
+
var monthsInYearRegistry = createOverridable(monthsInYear, "monthsInYear");
|
|
2327
|
+
var isLeapYearRegistry = createOverridable(isLeapYear, "isLeapYear");
|
|
2328
|
+
var isLeapMonthRegistry = createOverridable(isLeapMonth, "isLeapMonth");
|
|
2329
|
+
var weekOfYearRegistry = createOverridable(weekOfYear, "weekOfYear");
|
|
2330
|
+
var weekYearRegistry = createOverridable(weekYear, "weekYear");
|
|
2331
|
+
var getMonthRegistry = createOverridable(getMonth, "getMonth");
|
|
2332
|
+
var getWeekdayRegistry = createOverridable(getWeekday, "getWeekday");
|
|
2333
|
+
var isEqualRegistry = createOverridable(isEqual, "isEqual");
|
|
2334
|
+
var isBeforeRegistry = createOverridable(isBefore, "isBefore");
|
|
2335
|
+
var isAfterRegistry = createOverridable(isAfter, "isAfter");
|
|
2336
|
+
var clampRegistry = createOverridable(clamp, "clamp");
|
|
2337
|
+
var isBetweenRegistry = createOverridable(isBetween, "isBetween");
|
|
2338
|
+
var isTodayRegistry = createOverridable(isToday, "isToday");
|
|
2339
|
+
var isTomorrowRegistry = createOverridable(isTomorrow, "isTomorrow");
|
|
2340
|
+
var isYesterdayRegistry = createOverridable(isYesterday, "isYesterday");
|
|
2341
|
+
var isSameDayRegistry = createOverridable(isSameDay, "isSameDay");
|
|
2342
|
+
var isSameWeekRegistry = createOverridable(isSameWeek, "isSameWeek");
|
|
2343
|
+
var isSameMonthRegistry = createOverridable(isSameMonth, "isSameMonth");
|
|
2344
|
+
var isSameQuarterRegistry = createOverridable(isSameQuarter, "isSameQuarter");
|
|
2345
|
+
var isSameYearRegistry = createOverridable(isSameYear, "isSameYear");
|
|
2346
|
+
var isWeekdayRegistry = createOverridable(isWeekday, "isWeekday");
|
|
2347
|
+
var floorRegistry = createOverridable(floor, "floor");
|
|
2348
|
+
var ceilRegistry = createOverridable(ceil, "ceil");
|
|
2349
|
+
var truncateRegistry = createOverridable(truncate, "truncate");
|
|
2350
|
+
var parseRFC3339Registry = createOverridable(parseRFC3339, "parseRFC3339");
|
|
2351
|
+
var formatRFC3339Registry = createOverridable(formatRFC3339, "formatRFC3339");
|
|
2352
|
+
var parseRFC2822Registry = createOverridable(parseRFC2822, "parseRFC2822");
|
|
2353
|
+
var parseHTTPDateRegistry = createOverridable(parseHTTPDate, "parseHTTPDate");
|
|
2354
|
+
var fromUnixMicrosecondsRegistry = createOverridable(fromUnixMicroseconds, "fromUnixMicroseconds");
|
|
2355
|
+
var fromUnixNanosecondsRegistry = createOverridable(fromUnixNanoseconds, "fromUnixNanoseconds");
|
|
2356
|
+
var toUnixSecondsRegistry = createOverridable(toUnixSeconds, "toUnixSeconds");
|
|
2357
|
+
var toUnixMillisecondsRegistry = createOverridable(toUnixMilliseconds, "toUnixMilliseconds");
|
|
2358
|
+
var toUnixMicrosecondsRegistry = createOverridable(toUnixMicroseconds, "toUnixMicroseconds");
|
|
2359
|
+
var toUnixNanosecondsRegistry = createOverridable(toUnixNanoseconds, "toUnixNanoseconds");
|
|
2360
|
+
var parseSQLRegistry = createOverridable(parseSQL, "parseSQL");
|
|
2361
|
+
var formatSQLRegistry = createOverridable(formatSQL, "formatSQL");
|
|
2362
|
+
var formatDurationToPartsRegistry = createOverridable(formatDurationToParts, "formatDurationToParts");
|
|
2363
|
+
var parseDurationRegistry = createOverridable(parseDuration, "parseDuration");
|
|
2364
|
+
var parseISODurationRegistry = createOverridable(parseISODuration, "parseISODuration");
|
|
2365
|
+
var formatISODurationRegistry = createOverridable(formatISODuration, "formatISODuration");
|
|
2366
|
+
var balanceDurationRegistry = createOverridable(balanceDuration, "balanceDuration");
|
|
2367
|
+
var compareDurationRegistry = createOverridable(compareDuration, "compareDuration");
|
|
2368
|
+
var subtractDurationRegistry = createOverridable(subtractDuration, "subtractDuration");
|
|
2369
|
+
var getLocaleRegistry = createOverridable(getLocale, "getLocale");
|
|
2370
|
+
var hasLocaleRegistry = createOverridable(hasLocale, "hasLocale");
|
|
2371
|
+
var createConfigRegistry = createOverridable(createConfig, "createConfig");
|
|
2372
|
+
var mergeWithConfigRegistry = createOverridable(mergeWithConfig, "mergeWithConfig");
|
|
2373
|
+
var listRegisteredGrammarsRegistry = createOverridable(listRegisteredGrammars, "listRegisteredGrammars");
|
|
2374
|
+
var intervalRegistry = createOverridable(interval, "interval");
|
|
2375
|
+
var overlapsRegistry = createOverridable(overlaps, "overlaps");
|
|
2376
|
+
var intersectionRegistry = createOverridable(intersection, "intersection");
|
|
2377
|
+
var unionRegistry = createOverridable(union, "union");
|
|
2378
|
+
var mergeIntervalsRegistry = createOverridable(mergeIntervals, "mergeIntervals");
|
|
2379
|
+
var formatRangeToPartsRegistry = createOverridable(formatRangeToParts, "formatRangeToParts");
|
|
2380
|
+
var betweenRegistry = createOverridable(between, "between");
|
|
2381
|
+
var parseRRuleRegistry = createOverridable(parseRRule, "parseRRule");
|
|
2382
|
+
var formatRRuleRegistry = createOverridable(formatRRule, "formatRRule");
|
|
2383
|
+
var createBusinessCalendarRegistry = createOverridable(createBusinessCalendar, "createBusinessCalendar");
|
|
2384
|
+
var subtractBusinessDaysRegistry = createOverridable(subtractBusinessDays, "subtractBusinessDays");
|
|
2385
|
+
var nextHolidayRegistry = createOverridable(nextHoliday, "nextHoliday");
|
|
2386
|
+
var previousHolidayRegistry = createOverridable(previousHoliday, "previousHoliday");
|
|
2387
|
+
var resolveZonedRegistry = createOverridable(resolveZoned, "resolveZoned");
|
|
2388
|
+
var getNextTransitionRegistry = createOverridable(getNextTransition, "getNextTransition");
|
|
2389
|
+
var getPreviousTransitionRegistry = createOverridable(getPreviousTransition, "getPreviousTransition");
|
|
2390
|
+
var possibleInstantsForRegistry = createOverridable(possibleInstantsFor, "possibleInstantsFor");
|
|
2391
|
+
var getAutocompleteDataRegistry = createOverridable(getAutocompleteData, "getAutocompleteData");
|
|
2392
|
+
var getHoverDocsRegistry = createOverridable(getHoverDocs, "getHoverDocs");
|
|
2393
|
+
var getInlineDiagnosticsRegistry = createOverridable(getInlineDiagnostics, "getInlineDiagnostics");
|
|
2394
|
+
var previewFormatRegistry = createOverridable(previewFormat, "previewFormat");
|
|
2395
|
+
var getDocUrlRegistry = createOverridable(getDocUrl, "getDocUrl");
|
|
2396
|
+
var translateDateFnsFormatStringRegistry = createOverridable(translateDateFnsFormatString, "translateDateFnsFormatString");
|
|
2397
|
+
var getCompileFormatImpl = compileFormatRegistry.get;
|
|
2398
|
+
var setCompileFormatOverride = compileFormatRegistry.set;
|
|
2399
|
+
var getCompileParserImpl = compileParserRegistry.get;
|
|
2400
|
+
var setCompileParserOverride = compileParserRegistry.set;
|
|
2401
|
+
var getParseRelativeImpl = parseRelativeRegistry.get;
|
|
2402
|
+
var setParseRelativeOverride = parseRelativeRegistry.set;
|
|
2403
|
+
var getExplainFormatImpl = explainFormatRegistry.get;
|
|
2404
|
+
var setExplainFormatOverride = explainFormatRegistry.set;
|
|
2405
|
+
var getTokenizeFormatImpl = tokenizeFormatRegistry.get;
|
|
2406
|
+
var setTokenizeFormatOverride = tokenizeFormatRegistry.set;
|
|
2407
|
+
var getListTokensImpl = listTokensRegistry.get;
|
|
2408
|
+
var setListTokensOverride = listTokensRegistry.set;
|
|
2409
|
+
var getTokenInfoImpl = tokenInfoRegistry.get;
|
|
2410
|
+
var setTokenInfoOverride = tokenInfoRegistry.set;
|
|
2411
|
+
var getIsValidFormatImpl = isValidFormatRegistry.get;
|
|
2412
|
+
var setIsValidFormatOverride = isValidFormatRegistry.set;
|
|
2413
|
+
var getValidateFormatImpl = validateFormatRegistry.get;
|
|
2414
|
+
var setValidateFormatOverride = validateFormatRegistry.set;
|
|
2415
|
+
var getFieldForTokenImpl = fieldForTokenRegistry.get;
|
|
2416
|
+
var setFieldForTokenOverride = fieldForTokenRegistry.set;
|
|
2417
|
+
var getMonthsInYearImpl = monthsInYearRegistry.get;
|
|
2418
|
+
var setMonthsInYearOverride = monthsInYearRegistry.set;
|
|
2419
|
+
var getIsLeapYearImpl = isLeapYearRegistry.get;
|
|
2420
|
+
var setIsLeapYearOverride = isLeapYearRegistry.set;
|
|
2421
|
+
var getIsLeapMonthImpl = isLeapMonthRegistry.get;
|
|
2422
|
+
var setIsLeapMonthOverride = isLeapMonthRegistry.set;
|
|
2423
|
+
var getWeekOfYearImpl = weekOfYearRegistry.get;
|
|
2424
|
+
var setWeekOfYearOverride = weekOfYearRegistry.set;
|
|
2425
|
+
var getWeekYearImpl = weekYearRegistry.get;
|
|
2426
|
+
var setWeekYearOverride = weekYearRegistry.set;
|
|
2427
|
+
var getGetMonthImpl = getMonthRegistry.get;
|
|
2428
|
+
var setGetMonthOverride = getMonthRegistry.set;
|
|
2429
|
+
var getGetWeekdayImpl = getWeekdayRegistry.get;
|
|
2430
|
+
var setGetWeekdayOverride = getWeekdayRegistry.set;
|
|
2431
|
+
var getIsEqualImpl = isEqualRegistry.get;
|
|
2432
|
+
var setIsEqualOverride = isEqualRegistry.set;
|
|
2433
|
+
var getIsBeforeImpl = isBeforeRegistry.get;
|
|
2434
|
+
var setIsBeforeOverride = isBeforeRegistry.set;
|
|
2435
|
+
var getIsAfterImpl = isAfterRegistry.get;
|
|
2436
|
+
var setIsAfterOverride = isAfterRegistry.set;
|
|
2437
|
+
var getClampImpl = clampRegistry.get;
|
|
2438
|
+
var setClampOverride = clampRegistry.set;
|
|
2439
|
+
var getIsBetweenImpl = isBetweenRegistry.get;
|
|
2440
|
+
var setIsBetweenOverride = isBetweenRegistry.set;
|
|
2441
|
+
var getIsTodayImpl = isTodayRegistry.get;
|
|
2442
|
+
var setIsTodayOverride = isTodayRegistry.set;
|
|
2443
|
+
var getIsTomorrowImpl = isTomorrowRegistry.get;
|
|
2444
|
+
var setIsTomorrowOverride = isTomorrowRegistry.set;
|
|
2445
|
+
var getIsYesterdayImpl = isYesterdayRegistry.get;
|
|
2446
|
+
var setIsYesterdayOverride = isYesterdayRegistry.set;
|
|
2447
|
+
var getIsSameDayImpl = isSameDayRegistry.get;
|
|
2448
|
+
var setIsSameDayOverride = isSameDayRegistry.set;
|
|
2449
|
+
var getIsSameWeekImpl = isSameWeekRegistry.get;
|
|
2450
|
+
var setIsSameWeekOverride = isSameWeekRegistry.set;
|
|
2451
|
+
var getIsSameMonthImpl = isSameMonthRegistry.get;
|
|
2452
|
+
var setIsSameMonthOverride = isSameMonthRegistry.set;
|
|
2453
|
+
var getIsSameQuarterImpl = isSameQuarterRegistry.get;
|
|
2454
|
+
var setIsSameQuarterOverride = isSameQuarterRegistry.set;
|
|
2455
|
+
var getIsSameYearImpl = isSameYearRegistry.get;
|
|
2456
|
+
var setIsSameYearOverride = isSameYearRegistry.set;
|
|
2457
|
+
var getIsWeekdayImpl = isWeekdayRegistry.get;
|
|
2458
|
+
var setIsWeekdayOverride = isWeekdayRegistry.set;
|
|
2459
|
+
var getFloorImpl = floorRegistry.get;
|
|
2460
|
+
var setFloorOverride = floorRegistry.set;
|
|
2461
|
+
var getCeilImpl = ceilRegistry.get;
|
|
2462
|
+
var setCeilOverride = ceilRegistry.set;
|
|
2463
|
+
var getTruncateImpl = truncateRegistry.get;
|
|
2464
|
+
var setTruncateOverride = truncateRegistry.set;
|
|
2465
|
+
var getParseRFC3339Impl = parseRFC3339Registry.get;
|
|
2466
|
+
var setParseRFC3339Override = parseRFC3339Registry.set;
|
|
2467
|
+
var getFormatRFC3339Impl = formatRFC3339Registry.get;
|
|
2468
|
+
var setFormatRFC3339Override = formatRFC3339Registry.set;
|
|
2469
|
+
var getParseRFC2822Impl = parseRFC2822Registry.get;
|
|
2470
|
+
var setParseRFC2822Override = parseRFC2822Registry.set;
|
|
2471
|
+
var getParseHTTPDateImpl = parseHTTPDateRegistry.get;
|
|
2472
|
+
var setParseHTTPDateOverride = parseHTTPDateRegistry.set;
|
|
2473
|
+
var getFromUnixMicrosecondsImpl = fromUnixMicrosecondsRegistry.get;
|
|
2474
|
+
var setFromUnixMicrosecondsOverride = fromUnixMicrosecondsRegistry.set;
|
|
2475
|
+
var getFromUnixNanosecondsImpl = fromUnixNanosecondsRegistry.get;
|
|
2476
|
+
var setFromUnixNanosecondsOverride = fromUnixNanosecondsRegistry.set;
|
|
2477
|
+
var getToUnixSecondsImpl = toUnixSecondsRegistry.get;
|
|
2478
|
+
var setToUnixSecondsOverride = toUnixSecondsRegistry.set;
|
|
2479
|
+
var getToUnixMillisecondsImpl = toUnixMillisecondsRegistry.get;
|
|
2480
|
+
var setToUnixMillisecondsOverride = toUnixMillisecondsRegistry.set;
|
|
2481
|
+
var getToUnixMicrosecondsImpl = toUnixMicrosecondsRegistry.get;
|
|
2482
|
+
var setToUnixMicrosecondsOverride = toUnixMicrosecondsRegistry.set;
|
|
2483
|
+
var getToUnixNanosecondsImpl = toUnixNanosecondsRegistry.get;
|
|
2484
|
+
var setToUnixNanosecondsOverride = toUnixNanosecondsRegistry.set;
|
|
2485
|
+
var getParseSQLImpl = parseSQLRegistry.get;
|
|
2486
|
+
var setParseSQLOverride = parseSQLRegistry.set;
|
|
2487
|
+
var getFormatSQLImpl = formatSQLRegistry.get;
|
|
2488
|
+
var setFormatSQLOverride = formatSQLRegistry.set;
|
|
2489
|
+
var getFormatDurationToPartsImpl = formatDurationToPartsRegistry.get;
|
|
2490
|
+
var setFormatDurationToPartsOverride = formatDurationToPartsRegistry.set;
|
|
2491
|
+
var getParseDurationImpl = parseDurationRegistry.get;
|
|
2492
|
+
var setParseDurationOverride = parseDurationRegistry.set;
|
|
2493
|
+
var getParseISODurationImpl = parseISODurationRegistry.get;
|
|
2494
|
+
var setParseISODurationOverride = parseISODurationRegistry.set;
|
|
2495
|
+
var getFormatISODurationImpl = formatISODurationRegistry.get;
|
|
2496
|
+
var setFormatISODurationOverride = formatISODurationRegistry.set;
|
|
2497
|
+
var getBalanceDurationImpl = balanceDurationRegistry.get;
|
|
2498
|
+
var setBalanceDurationOverride = balanceDurationRegistry.set;
|
|
2499
|
+
var getCompareDurationImpl = compareDurationRegistry.get;
|
|
2500
|
+
var setCompareDurationOverride = compareDurationRegistry.set;
|
|
2501
|
+
var getSubtractDurationImpl = subtractDurationRegistry.get;
|
|
2502
|
+
var setSubtractDurationOverride = subtractDurationRegistry.set;
|
|
2503
|
+
var getGetLocaleImpl = getLocaleRegistry.get;
|
|
2504
|
+
var setGetLocaleOverride = getLocaleRegistry.set;
|
|
2505
|
+
var getHasLocaleImpl = hasLocaleRegistry.get;
|
|
2506
|
+
var setHasLocaleOverride = hasLocaleRegistry.set;
|
|
2507
|
+
var getCreateConfigImpl = createConfigRegistry.get;
|
|
2508
|
+
var setCreateConfigOverride = createConfigRegistry.set;
|
|
2509
|
+
var getMergeWithConfigImpl = mergeWithConfigRegistry.get;
|
|
2510
|
+
var setMergeWithConfigOverride = mergeWithConfigRegistry.set;
|
|
2511
|
+
var getListRegisteredGrammarsImpl = listRegisteredGrammarsRegistry.get;
|
|
2512
|
+
var setListRegisteredGrammarsOverride = listRegisteredGrammarsRegistry.set;
|
|
2513
|
+
var getIntervalImpl = intervalRegistry.get;
|
|
2514
|
+
var setIntervalOverride = intervalRegistry.set;
|
|
2515
|
+
var getOverlapsImpl = overlapsRegistry.get;
|
|
2516
|
+
var setOverlapsOverride = overlapsRegistry.set;
|
|
2517
|
+
var getIntersectionImpl = intersectionRegistry.get;
|
|
2518
|
+
var setIntersectionOverride = intersectionRegistry.set;
|
|
2519
|
+
var getUnionImpl = unionRegistry.get;
|
|
2520
|
+
var setUnionOverride = unionRegistry.set;
|
|
2521
|
+
var getMergeIntervalsImpl = mergeIntervalsRegistry.get;
|
|
2522
|
+
var setMergeIntervalsOverride = mergeIntervalsRegistry.set;
|
|
2523
|
+
var getFormatRangeToPartsImpl = formatRangeToPartsRegistry.get;
|
|
2524
|
+
var setFormatRangeToPartsOverride = formatRangeToPartsRegistry.set;
|
|
2525
|
+
var getBetweenImpl = betweenRegistry.get;
|
|
2526
|
+
var setBetweenOverride = betweenRegistry.set;
|
|
2527
|
+
var getParseRRuleImpl = parseRRuleRegistry.get;
|
|
2528
|
+
var setParseRRuleOverride = parseRRuleRegistry.set;
|
|
2529
|
+
var getFormatRRuleImpl = formatRRuleRegistry.get;
|
|
2530
|
+
var setFormatRRuleOverride = formatRRuleRegistry.set;
|
|
2531
|
+
var getCreateBusinessCalendarImpl = createBusinessCalendarRegistry.get;
|
|
2532
|
+
var setCreateBusinessCalendarOverride = createBusinessCalendarRegistry.set;
|
|
2533
|
+
var getSubtractBusinessDaysImpl = subtractBusinessDaysRegistry.get;
|
|
2534
|
+
var setSubtractBusinessDaysOverride = subtractBusinessDaysRegistry.set;
|
|
2535
|
+
var getNextHolidayImpl = nextHolidayRegistry.get;
|
|
2536
|
+
var setNextHolidayOverride = nextHolidayRegistry.set;
|
|
2537
|
+
var getPreviousHolidayImpl = previousHolidayRegistry.get;
|
|
2538
|
+
var setPreviousHolidayOverride = previousHolidayRegistry.set;
|
|
2539
|
+
var getResolveZonedImpl = resolveZonedRegistry.get;
|
|
2540
|
+
var setResolveZonedOverride = resolveZonedRegistry.set;
|
|
2541
|
+
var getGetNextTransitionImpl = getNextTransitionRegistry.get;
|
|
2542
|
+
var setGetNextTransitionOverride = getNextTransitionRegistry.set;
|
|
2543
|
+
var getGetPreviousTransitionImpl = getPreviousTransitionRegistry.get;
|
|
2544
|
+
var setGetPreviousTransitionOverride = getPreviousTransitionRegistry.set;
|
|
2545
|
+
var getPossibleInstantsForImpl = possibleInstantsForRegistry.get;
|
|
2546
|
+
var setPossibleInstantsForOverride = possibleInstantsForRegistry.set;
|
|
2547
|
+
var getGetAutocompleteDataImpl = getAutocompleteDataRegistry.get;
|
|
2548
|
+
var setGetAutocompleteDataOverride = getAutocompleteDataRegistry.set;
|
|
2549
|
+
var getGetHoverDocsImpl = getHoverDocsRegistry.get;
|
|
2550
|
+
var setGetHoverDocsOverride = getHoverDocsRegistry.set;
|
|
2551
|
+
var getGetInlineDiagnosticsImpl = getInlineDiagnosticsRegistry.get;
|
|
2552
|
+
var setGetInlineDiagnosticsOverride = getInlineDiagnosticsRegistry.set;
|
|
2553
|
+
var getPreviewFormatImpl = previewFormatRegistry.get;
|
|
2554
|
+
var setPreviewFormatOverride = previewFormatRegistry.set;
|
|
2555
|
+
var getGetDocUrlImpl = getDocUrlRegistry.get;
|
|
2556
|
+
var setGetDocUrlOverride = getDocUrlRegistry.set;
|
|
2557
|
+
var getTranslateDateFnsFormatStringImpl = translateDateFnsFormatStringRegistry.get;
|
|
2558
|
+
var setTranslateDateFnsFormatStringOverride = translateDateFnsFormatStringRegistry.set;
|
|
2559
|
+
|
|
2560
|
+
// src/interval.ts
|
|
2561
|
+
function interval(start, end, bounds = "closed") {
|
|
2562
|
+
const cmp = compare(start, end);
|
|
2563
|
+
if (cmp > 0) {
|
|
2564
|
+
throw new Error(
|
|
2565
|
+
`temporal-fmt: interval start must be \u2264 end (got start > end). Pass them in chronological order.`
|
|
2566
|
+
);
|
|
2567
|
+
}
|
|
2568
|
+
return { start, end, bounds };
|
|
2569
|
+
}
|
|
2570
|
+
function contains(iv, value) {
|
|
2571
|
+
const startCmp = compare(value, iv.start);
|
|
2572
|
+
const endCmp = compare(value, iv.end);
|
|
2573
|
+
const afterStart = iv.bounds === "open" || iv.bounds === "half-open-end" ? startCmp > 0 : startCmp >= 0;
|
|
2574
|
+
const beforeEnd = iv.bounds === "open" || iv.bounds === "half-open-start" ? endCmp < 0 : endCmp <= 0;
|
|
2575
|
+
return afterStart && beforeEnd;
|
|
2576
|
+
}
|
|
2577
|
+
function overlaps(a, b) {
|
|
2578
|
+
return intersects(a, b);
|
|
2579
|
+
}
|
|
2580
|
+
function intersects(a, b) {
|
|
2581
|
+
if (compare(a.end, b.start) < 0) return false;
|
|
2582
|
+
if (compare(a.start, b.end) > 0) return false;
|
|
2583
|
+
return true;
|
|
2584
|
+
}
|
|
2585
|
+
function isBefore2(a, b) {
|
|
2586
|
+
return compare(a.end, b.start) < 0;
|
|
2587
|
+
}
|
|
2588
|
+
function isAfter2(a, b) {
|
|
2589
|
+
return compare(a.start, b.end) > 0;
|
|
2590
|
+
}
|
|
2591
|
+
function intersection(a, b) {
|
|
2592
|
+
if (!intersects(a, b)) return null;
|
|
2593
|
+
const start = compare(a.start, b.start) >= 0 ? a.start : b.start;
|
|
2594
|
+
const end = compare(a.end, b.end) <= 0 ? a.end : b.end;
|
|
2595
|
+
const startBoundsOpen = a.bounds === "open" || a.bounds === "half-open-end" || (b.bounds === "open" || b.bounds === "half-open-end");
|
|
2596
|
+
const endBoundsOpen = a.bounds === "open" || a.bounds === "half-open-start" || (b.bounds === "open" || b.bounds === "half-open-start");
|
|
2597
|
+
const bounds = startBoundsOpen && endBoundsOpen ? "open" : startBoundsOpen ? "half-open-end" : endBoundsOpen ? "half-open-start" : "closed";
|
|
2598
|
+
return { start, end, bounds };
|
|
2599
|
+
}
|
|
2600
|
+
function union(a, b) {
|
|
2601
|
+
if (!intersects(a, b)) return null;
|
|
2602
|
+
const start = compare(a.start, b.start) <= 0 ? a.start : b.start;
|
|
2603
|
+
const end = compare(a.end, b.end) >= 0 ? a.end : b.end;
|
|
2604
|
+
const startBoundsOpen = (a.bounds === "open" || a.bounds === "half-open-end") && (b.bounds === "open" || b.bounds === "half-open-end");
|
|
2605
|
+
const endBoundsOpen = (a.bounds === "open" || a.bounds === "half-open-start") && (b.bounds === "open" || b.bounds === "half-open-start");
|
|
2606
|
+
const bounds = startBoundsOpen && endBoundsOpen ? "open" : startBoundsOpen ? "half-open-end" : endBoundsOpen ? "half-open-start" : "closed";
|
|
2607
|
+
return { start, end, bounds };
|
|
2608
|
+
}
|
|
2609
|
+
function difference(a, b) {
|
|
2610
|
+
if (!intersects(a, b)) return [a];
|
|
2611
|
+
const result = [];
|
|
2612
|
+
const aStartIncluded = a.bounds === "closed" || a.bounds === "half-open-end";
|
|
2613
|
+
const aEndIncluded = a.bounds === "closed" || a.bounds === "half-open-start";
|
|
2614
|
+
if (compare(a.start, b.start) < 0) {
|
|
2615
|
+
result.push({ start: a.start, end: b.start, bounds: aStartIncluded ? "half-open-end" : "open" });
|
|
2616
|
+
}
|
|
2617
|
+
if (compare(a.end, b.end) > 0) {
|
|
2618
|
+
result.push({ start: b.end, end: a.end, bounds: aEndIncluded ? "half-open-start" : "open" });
|
|
2619
|
+
}
|
|
2620
|
+
return result;
|
|
2621
|
+
}
|
|
2622
|
+
var subtract = difference;
|
|
2623
|
+
function mergeIntervals(intervals) {
|
|
2624
|
+
if (intervals.length === 0) return [];
|
|
2625
|
+
const sorted = [...intervals].sort((a, b) => compare(a.start, b.start));
|
|
2626
|
+
const result = [{ ...sorted[0] }];
|
|
2627
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
2628
|
+
const current = sorted[i];
|
|
2629
|
+
const last = result[result.length - 1];
|
|
2630
|
+
if (intersects(last, current) || compare(last.end, current.start) === 0) {
|
|
2631
|
+
if (compare(current.end, last.end) > 0) {
|
|
2632
|
+
last.end = current.end;
|
|
2633
|
+
}
|
|
2634
|
+
} else {
|
|
2635
|
+
result.push(current);
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
return result;
|
|
2639
|
+
}
|
|
2640
|
+
var MAX_DATE_MS = 864e13;
|
|
2641
|
+
function splitInterval(iv, n) {
|
|
2642
|
+
if (n <= 0) throw new Error(`temporal-fmt: splitInterval requires n > 0 (got ${n}).`);
|
|
2643
|
+
if (n === 1) return [iv];
|
|
2644
|
+
const startFields = asDateFieldView(iv.start);
|
|
2645
|
+
const endFields = asDateFieldView(iv.end);
|
|
2646
|
+
const startMs = toMs(startFields);
|
|
2647
|
+
const endMs = toMs(endFields);
|
|
2648
|
+
if (Math.abs(startMs) > MAX_DATE_MS || Math.abs(endMs) > MAX_DATE_MS) {
|
|
2649
|
+
throw new RangeError(
|
|
2650
|
+
`temporal-fmt: splitInterval() endpoints are outside the representable Date range (approximately \xB1275,760 years). Split the interval into smaller ranges first.`
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
const step = (endMs - startMs) / n;
|
|
2654
|
+
const result = [];
|
|
2655
|
+
for (let i = 0; i < n; i++) {
|
|
2656
|
+
const sliceStart = startMs + i * step;
|
|
2657
|
+
const sliceEnd = i === n - 1 ? endMs : sliceStart + step;
|
|
2658
|
+
result.push({
|
|
2659
|
+
start: fromMs(sliceStart, startFields),
|
|
2660
|
+
end: fromMs(sliceEnd, endFields),
|
|
2661
|
+
bounds: i === 0 ? iv.bounds : "half-open-start"
|
|
2662
|
+
});
|
|
2663
|
+
}
|
|
2664
|
+
return result;
|
|
2665
|
+
}
|
|
2666
|
+
function toMs(v) {
|
|
2667
|
+
const y = v.year, m = v.month, d = v.day;
|
|
2668
|
+
const y2 = m <= 2 ? y - 1 : y;
|
|
2669
|
+
const era = Math.floor((y2 >= 0 ? y2 : y2 - 399) / 400);
|
|
2670
|
+
const yoe = y2 - era * 400;
|
|
2671
|
+
const m2 = m > 2 ? m - 3 : m + 9;
|
|
2672
|
+
const doy = Math.floor((153 * m2 + 2) / 5) + d - 1;
|
|
2673
|
+
const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy;
|
|
2674
|
+
const days = era * 146097 + doe - 719468;
|
|
2675
|
+
return days * 864e5 + (v.hour ?? 0) * 36e5 + (v.minute ?? 0) * 6e4 + (v.second ?? 0) * 1e3 + (v.millisecond ?? 0);
|
|
2676
|
+
}
|
|
2677
|
+
function fromMs(ms, base) {
|
|
2678
|
+
const MS_PER_DAY = 864e5;
|
|
2679
|
+
const dayOverflow = Math.floor(ms / MS_PER_DAY);
|
|
2680
|
+
let withinDay = ms % MS_PER_DAY;
|
|
2681
|
+
if (withinDay < 0) withinDay += MS_PER_DAY;
|
|
2682
|
+
const hour = Math.floor(withinDay / 36e5);
|
|
2683
|
+
const minute = Math.floor(withinDay % 36e5 / 6e4);
|
|
2684
|
+
const second = Math.floor(withinDay % 6e4 / 1e3);
|
|
2685
|
+
const millisecond = withinDay % 1e3;
|
|
2686
|
+
const newMs = dayOverflow * MS_PER_DAY;
|
|
2687
|
+
const d = new Date(newMs);
|
|
2688
|
+
return {
|
|
2689
|
+
...base,
|
|
2690
|
+
year: d.getUTCFullYear(),
|
|
2691
|
+
month: d.getUTCMonth() + 1,
|
|
2692
|
+
day: d.getUTCDate(),
|
|
2693
|
+
hour,
|
|
2694
|
+
minute,
|
|
2695
|
+
second,
|
|
2696
|
+
millisecond
|
|
2697
|
+
};
|
|
2698
|
+
}
|
|
2699
|
+
function formatRange(iv, formatStr, options = {}) {
|
|
2700
|
+
try {
|
|
2701
|
+
const format2 = getFormatImpl();
|
|
2702
|
+
const startStr = format2(iv.start, formatStr, options);
|
|
2703
|
+
const endStr = format2(iv.end, formatStr, options);
|
|
2704
|
+
return `${startStr} \u2013 ${endStr}`;
|
|
2705
|
+
} catch (err) {
|
|
2706
|
+
try {
|
|
2707
|
+
const fmt = new Intl.DateTimeFormat(normalizeLocaleTag(options.locale ?? "en-US"), {});
|
|
2708
|
+
const startDate = toJSDate(iv.start);
|
|
2709
|
+
const endDate = toJSDate(iv.end);
|
|
2710
|
+
return fmt.formatRange(startDate, endDate);
|
|
2711
|
+
} catch {
|
|
2712
|
+
throw err;
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2716
|
+
function formatRangeToParts(iv, formatStr, options = {}) {
|
|
2717
|
+
const startParts = formatToParts(iv.start, formatStr, options);
|
|
2718
|
+
const endParts = formatToParts(iv.end, formatStr, options);
|
|
2719
|
+
const result = [...startParts];
|
|
2720
|
+
result.push({ type: "literal", value: " \u2013 " });
|
|
2721
|
+
result.push(...endParts);
|
|
2722
|
+
return result;
|
|
2723
|
+
}
|
|
2724
|
+
function toJSDate(value) {
|
|
2725
|
+
const v = value;
|
|
2726
|
+
if (typeof v?.toInstant === "function") {
|
|
2727
|
+
return new Date(v.toInstant().epochMilliseconds);
|
|
2728
|
+
}
|
|
2729
|
+
if (typeof v?.year === "number" && typeof v?.month === "number" && typeof v?.day === "number") {
|
|
2730
|
+
return new Date(Date.UTC(v.year, v.month - 1, v.day, v.hour ?? 0, v.minute ?? 0, v.second ?? 0, v.millisecond ?? 0));
|
|
2731
|
+
}
|
|
2732
|
+
throw new Error(`temporal-fmt: formatRange() expected Temporal values with year/month/day, got ${typeof value}.`);
|
|
2733
|
+
}
|
|
2734
|
+
|
|
2735
|
+
export {
|
|
2736
|
+
registerRelativeGrammar,
|
|
2737
|
+
TOKEN_METADATA,
|
|
2738
|
+
ALL_TOKEN_NAMES,
|
|
2739
|
+
analyzeFormat,
|
|
2740
|
+
parseISO,
|
|
2741
|
+
formatISO,
|
|
2742
|
+
formatRFC2822,
|
|
2743
|
+
formatHTTPDate,
|
|
2744
|
+
fromUnixSeconds,
|
|
2745
|
+
fromUnixMilliseconds,
|
|
2746
|
+
DEFAULT_CONFIG,
|
|
2747
|
+
interval,
|
|
2748
|
+
contains,
|
|
2749
|
+
overlaps,
|
|
2750
|
+
intersects,
|
|
2751
|
+
isBefore2 as isBefore,
|
|
2752
|
+
isAfter2 as isAfter,
|
|
2753
|
+
intersection,
|
|
2754
|
+
union,
|
|
2755
|
+
difference,
|
|
2756
|
+
subtract,
|
|
2757
|
+
mergeIntervals,
|
|
2758
|
+
splitInterval,
|
|
2759
|
+
formatRange,
|
|
2760
|
+
formatRangeToParts,
|
|
2761
|
+
isBusinessDay,
|
|
2762
|
+
nextBusinessDay,
|
|
2763
|
+
previousBusinessDay,
|
|
2764
|
+
addBusinessDays,
|
|
2765
|
+
differenceInBusinessDays,
|
|
2766
|
+
createHolidayCalendar,
|
|
2767
|
+
holidaysBetween,
|
|
2768
|
+
DAYJS_TO_TEMPORAL_FMT,
|
|
2769
|
+
DATE_FNS_TO_TEMPORAL_FMT,
|
|
2770
|
+
translateDayjsFormatString,
|
|
2771
|
+
getFormatImpl,
|
|
2772
|
+
getParseImpl,
|
|
2773
|
+
OverrideConflictError,
|
|
2774
|
+
setFormatOverride,
|
|
2775
|
+
setParseOverride,
|
|
2776
|
+
getCompileFormatImpl,
|
|
2777
|
+
setCompileFormatOverride,
|
|
2778
|
+
getCompileParserImpl,
|
|
2779
|
+
setCompileParserOverride,
|
|
2780
|
+
getParseRelativeImpl,
|
|
2781
|
+
setParseRelativeOverride,
|
|
2782
|
+
getExplainFormatImpl,
|
|
2783
|
+
setExplainFormatOverride,
|
|
2784
|
+
getTokenizeFormatImpl,
|
|
2785
|
+
setTokenizeFormatOverride,
|
|
2786
|
+
getListTokensImpl,
|
|
2787
|
+
setListTokensOverride,
|
|
2788
|
+
getTokenInfoImpl,
|
|
2789
|
+
setTokenInfoOverride,
|
|
2790
|
+
getIsValidFormatImpl,
|
|
2791
|
+
setIsValidFormatOverride,
|
|
2792
|
+
getValidateFormatImpl,
|
|
2793
|
+
setValidateFormatOverride,
|
|
2794
|
+
getFieldForTokenImpl,
|
|
2795
|
+
setFieldForTokenOverride,
|
|
2796
|
+
getMonthsInYearImpl,
|
|
2797
|
+
setMonthsInYearOverride,
|
|
2798
|
+
getIsLeapYearImpl,
|
|
2799
|
+
setIsLeapYearOverride,
|
|
2800
|
+
getIsLeapMonthImpl,
|
|
2801
|
+
setIsLeapMonthOverride,
|
|
2802
|
+
getWeekOfYearImpl,
|
|
2803
|
+
setWeekOfYearOverride,
|
|
2804
|
+
getWeekYearImpl,
|
|
2805
|
+
setWeekYearOverride,
|
|
2806
|
+
getGetMonthImpl,
|
|
2807
|
+
setGetMonthOverride,
|
|
2808
|
+
getGetWeekdayImpl,
|
|
2809
|
+
setGetWeekdayOverride,
|
|
2810
|
+
getIsEqualImpl,
|
|
2811
|
+
setIsEqualOverride,
|
|
2812
|
+
getIsBeforeImpl,
|
|
2813
|
+
setIsBeforeOverride,
|
|
2814
|
+
getIsAfterImpl,
|
|
2815
|
+
setIsAfterOverride,
|
|
2816
|
+
getClampImpl,
|
|
2817
|
+
setClampOverride,
|
|
2818
|
+
getIsBetweenImpl,
|
|
2819
|
+
setIsBetweenOverride,
|
|
2820
|
+
getIsTodayImpl,
|
|
2821
|
+
setIsTodayOverride,
|
|
2822
|
+
getIsTomorrowImpl,
|
|
2823
|
+
setIsTomorrowOverride,
|
|
2824
|
+
getIsYesterdayImpl,
|
|
2825
|
+
setIsYesterdayOverride,
|
|
2826
|
+
getIsSameDayImpl,
|
|
2827
|
+
setIsSameDayOverride,
|
|
2828
|
+
getIsSameWeekImpl,
|
|
2829
|
+
setIsSameWeekOverride,
|
|
2830
|
+
getIsSameMonthImpl,
|
|
2831
|
+
setIsSameMonthOverride,
|
|
2832
|
+
getIsSameQuarterImpl,
|
|
2833
|
+
setIsSameQuarterOverride,
|
|
2834
|
+
getIsSameYearImpl,
|
|
2835
|
+
setIsSameYearOverride,
|
|
2836
|
+
getIsWeekdayImpl,
|
|
2837
|
+
setIsWeekdayOverride,
|
|
2838
|
+
getFloorImpl,
|
|
2839
|
+
setFloorOverride,
|
|
2840
|
+
getCeilImpl,
|
|
2841
|
+
setCeilOverride,
|
|
2842
|
+
getTruncateImpl,
|
|
2843
|
+
setTruncateOverride,
|
|
2844
|
+
getParseRFC3339Impl,
|
|
2845
|
+
setParseRFC3339Override,
|
|
2846
|
+
getFormatRFC3339Impl,
|
|
2847
|
+
setFormatRFC3339Override,
|
|
2848
|
+
getParseRFC2822Impl,
|
|
2849
|
+
setParseRFC2822Override,
|
|
2850
|
+
getParseHTTPDateImpl,
|
|
2851
|
+
setParseHTTPDateOverride,
|
|
2852
|
+
getFromUnixMicrosecondsImpl,
|
|
2853
|
+
setFromUnixMicrosecondsOverride,
|
|
2854
|
+
getFromUnixNanosecondsImpl,
|
|
2855
|
+
setFromUnixNanosecondsOverride,
|
|
2856
|
+
getToUnixSecondsImpl,
|
|
2857
|
+
setToUnixSecondsOverride,
|
|
2858
|
+
getToUnixMillisecondsImpl,
|
|
2859
|
+
setToUnixMillisecondsOverride,
|
|
2860
|
+
getToUnixMicrosecondsImpl,
|
|
2861
|
+
setToUnixMicrosecondsOverride,
|
|
2862
|
+
getToUnixNanosecondsImpl,
|
|
2863
|
+
setToUnixNanosecondsOverride,
|
|
2864
|
+
getParseSQLImpl,
|
|
2865
|
+
setParseSQLOverride,
|
|
2866
|
+
getFormatSQLImpl,
|
|
2867
|
+
setFormatSQLOverride,
|
|
2868
|
+
getFormatDurationToPartsImpl,
|
|
2869
|
+
setFormatDurationToPartsOverride,
|
|
2870
|
+
getParseDurationImpl,
|
|
2871
|
+
setParseDurationOverride,
|
|
2872
|
+
getParseISODurationImpl,
|
|
2873
|
+
setParseISODurationOverride,
|
|
2874
|
+
getFormatISODurationImpl,
|
|
2875
|
+
setFormatISODurationOverride,
|
|
2876
|
+
getBalanceDurationImpl,
|
|
2877
|
+
setBalanceDurationOverride,
|
|
2878
|
+
getCompareDurationImpl,
|
|
2879
|
+
setCompareDurationOverride,
|
|
2880
|
+
getSubtractDurationImpl,
|
|
2881
|
+
setSubtractDurationOverride,
|
|
2882
|
+
getGetLocaleImpl,
|
|
2883
|
+
setGetLocaleOverride,
|
|
2884
|
+
getHasLocaleImpl,
|
|
2885
|
+
setHasLocaleOverride,
|
|
2886
|
+
getCreateConfigImpl,
|
|
2887
|
+
setCreateConfigOverride,
|
|
2888
|
+
getMergeWithConfigImpl,
|
|
2889
|
+
setMergeWithConfigOverride,
|
|
2890
|
+
getListRegisteredGrammarsImpl,
|
|
2891
|
+
setListRegisteredGrammarsOverride,
|
|
2892
|
+
getIntervalImpl,
|
|
2893
|
+
setIntervalOverride,
|
|
2894
|
+
getOverlapsImpl,
|
|
2895
|
+
setOverlapsOverride,
|
|
2896
|
+
getIntersectionImpl,
|
|
2897
|
+
setIntersectionOverride,
|
|
2898
|
+
getUnionImpl,
|
|
2899
|
+
setUnionOverride,
|
|
2900
|
+
getMergeIntervalsImpl,
|
|
2901
|
+
setMergeIntervalsOverride,
|
|
2902
|
+
getFormatRangeToPartsImpl,
|
|
2903
|
+
setFormatRangeToPartsOverride,
|
|
2904
|
+
getBetweenImpl,
|
|
2905
|
+
setBetweenOverride,
|
|
2906
|
+
getParseRRuleImpl,
|
|
2907
|
+
setParseRRuleOverride,
|
|
2908
|
+
getFormatRRuleImpl,
|
|
2909
|
+
setFormatRRuleOverride,
|
|
2910
|
+
getCreateBusinessCalendarImpl,
|
|
2911
|
+
setCreateBusinessCalendarOverride,
|
|
2912
|
+
getSubtractBusinessDaysImpl,
|
|
2913
|
+
setSubtractBusinessDaysOverride,
|
|
2914
|
+
getNextHolidayImpl,
|
|
2915
|
+
setNextHolidayOverride,
|
|
2916
|
+
getPreviousHolidayImpl,
|
|
2917
|
+
setPreviousHolidayOverride,
|
|
2918
|
+
getResolveZonedImpl,
|
|
2919
|
+
setResolveZonedOverride,
|
|
2920
|
+
getGetNextTransitionImpl,
|
|
2921
|
+
setGetNextTransitionOverride,
|
|
2922
|
+
getGetPreviousTransitionImpl,
|
|
2923
|
+
setGetPreviousTransitionOverride,
|
|
2924
|
+
getPossibleInstantsForImpl,
|
|
2925
|
+
setPossibleInstantsForOverride,
|
|
2926
|
+
getGetAutocompleteDataImpl,
|
|
2927
|
+
setGetAutocompleteDataOverride,
|
|
2928
|
+
getGetHoverDocsImpl,
|
|
2929
|
+
setGetHoverDocsOverride,
|
|
2930
|
+
getGetInlineDiagnosticsImpl,
|
|
2931
|
+
setGetInlineDiagnosticsOverride,
|
|
2932
|
+
getPreviewFormatImpl,
|
|
2933
|
+
setPreviewFormatOverride,
|
|
2934
|
+
getGetDocUrlImpl,
|
|
2935
|
+
setGetDocUrlOverride,
|
|
2936
|
+
getTranslateDateFnsFormatStringImpl,
|
|
2937
|
+
setTranslateDateFnsFormatStringOverride
|
|
2938
|
+
};
|
|
2939
|
+
//# sourceMappingURL=chunk-FBPHNRVW.js.map
|