temporal-fmt 0.8.2 → 0.8.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/LICENSE +1 -0
- package/README.md +168 -1
- package/dist/formatDistance.d.cts +33 -0
- package/dist/formatDistance.d.ts +33 -0
- package/dist/formatDuration.d.cts +27 -0
- package/dist/formatDuration.d.ts +27 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isoWeek.d.cts +7 -0
- package/dist/isoWeek.d.ts +7 -0
- package/dist/localeVocab.d.cts +27 -0
- package/dist/localeVocab.d.ts +27 -0
- package/dist/parseRelative.d.cts +25 -0
- package/dist/parseRelative.d.ts +25 -0
- package/dist/temporalProvider.d.cts +1 -0
- package/dist/temporalProvider.d.ts +1 -0
- package/dist/tokens.d.cts +7 -0
- package/dist/tokens.d.ts +7 -0
- package/package.json +8 -5
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -113,6 +113,11 @@ A few things worth knowing:
|
|
|
113
113
|
- this is an opinionated tradeoff but ensures `yy` is deterministic without an external date reference
|
|
114
114
|
- **`hh`/`h` (12-hour) without an `a` token throws** — same if a format string mixes `HH`/`H` with `hh`/`h`,
|
|
115
115
|
even when both agree on the same hour. `parse` won't guess which one is authoritative; pick one.
|
|
116
|
+
- **`HH`/`H` combined with `a` is allowed, and cross-checked** — `parse('HH:mm a', '13:05 PM')` succeeds since
|
|
117
|
+
13:05 can only mean PM, but `parse('HH:mm a', '01:05 PM')` throws: the day period contradicts the hour.
|
|
118
|
+
This is different from mixing `HH` with `hh`/`h` above — there's only one hour token here, `a` just confirms it.
|
|
119
|
+
- **`a` (AM/PM) matches case-insensitively** — `pm`, `Pm`, and `PM` all parse the same way. Month and weekday
|
|
120
|
+
names (`MMMM`, `EEEE`, etc.) stay case-sensitive; only the day-period marker is case-folded.
|
|
116
121
|
- **`MMMM`/`MMM` name matching assumes a 12-month calendar** — the vocabulary
|
|
117
122
|
it matches against is generated from 12 Gregorian reference dates, so a
|
|
118
123
|
calendar with a leap month (e.g. Hebrew's 13-month leap years) isn't fully
|
|
@@ -167,6 +172,7 @@ yourself.
|
|
|
167
172
|
| M | month | 8 |
|
|
168
173
|
| dd | 2-digit day | 04 |
|
|
169
174
|
| d | day | 4 |
|
|
175
|
+
| do | ordinal day (English-only: 1st, 2nd, 3rd, 4th, ... 11th/12th/13th, ... 21st) | 4th |
|
|
170
176
|
| EEEE | full weekday | Tuesday |
|
|
171
177
|
| EEE | short weekday | Tue |
|
|
172
178
|
| HH | 2-digit hour (24h) | 15 |
|
|
@@ -178,13 +184,162 @@ yourself.
|
|
|
178
184
|
| ss | 2-digit second | 30 |
|
|
179
185
|
| s | second | 30 |
|
|
180
186
|
| SSS | milliseconds | 000 |
|
|
181
|
-
| a | AM/PM
|
|
187
|
+
| a | AM/PM (case-insensitive on parse) | PM |
|
|
188
|
+
| Q | numeric quarter (1-4) | 3 |
|
|
189
|
+
| QQQ | quarter with "Q" prefix (Q1, Q2, Q3, Q4) | Q3 |
|
|
190
|
+
| ww | ISO 8601 week (01-53), format-only | 32 |
|
|
191
|
+
| RRRR | ISO 8601 week-numbering year, format-only | 2026 |
|
|
182
192
|
| zzz | IANA time zone id | America/New_York |
|
|
183
193
|
|
|
194
|
+
`do` is format-only (parse() rejects it — the "st"/"nd"/"rd"/"th" suffix isn't structurally distinguishable from adjacent literal text in a parse context). The English-only suffix rule is on purpose — locale-aware ordinals are out of scope; `Intl.DateTimeFormat` has no part type for ordinals, and the rest of this library routes locale-specific names through it.
|
|
195
|
+
|
|
196
|
+
`Q` and `QQQ` both format and parse. On parse, they cross-check against any month/date tokens present in the same format string, the same way `EEEE` cross-checks weekday against date — throw if they disagree.
|
|
197
|
+
|
|
198
|
+
`ww` and `RRRR` are format-only. Parsing "ww"/"RRRR" back into a date requires resolving an ISO week + a weekday to a specific date, which is a different parsing surface than the token-based `parse()` here.
|
|
199
|
+
|
|
200
|
+
`RRRR` is the **ISO week-numbering year**, not the calendar year — they can differ at year boundaries. Dec 29-31 often belong to week 1 of the *next* year; Jan 1-3 often belong to week 52/53 of the *previous* year. Examples: `format(PlainDate.from('2026-12-31'), 'ww RRRR')` → `"53 2026"`; `format(PlainDate.from('2027-01-01'), 'ww RRRR')` → `"53 2026"` (Friday in ISO year 2026's week 53); `format(PlainDate.from('2027-01-04'), 'ww RRRR')` → `"01 2027"` (Monday starting ISO week 1 of 2027).
|
|
201
|
+
|
|
184
202
|
Try to use a token your input type doesn't support — `HH` on a `PlainDate`,
|
|
185
203
|
say — and you'll get a real error telling you so, not a silent `undefined`
|
|
186
204
|
sitting in your output waiting to confuse someone in three weeks.
|
|
187
205
|
|
|
206
|
+
## Duration formatting
|
|
207
|
+
|
|
208
|
+
`formatDuration(duration, formatStr, options?)` formats a `Temporal.Duration` (or a plain field bag `{ years, months, weeks, days, hours, minutes, seconds, milliseconds }`) with a duration-specific token set. A duration doesn't sit on a calendar — it has no year/month/day position the way a PlainDate does — so the date/time token table above doesn't apply.
|
|
209
|
+
|
|
210
|
+
Token grammar: each unit has three forms, in increasing verbosity.
|
|
211
|
+
|
|
212
|
+
| Token | Form | Example |
|
|
213
|
+
|-------|------|---------|
|
|
214
|
+
| `y` / `yy` / `yyy` | numeric / short / long (years) | `2` / `2yr` / `2 years` |
|
|
215
|
+
| `o` / `oo` / `ooo` | numeric / short / long (months) | `2` / `2mo` / `2 months` |
|
|
216
|
+
| `w` / `ww` / `www` | weeks | `2` / `2wk` / `2 weeks` |
|
|
217
|
+
| `d` / `dd` / `ddd` | days | `2` / `2d` / `2 days` |
|
|
218
|
+
| `h` / `hh` / `hhh` | hours | `2` / `2h` / `2 hours` |
|
|
219
|
+
| `m` / `mm` / `mmm` | minutes | `2` / `2m` / `2 minutes` |
|
|
220
|
+
| `s` / `ss` / `sss` | seconds | `2` / `2s` / `2 seconds` |
|
|
221
|
+
| `S` / `SS` / `SSS` | milliseconds | `2` / `2ms` / `2 milliseconds` |
|
|
222
|
+
|
|
223
|
+
The short and long forms are plural-aware (singular for value 1, plural otherwise).
|
|
224
|
+
|
|
225
|
+
```js
|
|
226
|
+
import { formatDuration } from 'temporal-fmt';
|
|
227
|
+
|
|
228
|
+
formatDuration({ years: 2, months: 3 }, 'yyy ooo') // "2 years 3 months"
|
|
229
|
+
formatDuration({ hours: 2, minutes: 30 }, 'hhh mmm') // "2 hours 30 minutes"
|
|
230
|
+
formatDuration({ hours: 2, minutes: 30 }, 'h:mm') // "2:30"
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Zero-value handling**: by default, zero-value units are omitted from the output. `formatDuration({ hours: 2 }, 'hhh mmm')` returns `"2 hours "` (the trailing space is the literal separator from the format string — the codemod doesn't do separator cleanup; the caller is responsible for structuring the format string). Pass `{ showZeroValues: true }` to force zero-value units to render.
|
|
234
|
+
|
|
235
|
+
Unit names are hardcoded English in this pass. `Intl.DurationFormat` exists in some engines but is still maturing; for now, English-only is explicit. Callers wanting locale-aware duration formatting should use `Intl.DurationFormat` directly.
|
|
236
|
+
|
|
237
|
+
## Relative time: formatDistance
|
|
238
|
+
|
|
239
|
+
`formatDistance(date1, date2, options?)` returns a human-readable relative-time string — "3 days ago", "in 2 hours", "now". Delegates unit names and pluralization to `Intl.RelativeTimeFormat` so the output localizes the same way the rest of the library's locale-aware tokens do.
|
|
240
|
+
|
|
241
|
+
```js
|
|
242
|
+
import { formatDistance } from 'temporal-fmt';
|
|
243
|
+
|
|
244
|
+
const today = Temporal.PlainDate.from('2026-08-04');
|
|
245
|
+
const yesterday = Temporal.PlainDate.from('2026-08-03');
|
|
246
|
+
|
|
247
|
+
formatDistance(today, yesterday) // "yesterday" (numeric: 'auto')
|
|
248
|
+
formatDistance(today, yesterday, { numeric: 'always' }) // "1 day ago"
|
|
249
|
+
formatDistance(today, today) // "now"
|
|
250
|
+
formatDistance(today, today.add({ days: 2 }), { locale: 'fr-FR' }) // "dans 2 jours"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Direction convention**: `diff = date1 - date2`. Positive diff → date1 is in the future relative to date2 → "in X". Negative diff → date1 is in the past → "X ago". Swap the args to flip the direction.
|
|
254
|
+
|
|
255
|
+
**Unit-selection cutoffs** (documented, not configurable):
|
|
256
|
+
|
|
257
|
+
| abs(diff) | Unit |
|
|
258
|
+
|-----------|------|
|
|
259
|
+
| < 60 seconds | seconds |
|
|
260
|
+
| < 60 minutes | minutes |
|
|
261
|
+
| < 24 hours | hours |
|
|
262
|
+
| < 30 days | days |
|
|
263
|
+
| < 365 days | months |
|
|
264
|
+
| otherwise | years |
|
|
265
|
+
|
|
266
|
+
30 days is an approximation of a month (calendar months are 28-31 days); 365 days is an approximation of a year. These are the same cutoffs date-fns uses, trimmed to the units `Intl.RelativeTimeFormat` supports across engines.
|
|
267
|
+
|
|
268
|
+
Accepts `Temporal.PlainDate`, `PlainDateTime`, or `ZonedDateTime`. A `PlainDate` is treated as midnight when diffing against a `PlainDateTime`. Throws on `PlainTime` (no anchor date to diff against) and on partial-date shapes (e.g. `{ year: 2026 }` with no month/day).
|
|
269
|
+
|
|
270
|
+
## Lenient parse mode
|
|
271
|
+
|
|
272
|
+
By default, `parse()` throws when an ambiguous glued numeric run (e.g. `"121"` against `yyyy-Md`) has more than one valid split. The library refuses to guess — silently picking one would mean returning a value indistinguishable from a different, equally-valid value the same input could describe.
|
|
273
|
+
|
|
274
|
+
Pass `{ lenient: true }` to opt into a documented heuristic that picks one split instead of throwing:
|
|
275
|
+
|
|
276
|
+
```js
|
|
277
|
+
parse('yyyy-Md', '2026-121') // throws — ambiguous
|
|
278
|
+
parse('yyyy-Md', '2026-121', { lenient: true }).toString() // '2026-12-01'
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Heuristic**: when one of the tokens in the ambiguous run is `d` (day), prefer the split where the day value is ≤ 12. Rationale: when a person writes a glued run like `"121"` for an `Md` format string, they're more likely to mean "Dec 1" (M=12, d=1) than "Jan 21" (M=1, d=21) — if they meant Jan 21, they'd more often have written it as `"1/21"` or `"01/21"` with a separator or padding. This isn't a guarantee (which is exactly why lenient mode is opt-in), but it's a reasonable default when the caller has explicitly asked us to guess.
|
|
282
|
+
|
|
283
|
+
When the heuristic doesn't narrow (e.g. both splits have day ≤ 12), falls back to the first valid split from `enumerateValidSplits()` — deterministic but necessarily arbitrary. When no `d` token is in the run (e.g. `Hm`), the heuristic doesn't apply; falls back to first split.
|
|
284
|
+
|
|
285
|
+
The default behavior (lenient unset or `false`) is unchanged — this is strictly additive.
|
|
286
|
+
|
|
287
|
+
## Custom locale vocabularies
|
|
288
|
+
|
|
289
|
+
`registerLocaleVocab(locale, vocab)` lets callers supply their own month/weekday/day-period vocabulary for a locale key `Intl` doesn't cover well. The known limitation this addresses: a 13-month Hebrew leap year silently loses a month because `Intl`'s 12-month vocabulary can't name it.
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
import { registerLocaleVocab, format, parse } from 'temporal-fmt';
|
|
293
|
+
|
|
294
|
+
registerLocaleVocab('en-u-ca-hebrew-leap', {
|
|
295
|
+
monthLong: ['Nisan','Iyar','Sivan','Tammuz','Av','Elul','Tishrei','Marcheshvan','Kislev','Tevet','Shevat','Adar I','Adar II'],
|
|
296
|
+
monthShort: ['Nis','Iyy','Siv','Tam','Av','Elu','Tish','Chesh','Kis','Tev','Shv','Ad1','Ad2'],
|
|
297
|
+
weekdayLong: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
|
|
298
|
+
weekdayShort: ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'],
|
|
299
|
+
dayPeriod: ['AM','PM'],
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
const date = Temporal.PlainDate.from('2026-08-04').withCalendar('hebrew');
|
|
303
|
+
format(date, 'MMMM d, yyyy', { locale: 'en-u-ca-hebrew-leap' }) // "Av 4, 5786" (or similar)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Validation is strict: throws descriptively on wrong array lengths (must be 12 months, 7 weekdays, 2 day periods), empty strings, duplicate entries, and identical AM/PM day periods (which would make `parse()` unable to tell AM from PM). All errors surface at registration time, not later during format/parse.
|
|
307
|
+
|
|
308
|
+
Registered vocab takes precedence over the `Intl`-derived vocab for that locale key, for both `format()` and `parse()`.
|
|
309
|
+
|
|
310
|
+
## parseRelative: natural-language date parsing
|
|
311
|
+
|
|
312
|
+
`parseRelative(input, referenceDate, options?)` resolves common English relative-date phrases against a reference date, returning a `Temporal.PlainDate`. English only this pass — the matching patterns are hand-written regular expressions keyed on English month/weekday names.
|
|
313
|
+
|
|
314
|
+
Supported phrases:
|
|
315
|
+
|
|
316
|
+
- **weekday references**: "next Tuesday", "last Friday", "this Monday"
|
|
317
|
+
- **relative day offsets**: "today", "tomorrow", "yesterday"
|
|
318
|
+
- **relative unit offsets**: "in 3 days", "2 weeks ago", "in 1 month", "1 year ago"
|
|
319
|
+
- **month-day without year**: "March 5th", "Aug 4" (resolved to next occurrence)
|
|
320
|
+
|
|
321
|
+
```js
|
|
322
|
+
import { parseRelative } from 'temporal-fmt';
|
|
323
|
+
|
|
324
|
+
const today = Temporal.PlainDate.from('2026-08-04'); // Tuesday
|
|
325
|
+
parseRelative('today', today).toString() // '2026-08-04'
|
|
326
|
+
parseRelative('tomorrow', today).toString() // '2026-08-05'
|
|
327
|
+
parseRelative('next Tuesday', today).toString() // '2026-08-11' (7 days out, not today)
|
|
328
|
+
parseRelative('last Friday', today).toString() // '2026-07-31'
|
|
329
|
+
parseRelative('in 3 days', today).toString() // '2026-08-07'
|
|
330
|
+
parseRelative('2 weeks ago', today).toString() // '2026-07-21'
|
|
331
|
+
parseRelative('March 5th', today).toString() // '2027-03-05' (next occurrence)
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Ambiguous-case choices** (documented, not inferred):
|
|
335
|
+
|
|
336
|
+
- **"next Tuesday" said on a Tuesday** = 7 days out, not today. "this Tuesday" handles the same-week case, so "next Tuesday" staying strictly-future gives the two phrases distinct, non-overlapping meanings.
|
|
337
|
+
- **"last Tuesday" said on a Tuesday** = 7 days ago (strictly-past, symmetric to "next").
|
|
338
|
+
- **"March 5th" without a year** = next occurrence. Future-leaning: today's date returns today; a past date this year returns next year's occurrence. (The alternative — "nearest in time, past or future" — would mean "March 5th" said on March 6 returns yesterday, which is counterintuitive for the typical "next birthday"/"next deadline" use case.)
|
|
339
|
+
- **"5 days" without "in" or "ago"** = throws. Past or future? parseRelative refuses to guess — same contract as `parse()`'s strict mode.
|
|
340
|
+
|
|
341
|
+
Throws a descriptive error for any phrase it doesn't recognize, naming the supported categories in the message. Accepts `PlainDate`, `PlainDateTime`, or `ZonedDateTime` as the reference (needs `dayOfWeek` to compute weekday offsets). Throws on `PlainTime`.
|
|
342
|
+
|
|
188
343
|
## Known limitations
|
|
189
344
|
|
|
190
345
|
- Numeral systems are always Western digits — see [Locale support](#locale-support).
|
|
@@ -249,6 +404,18 @@ type tests (`test:types`), so it's the only single command that actually
|
|
|
249
404
|
covers everything. CI runs `test:all` for this reason; running plain `npm
|
|
250
405
|
test` locally will pass even with a broken `vitest/` suite.
|
|
251
406
|
|
|
407
|
+
## Related tools
|
|
408
|
+
|
|
409
|
+
ojgewijgipejgiejwjpgiejig
|
|
410
|
+
|
|
411
|
+
Flipped the hell out, yanked the wrong build by mistake, republished it clean, and now npm's anti-malware lockout thinks I'm a supply chain attacker for the next 24 hours — yes, I'm unpatient crap too, so clone it and build it yourself, it's not some multi-hour C++ compile, just a quick build. This library's unaffected btw, bcz I actually didn't screw this one up hahaha, ha, ha ....... sorry nobody laughed.
|
|
412
|
+
|
|
413
|
+
(will pull this line once it's back up)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
- [`eslint-plugin-temporal-fmt`](https://github.com/DirazCoder/eslint-plugin-temporal-fmt) — lints format strings for common mistakes (e.g. `hh` without `a`)
|
|
417
|
+
- [`temporal-fmt-codemod`](https://github.com/DirazCoder/temporal-fmt-codemod) — one-time migration tool that rewrites dayjs/date-fns calls to temporal-fmt
|
|
418
|
+
|
|
252
419
|
## License
|
|
253
420
|
|
|
254
421
|
MIT
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type FormatOptions } from './tokens.cjs';
|
|
2
|
+
export interface FormatDistanceOptions extends FormatOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 'auto' (default) lets Intl.RelativeTimeFormat use natural forms like
|
|
5
|
+
* "yesterday"/"tomorrow"/"now" when the rounded value lands on ±1 or 0.
|
|
6
|
+
* 'always' forces the strict "1 day ago"/"in 1 day"/"in 0 seconds" form.
|
|
7
|
+
*/
|
|
8
|
+
numeric?: 'always' | 'auto';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Returns a human-readable relative-time string describing `date1`
|
|
12
|
+
* relative to `date2`, e.g. "3 days ago", "in 2 hours", "now". Delegates
|
|
13
|
+
* unit names and pluralization to `Intl.RelativeTimeFormat` so the
|
|
14
|
+
* output localizes the same way the rest of the library's locale-aware
|
|
15
|
+
* tokens do.
|
|
16
|
+
*
|
|
17
|
+
* Convention: the result describes `date1`'s position relative to
|
|
18
|
+
* `date2`. `formatDistance(now, threeDaysAgo)` → `"3 days ago"` (the
|
|
19
|
+
* past date is described relative to now). `formatDistance(now, twoHoursFromNow)`
|
|
20
|
+
* → `"in 2 hours"`. This matches the natural-language reading "describe
|
|
21
|
+
* the first date as if standing at the second one."
|
|
22
|
+
*
|
|
23
|
+
* Unit-selection cutoffs (seconds → minutes → hours → days → months →
|
|
24
|
+
* years) and the rationale for each are documented in the README under
|
|
25
|
+
* "formatDistance".
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* formatDistance(threeDaysAgo, today) // "3 days ago"
|
|
29
|
+
* formatDistance(twoHoursFromNow, today) // "in 2 hours"
|
|
30
|
+
* formatDistance(today, today) // "now"
|
|
31
|
+
* formatDistance(futureDate, today, {locale:'fr-FR'}) // "dans 2 jours"
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatDistance(date1: unknown, date2: unknown, options?: FormatDistanceOptions): string;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type FormatOptions } from './tokens.js';
|
|
2
|
+
export interface FormatDistanceOptions extends FormatOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 'auto' (default) lets Intl.RelativeTimeFormat use natural forms like
|
|
5
|
+
* "yesterday"/"tomorrow"/"now" when the rounded value lands on ±1 or 0.
|
|
6
|
+
* 'always' forces the strict "1 day ago"/"in 1 day"/"in 0 seconds" form.
|
|
7
|
+
*/
|
|
8
|
+
numeric?: 'always' | 'auto';
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Returns a human-readable relative-time string describing `date1`
|
|
12
|
+
* relative to `date2`, e.g. "3 days ago", "in 2 hours", "now". Delegates
|
|
13
|
+
* unit names and pluralization to `Intl.RelativeTimeFormat` so the
|
|
14
|
+
* output localizes the same way the rest of the library's locale-aware
|
|
15
|
+
* tokens do.
|
|
16
|
+
*
|
|
17
|
+
* Convention: the result describes `date1`'s position relative to
|
|
18
|
+
* `date2`. `formatDistance(now, threeDaysAgo)` → `"3 days ago"` (the
|
|
19
|
+
* past date is described relative to now). `formatDistance(now, twoHoursFromNow)`
|
|
20
|
+
* → `"in 2 hours"`. This matches the natural-language reading "describe
|
|
21
|
+
* the first date as if standing at the second one."
|
|
22
|
+
*
|
|
23
|
+
* Unit-selection cutoffs (seconds → minutes → hours → days → months →
|
|
24
|
+
* years) and the rationale for each are documented in the README under
|
|
25
|
+
* "formatDistance".
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* formatDistance(threeDaysAgo, today) // "3 days ago"
|
|
29
|
+
* formatDistance(twoHoursFromNow, today) // "in 2 hours"
|
|
30
|
+
* formatDistance(today, today) // "now"
|
|
31
|
+
* formatDistance(futureDate, today, {locale:'fr-FR'}) // "dans 2 jours"
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatDistance(date1: unknown, date2: unknown, options?: FormatDistanceOptions): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type FormatOptions } from './tokens.cjs';
|
|
2
|
+
export interface DurationFormatOptions extends FormatOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When true, units whose value is zero are still emitted in the output
|
|
5
|
+
* (e.g. "0 hours, 30 minutes" instead of "30 minutes"). Default is
|
|
6
|
+
* false: zero-value units are omitted, matching how date-fns's
|
|
7
|
+
* formatDuration works and how most callers rendering a duration to
|
|
8
|
+
* a human would want it.
|
|
9
|
+
*/
|
|
10
|
+
showZeroValues?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Format a Temporal.Duration (or a plain field bag { years, months, ...
|
|
14
|
+
* }) using a duration-specific token string. Token grammar is documented
|
|
15
|
+
* in the README under "Duration formatting" — it does NOT reuse the
|
|
16
|
+
* date/time token table, since a duration has no calendar position.
|
|
17
|
+
*
|
|
18
|
+
* Zero-value units are omitted by default; pass { showZeroValues: true }
|
|
19
|
+
* to force them to appear.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* formatDuration(Temporal.Duration.from({ years: 2, months: 1 }), 'yyy ooo')
|
|
23
|
+
* // "2 years 1 month"
|
|
24
|
+
* formatDuration({ hours: 2, minutes: 30 }, 'hhh mmm')
|
|
25
|
+
* // "2 hours 30 minutes"
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatDuration(duration: Record<string, unknown>, formatStr: string, options?: DurationFormatOptions): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type FormatOptions } from './tokens.js';
|
|
2
|
+
export interface DurationFormatOptions extends FormatOptions {
|
|
3
|
+
/**
|
|
4
|
+
* When true, units whose value is zero are still emitted in the output
|
|
5
|
+
* (e.g. "0 hours, 30 minutes" instead of "30 minutes"). Default is
|
|
6
|
+
* false: zero-value units are omitted, matching how date-fns's
|
|
7
|
+
* formatDuration works and how most callers rendering a duration to
|
|
8
|
+
* a human would want it.
|
|
9
|
+
*/
|
|
10
|
+
showZeroValues?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Format a Temporal.Duration (or a plain field bag { years, months, ...
|
|
14
|
+
* }) using a duration-specific token string. Token grammar is documented
|
|
15
|
+
* in the README under "Duration formatting" — it does NOT reuse the
|
|
16
|
+
* date/time token table, since a duration has no calendar position.
|
|
17
|
+
*
|
|
18
|
+
* Zero-value units are omitted by default; pass { showZeroValues: true }
|
|
19
|
+
* to force them to appear.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* formatDuration(Temporal.Duration.from({ years: 2, months: 1 }), 'yyy ooo')
|
|
23
|
+
* // "2 years 1 month"
|
|
24
|
+
* formatDuration({ hours: 2, minutes: 30 }, 'hhh mmm')
|
|
25
|
+
* // "2 hours 30 minutes"
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatDuration(duration: Record<string, unknown>, formatStr: string, options?: DurationFormatOptions): string;
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var j=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var ue=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var le=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})},pe=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ue(t))!ce.call(e,r)&&r!==n&&j(e,r,{get:()=>t[r],enumerable:!(o=de(t,r))||o.enumerable});return e};var ge=e=>pe(j({},"__esModule",{value:!0}),e);var Ue={};le(Ue,{format:()=>ee,parse:()=>ie,setTemporal:()=>B});module.exports=ge(Ue);var W,J=[];function q(e){J.push(e)}function B(e){W=e;for(let t of J)t()}function fe(){return W??globalThis.Temporal}function A(){let e=fe();if(!e)throw new Error("temporal-fmt: parse() needs a Temporal implementation to construct its result. Call setTemporal(Temporal) once at startup, or assign one to globalThis.Temporal (native on Node 26+, or a polyfill like temporal-polyfill).");return e}function F(e){try{return new Intl.Locale(e.replace(/_/g,"-")).toString().toLowerCase()}catch{return e}}var P=new Map,he=500;function v(e,t,n){let o=e.formatToParts(t),r=o.findIndex(p=>p.type===n);if(r===-1)throw new Error(`temporal-fmt: locale produced no "${n}" part while building match vocabulary.`);let a=o[r].value,i=o[r-1],s=o[r+1];return i?.type==="literal"&&!/\s/.test(i.value)&&(a=i.value+a),s?.type==="literal"&&!/\s/.test(s.value)&&(a=a+s.value),a}function _(e,t,n){let o=new Map;for(let r=0;r<e.length;r++){let a=o.get(e[r]);if(a!==void 0)throw new Error(`temporal-fmt: locale "${n}" renders ${t} index ${a} and ${r} identically ("${e[r]}"). parse() can't reliably tell these apart for this locale/token, so this combination isn't supported.`);o.set(e[r],r)}}function M(e){let t=F(e),n=P.get(t);if(n)return n;let o=new Intl.DateTimeFormat(e,{month:"long",timeZone:"UTC"}),r=new Intl.DateTimeFormat(e,{month:"short",timeZone:"UTC"}),a=[],i=[];for(let u=0;u<12;u++){let k=new Date(Date.UTC(2020,u,1));a.push(v(o,k,"month")),i.push(v(r,k,"month"))}_(a,"MMMM month",e),_(i,"MMM month",e);let s=new Intl.DateTimeFormat(e,{weekday:"long",timeZone:"UTC"}),p=new Intl.DateTimeFormat(e,{weekday:"short",timeZone:"UTC"}),c=[],m=[];for(let u=0;u<7;u++){let k=new Date(Date.UTC(2024,0,1+u));c.push(v(s,k,"weekday")),m.push(v(p,k,"weekday"))}_(c,"EEEE weekday",e),_(m,"EEE weekday",e);let d=new Intl.DateTimeFormat(e,{hour:"numeric",hour12:!0,timeZone:"UTC"}),f=v(d,new Date(Date.UTC(2020,0,1,1)),"dayPeriod"),w=v(d,new Date(Date.UTC(2020,0,1,13)),"dayPeriod"),h=[...new Set([f,w])],g={monthLong:a,monthShort:i,weekdayLong:c,weekdayShort:m,dayPeriod:h};if(P.size>=he){let u=P.keys().next().value;u!==void 0&&P.delete(u)}return P.set(t,g),g}function T(e,t){let n=e<0,o=String(Math.abs(e)).padStart(t,"0");return n?"-"+o:o}var Z="en-US",N=new Map,ye=500;function Q(e,t){let n=JSON.stringify([F(e),t]),o=N.get(n);if(o)return o;if(N.size>=ye){let r=N.keys().next().value;r!==void 0&&N.delete(r)}return o=new Intl.DateTimeFormat(e,t),N.set(n,o),o}var S;q(()=>{S=void 0});function we(){if(S===void 0){S=!1;try{let e=A();new Intl.DateTimeFormat("en-US",{day:"numeric"}).formatToParts(e.PlainDate.from({year:1970,month:1,day:1})),S=!0}catch{}}return S}function R(e,t,n,o){let r=e?.calendarId,a={...n,calendar:r&&r!=="iso8601"?r:"gregory"};if(!we())return e.toLocaleString(t,a);let{toInstant:i,timeZoneId:s}=e,p=typeof i=="function"&&typeof s=="string",c=p?e.toInstant():e,m={...a,...p?{timeZone:s}:{}},f=Q(t,m).formatToParts(c),w=f.findIndex(k=>k.type===o);if(w===-1)throw new Error(`temporal-fmt: locale "${t}" produced no "${o}" part for this token. This usually means the Temporal object is missing the field the token needs.`);let h=f[w].value,g=f[w-1],u=f[w+1];return g?.type==="literal"&&!/\s/.test(g.value)&&(h=g.value+h),u?.type==="literal"&&!/\s/.test(u.value)&&(h=h+u.value),h}function ke(e,t){let n=new Date(Date.UTC(1970,0,1,e)),r=Q(t,{hour:"numeric",hour12:!0,timeZone:"UTC"}).formatToParts(n).find(a=>a.type==="dayPeriod");if(!r)throw new Error(`temporal-fmt: locale "${t}" produced no "dayPeriod" part for token "a".`);return r.value}var H=[["yyyy",e=>T(e.year,4),"year"],["yy",e=>{if(e.year<0)throw new Error(`temporal-fmt: token "yy" doesn't support negative years (got ${e.year}), since truncating to 2 digits would make it indistinguishable from a positive year. Use "yyyy" instead.`);return T(e.year%100,2)},"year"],["MMMM",(e,t)=>R(e,t,{month:"long"},"month"),"month"],["MMM",(e,t)=>R(e,t,{month:"short"},"month"),"month"],["MM",e=>T(e.month,2),"month"],["M",e=>String(e.month),"month"],["dd",e=>T(e.day,2),"day"],["d",e=>String(e.day),"day"],["EEEE",(e,t)=>R(e,t,{weekday:"long"},"weekday"),"dayOfWeek"],["EEE",(e,t)=>R(e,t,{weekday:"short"},"weekday"),"dayOfWeek"],["HH",e=>T(e.hour,2),"hour"],["H",e=>String(e.hour),"hour"],["hh",e=>T(e.hour%12||12,2),"hour"],["h",e=>String(e.hour%12||12),"hour"],["mm",e=>T(e.minute,2),"minute"],["m",e=>String(e.minute),"minute"],["ss",e=>T(e.second,2),"second"],["s",e=>String(e.second),"second"],["SSS",e=>T(e.millisecond,3),"millisecond"],["a",(e,t)=>ke(e.hour,t),"hour"],["zzz",e=>e.timeZoneId,"timeZoneId"]];var Te=H.map(([e])=>e).sort((e,t)=>t.length-e.length);function U(e){let t=[],n=0;for(;n<e.length;){let o=e[n];if(o==="'"){if(e[n+1]==="'"){X(t,"'"),n+=2;continue}let a=n+1,i="",s=!1;for(;a<e.length;){if(e[a]==="'"){if(e[a+1]==="'"){i+="'",a+=2;continue}s=!0,a+=1;break}i+=e[a],a+=1}if(!s)throw new Error(`temporal-fmt: unterminated quote in format string "${e}"`);X(t,i),n=a;continue}let r=Te.find(a=>e.startsWith(a,n));if(r){t.push({kind:"token",value:r}),n+=r.length;continue}X(t,o),n+=1}return t}function X(e,t){let n=e[e.length-1];n&&n.kind==="literal"?n.value+=t:e.push({kind:"literal",value:t})}var Ee=new Map(H.map(([e,t,n])=>[e,{fn:t,field:n}]));function ee(e,t,n={}){if(t.length>1e3)throw new Error(`temporal-fmt: format string exceeds maximum length of ${1e3} characters (got ${t.length}).`);let o=n.locale??Z,r=U(t),a="";for(let i of r){if(i.kind==="literal"){a+=i.value;continue}let s=Ee.get(i.value);if(!s)throw new Error(`temporal-fmt: unknown token "${i.value}"`);if(e[s.field]===void 0)throw new Error(`temporal-fmt: token "${i.value}" requires "${s.field}", which this Temporal object doesn't have. (e.g. PlainDate has no time fields, PlainTime has no date fields)`);a+=s.fn(e,o)}return a}function be(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function $(e){return`(?:${e.map(be).join("|")})`}var xe="(?:UTC|[+-]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?|[A-Za-z_]+(?:[+-]\\d{1,2})?(?:\\/[A-Za-z0-9_+-]+)*)";function ve(){return xe}var z;function Me(){return z||(z=new Set(Intl.supportedValuesOf("timeZone")),z.add("UTC")),z}var De=/^[+-]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?$/;function te(e){return De.test(e)||Me().has(e)}var Pe={yy:"\\d{2}",MM:"(?:0[1-9]|1[0-2])",M:"(?:1[0-2]|[1-9])",dd:"(?:0[1-9]|[12]\\d|3[01])",d:"(?:[12]\\d|3[01]|[1-9])",HH:"(?:[01]\\d|2[0-3])",H:"(?:1\\d|2[0-3]|[0-9])",hh:"(?:0[1-9]|1[0-2])",h:"(?:1[0-2]|[1-9])",mm:"(?:[0-5]\\d)",m:"(?:[1-5]\\d|[0-9])",ss:"(?:[0-5]\\d)",s:"(?:[1-5]\\d|[0-9])",SSS:"\\d{3}"},Fe="-?\\d{4}",Ne="-?\\d{4,}",Se=new Set(["yyyy","yy","MM","M","dd","d","HH","H","hh","h","mm","m","ss","s","SSS"]);function ne(e,t,n){if(e==="yyyy")return n!==void 0&&Se.has(n)?Fe:Ne;let o=Pe[e];if(o)return o;let r=M(t);switch(e){case"MMMM":return $(r.monthLong);case"MMM":return $(r.monthShort);case"EEEE":return $(r.weekdayLong);case"EEE":return $(r.weekdayShort);case"a":return $(r.dayPeriod);case"zzz":return ve();default:throw new Error(`temporal-fmt: unknown token "${e}"`)}}var re=new Set(["M","d","H","h","m","s"]),$e={M:[{digits:1,min:1,max:9},{digits:2,min:10,max:12}],d:[{digits:1,min:1,max:9},{digits:2,min:10,max:31}],H:[{digits:1,min:0,max:9},{digits:2,min:10,max:23}],h:[{digits:1,min:1,max:9},{digits:2,min:10,max:12}],m:[{digits:1,min:0,max:9},{digits:2,min:10,max:59}],s:[{digits:1,min:0,max:9},{digits:2,min:10,max:59}]};function oe(e,t){let n=new Map;function o(r,a){let i=`${r}:${a}`,s=n.get(i);if(s)return s;if(r===t.length){let d=a===e.length?[[]]:[];return n.set(i,d),d}let p=t[r],c=$e[p];if(!c)throw new Error(`temporal-fmt: internal error \u2014 "${p}" is not an unpadded numeric token`);let m=[];for(let{digits:d,min:f,max:w}of c){if(a+d>e.length)continue;let h=e.slice(a,a+d);if(d===2&&h[0]==="0")continue;let g=Number(h);if(!(g<f||g>w)){for(let u of o(r+1,a+d))if(m.push([g,...u]),m.length===2)break;if(m.length===2)break}}return n.set(i,m),m}return o(0,0)}function Ce(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ae(e,t){let n=[],o=[],r="",a=0,i={groupNames:[],tokens:[]},s=()=>{i.tokens.length>=2&&o.push(i),i={groupNames:[],tokens:[]}};for(let[p,c]of e.entries()){if(c.kind==="literal"){r+=Ce(c.value),s();continue}let m=`g${a++}`;n.push({name:m,token:c.value});let d=e[p+1],f=d?.kind==="token"?d.value:void 0;r+=`(?<${m}>${ne(c.value,t,f)})`,re.has(c.value)?(i.groupNames.push(m),i.tokens.push(c.value)):s()}return s(),{regex:new RegExp(`^(?:${r})$`,"u"),groups:n,ambiguousRuns:o}}var C=new Map,Le=500;function Oe(e,t){let n=JSON.stringify([F(t),e]),o=C.get(n);if(o)return o;if(C.size>=Le){let r=C.keys().next().value;r!==void 0&&C.delete(r)}return o=ae(U(e),t),C.set(n,o),o}var D=new Map,Ae=500;function _e(e){let t=new Intl.Locale(e).toString().toLowerCase();if(D.has(t))return D.get(t);if(D.size>=Ae){let i=D.keys().next().value;i!==void 0&&D.delete(i)}let n,o=t.split("-"),r=o.indexOf("u"),a=r===-1?-1:o.indexOf("ca",r+1);if(a!==-1&&a+1<o.length){let i=new Intl.DateTimeFormat(t).resolvedOptions().calendar;n=i==="gregory"?void 0:i}return D.set(t,n),n}function l(e,t,n){e[t]=n}function Re(e,t,n,o,r){let a=M(o);switch(t){case"yyyy":l(e,"year",Number(n));break;case"yy":l(e,"twoDigitYear",Number(n));break;case"MM":case"M":l(e,"month",Number(n));break;case"MMMM":l(e,"month",a.monthLong.indexOf(n)+1);break;case"MMM":l(e,"month",a.monthShort.indexOf(n)+1);break;case"dd":case"d":l(e,"day",Number(n));break;case"EEEE":l(e,"weekdayRaw",n),l(e,"weekdayExpected",a.weekdayLong.indexOf(n)+1);break;case"EEE":l(e,"weekdayRaw",n),l(e,"weekdayExpected",a.weekdayShort.indexOf(n)+1);break;case"HH":case"H":l(e,"hour",Number(n));break;case"hh":case"h":l(e,"hour12",Number(n));break;case"mm":case"m":l(e,"minute",Number(n));break;case"ss":case"s":l(e,"second",Number(n));break;case"SSS":l(e,"millisecond",Number(n));break;case"a":{let i=a.dayPeriod.indexOf(n);if(i<0)throw new Error(`temporal-fmt: unknown day period "${n}" for locale "${o}".`);l(e,"dayPeriodRaw",n),l(e,"isPM",i===1);break}case"zzz":l(e,"timeZoneId",n);break}}function Ze(e){if(e.year!==void 0&&e.twoDigitYear!==void 0)throw new Error('temporal-fmt: format string mixes "yyyy" and "yy" year representations.');if(e.year!==void 0)return e.year;if(e.twoDigitYear!==void 0)return e.twoDigitYear<=68?2e3+e.twoDigitYear:1900+e.twoDigitYear}function He(e,t,n){if(e.hour!==void 0&&e.hour12!==void 0)throw new Error(`temporal-fmt: format string "${t}" mixes a 24-hour token ("HH"/"H") with a 12-hour token ("hh"/"h").`);if(e.hour!==void 0){if(e.dayPeriodRaw!==void 0){let o=M(n),r=e.hour<12?o.dayPeriod[0]:o.dayPeriod[1];if(e.dayPeriodRaw!==r)throw new Error(`temporal-fmt: format string "${t}" contains a day period that contradicts the 24-hour value.`)}return e.hour}if(e.hour12!==void 0){if(e.isPM===void 0)throw new Error(`temporal-fmt: format string "${t}" uses a 12-hour token ("hh"/"h") without an "a" token, so parse() can't tell AM from PM.`);return e.hour12%12+(e.isPM?12:0)}}function ie(e,t,n={}){if(e.length>1e3)throw new Error(`temporal-fmt: format string exceeds maximum length of ${1e3} characters (got ${e.length}).`);if(t.length>1e5)throw new Error(`temporal-fmt: input exceeds maximum length of ${1e5} characters (got ${t.length}).`);let o=n.locale??Z,r=_e(o),a=Oe(e,o),i=a.regex.exec(t);if(!i)throw new Error("temporal-fmt: no valid pattern matches the format string and input shape");if(a.groups.length===0)throw new Error(`temporal-fmt: format string "${e}" has no tokens \u2014 nothing to parse into a value.`);for(let{name:y,token:E}of a.groups)if(E==="zzz"&&!te(i.groups[y]))throw new Error("temporal-fmt: no valid pattern matches the format string and input shape");for(let y of a.ambiguousRuns){let E=y.groupNames.map(me=>i.groups[me]).join(""),O=oe(E,y.tokens);if(O.length>1)throw new Error(`temporal-fmt: "${E}" in format string "${e}" is ambiguous \u2014 ${O.length} different ways to read tokens "${y.tokens.join("")}" (with no separator between them) are all individually valid (e.g. ${JSON.stringify(O[0])} vs ${JSON.stringify(O[1])}). parse() won't guess; add a separator between these tokens, or use their padded form (e.g. "MM" instead of "M") so each one has a fixed width.`)}let s={};for(let{name:y,token:E}of a.groups)Re(s,E,i.groups[y],o,e);let p=Ze(s),c=He(s,e,o),{month:m,day:d,minute:f,second:w,millisecond:h,timeZoneId:g,weekdayExpected:u,weekdayRaw:k}=s,se=p!==void 0||m!==void 0||d!==void 0,b=p!==void 0&&m!==void 0&&d!==void 0;if(se&&!b)throw new Error(`temporal-fmt: format string "${e}" has an incomplete date \u2014 year, month, and day tokens must all be present together.`);let K=c!==void 0||f!==void 0||w!==void 0||h!==void 0;if(g!==void 0&&!(b&&K))throw new Error(`temporal-fmt: format string "${e}" has a "zzz" token but needs a full date and time to build a ZonedDateTime.`);if(u!==void 0&&!b)throw new Error(`temporal-fmt: format string "${e}" has a weekday token ("EEEE"/"EEE") but needs a full date to validate it against.`);if(!b&&!K)throw new Error(`temporal-fmt: format string "${e}" has no date or time tokens to parse.`);let I=A(),Y={hour:c??0,minute:f??0,second:w??0,millisecond:h??0},V=r?{calendar:r}:{},L={overflow:"reject"},x;try{g!==void 0?x=I.ZonedDateTime.from({year:p,month:m,day:d,...Y,...V,timeZone:g},L):b&&K?x=I.PlainDateTime.from({year:p,month:m,day:d,...Y,...V},L):b?x=I.PlainDate.from({year:p,month:m,day:d,...V},L):x=I.PlainTime.from(Y,L)}catch(y){throw new Error(`temporal-fmt: "${t}" doesn't describe a valid date/time for format "${e}": ${y.message}`)}if(u!==void 0){let y=x.dayOfWeek;if(y!==u){let E=M(o);throw new Error(`temporal-fmt: "${k}" doesn't match the actual weekday (${E.weekdayLong[y-1]}) for the parsed date.`)}}return x}0&&(module.exports={format,parse,setTemporal});
|
|
1
|
+
"use strict";var ie=Object.defineProperty;var Ue=Object.getOwnPropertyDescriptor;var Ve=Object.getOwnPropertyNames;var Ye=Object.prototype.hasOwnProperty;var Ze=(e,t)=>{for(var n in t)ie(e,n,{get:t[n],enumerable:!0})},He=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Ve(t))!Ye.call(e,o)&&o!==n&&ie(e,o,{get:()=>t[o],enumerable:!(r=Ue(t,o))||r.enumerable});return e};var je=e=>He(ie({},"__esModule",{value:!0}),e);var jt={};Ze(jt,{format:()=>xe,formatDistance:()=>Ae,formatDuration:()=>Oe,parse:()=>Fe,parseRelative:()=>Ce,registerLocaleVocab:()=>Te,setTemporal:()=>Ee});module.exports=je(jt);var we,be=[];function ke(e){be.push(e)}function Ee(e){we=e;for(let t of be)t()}function ze(){return we??globalThis.Temporal}function $(){let e=ze();if(!e)throw new Error("temporal-fmt: parse() needs a Temporal implementation to construct its result. Call setTemporal(Temporal) once at startup, or assign one to globalThis.Temporal (native on Node 26+, or a polyfill like temporal-polyfill).");return e}var se=new Map;function Ke(e,t){let n=[{key:"monthLong",length:12,label:"long month names"},{key:"monthShort",length:12,label:"short month names"},{key:"weekdayLong",length:7,label:"long weekday names"},{key:"weekdayShort",length:7,label:"short weekday names"},{key:"dayPeriod",length:2,label:"day period markers (AM/PM-equivalent)"}];for(let{key:r,length:o,label:a}of n){let i=e[r];if(i===void 0)throw new Error(`temporal-fmt: registerLocaleVocab for locale "${t}" is missing required field "${r}" (${a}).`);if(!Array.isArray(i))throw new Error(`temporal-fmt: registerLocaleVocab for locale "${t}": "${r}" must be an array, got ${typeof i}.`);if(i.length!==o)throw new Error(`temporal-fmt: registerLocaleVocab for locale "${t}": "${r}" must have exactly ${o} entries (got ${i.length}) \u2014 ${a}.`);i.forEach((s,m)=>{if(typeof s!="string"||s.length===0)throw new Error(`temporal-fmt: registerLocaleVocab for locale "${t}": "${r}[${m}]" must be a non-empty string, got ${String(s)}.`)})}if(M(e.monthLong,"MMMM month",t),M(e.monthShort,"MMM month",t),M(e.weekdayLong,"EEEE weekday",t),M(e.weekdayShort,"EEE weekday",t),e.dayPeriod[0]===e.dayPeriod[1])throw new Error(`temporal-fmt: registerLocaleVocab for locale "${t}": dayPeriod entries must differ (both are "${e.dayPeriod[0]}"); otherwise parse() can't tell AM from PM.`)}function Te(e,t){if(typeof e!="string"||e.length===0)throw new Error(`temporal-fmt: registerLocaleVocab requires a non-empty locale string, got ${String(e)}.`);Ke(t,e);let n=P(e);se.set(n,{monthLong:[...t.monthLong],monthShort:[...t.monthShort],weekdayLong:[...t.weekdayLong],weekdayShort:[...t.weekdayShort],dayPeriod:[...t.dayPeriod]}),L.delete(n)}function P(e){try{return new Intl.Locale(e.replace(/_/g,"-")).toString().toLowerCase()}catch{return e}}var L=new Map,We=500;function F(e,t,n){let r=e.formatToParts(t),o=r.findIndex(m=>m.type===n);if(o===-1)throw new Error(`temporal-fmt: locale produced no "${n}" part while building match vocabulary.`);let a=r[o].value,i=r[o-1],s=r[o+1];return i?.type==="literal"&&!/\s/.test(i.value)&&(a=i.value+a),s?.type==="literal"&&!/\s/.test(s.value)&&(a=a+s.value),a}function M(e,t,n){let r=new Map;for(let o=0;o<e.length;o++){let a=r.get(e[o]);if(a!==void 0)throw new Error(`temporal-fmt: locale "${n}" renders ${t} index ${a} and ${o} identically ("${e[o]}"). parse() can't reliably tell these apart for this locale/token, so this combination isn't supported.`);r.set(e[o],o)}}function O(e){let t=P(e);return se.get(t)}function N(e){let t=P(e),n=se.get(t);if(n)return n;let r=L.get(t);if(r)return r;let o=new Intl.DateTimeFormat(e,{month:"long",timeZone:"UTC"}),a=new Intl.DateTimeFormat(e,{month:"short",timeZone:"UTC"}),i=[],s=[];for(let y=0;y<12;y++){let T=new Date(Date.UTC(2020,y,1));i.push(F(o,T,"month")),s.push(F(a,T,"month"))}M(i,"MMMM month",e),M(s,"MMM month",e);let m=new Intl.DateTimeFormat(e,{weekday:"long",timeZone:"UTC"}),c=new Intl.DateTimeFormat(e,{weekday:"short",timeZone:"UTC"}),u=[],l=[];for(let y=0;y<7;y++){let T=new Date(Date.UTC(2024,0,1+y));u.push(F(m,T,"weekday")),l.push(F(c,T,"weekday"))}M(u,"EEEE weekday",e),M(l,"EEE weekday",e);let d=new Intl.DateTimeFormat(e,{hour:"numeric",hour12:!0,timeZone:"UTC"}),f=F(d,new Date(Date.UTC(2020,0,1,1)),"dayPeriod"),p=F(d,new Date(Date.UTC(2020,0,1,13)),"dayPeriod"),w=[...new Set([f,p])],b={monthLong:i,monthShort:s,weekdayLong:u,weekdayShort:l,dayPeriod:w};if(L.size>=We){let y=L.keys().next().value;y!==void 0&&L.delete(y)}return L.set(t,b),b}var Qe=[0,31,59,90,120,151,181,212,243,273,304,334];function I(e){return e%4===0&&e%100!==0||e%400===0}function C(e){return I(e)?366:365}function ue(e,t,n){let r=Qe[t-1]+n;return t>2&&I(e)&&(r+=1),r}var me=2e3;function qe(e){let t=0;if(e>=me)for(let r=me;r<e;r++)t+=C(r);else for(let r=e;r<me;r++)t-=C(r);return((5+t)%7+7)%7+1}function de(e,t,n,r){let a=ue(e,t,n)+(4-r),i,s;a<1?(i=e-1,s=a+C(i)):a>C(e)?(i=e+1,s=a-C(e)):(i=e,s=a);let c=1+(4-qe(i)+7)%7,u=1+Math.floor((s-c)/7);return{isoYear:i,week:u}}function k(e,t){let n=e<0,r=String(Math.abs(e)).padStart(t,"0");return n?"-"+r:r}var R="en-US",_=new Map,Ge=500;function De(e,t){let n=JSON.stringify([P(e),t]),r=_.get(n);if(r)return r;if(_.size>=Ge){let o=_.keys().next().value;o!==void 0&&_.delete(o)}return r=new Intl.DateTimeFormat(e,t),_.set(n,r),r}var U;ke(()=>{U=void 0});function Xe(){if(U===void 0){U=!1;try{let e=$();new Intl.DateTimeFormat("en-US",{day:"numeric"}).formatToParts(e.PlainDate.from({year:1970,month:1,day:1})),U=!0}catch{}}return U}function Be(e,t,n,r){let o=e?.calendarId,a={...n,calendar:o&&o!=="iso8601"?o:"gregory"};if(!Xe())return e.toLocaleString(t,a);let{toInstant:i,timeZoneId:s}=e,m=typeof i=="function"&&typeof s=="string",c=m?e.toInstant():e,u={...a,...m?{timeZone:s}:{}},d=De(t,u).formatToParts(c),f=d.findIndex(y=>y.type===r);if(f===-1)throw new Error(`temporal-fmt: locale "${t}" produced no "${r}" part for this token. This usually means the Temporal object is missing the field the token needs.`);let p=d[f].value,w=d[f-1],b=d[f+1];return w?.type==="literal"&&!/\s/.test(w.value)&&(p=w.value+p),b?.type==="literal"&&!/\s/.test(b.value)&&(p=p+b.value),p}function Je(e,t){let n=O(t);if(n)return e<12?n.dayPeriod[0]:n.dayPeriod[1];let r=new Date(Date.UTC(1970,0,1,e)),a=De(t,{hour:"numeric",hour12:!0,timeZone:"UTC"}).formatToParts(r).find(i=>i.type==="dayPeriod");if(!a)throw new Error(`temporal-fmt: locale "${t}" produced no "dayPeriod" part for token "a".`);return a.value}function K(e,t,n,r,o,a){return o&&a!==void 0&&a>=0&&a<o.length?o[a]:Be(e,t,n,r)}var W=[["yyyy",e=>k(e.year,4),"year"],["yy",e=>{if(e.year<0)throw new Error(`temporal-fmt: token "yy" doesn't support negative years (got ${e.year}), since truncating to 2 digits would make it indistinguishable from a positive year. Use "yyyy" instead.`);return k(e.year%100,2)},"year"],["MMMM",(e,t)=>{let n=O(t);return K(e,t,{month:"long"},"month",n?.monthLong,e.month-1)},"month"],["MMM",(e,t)=>{let n=O(t);return K(e,t,{month:"short"},"month",n?.monthShort,e.month-1)},"month"],["MM",e=>k(e.month,2),"month"],["M",e=>String(e.month),"month"],["dd",e=>k(e.day,2),"day"],["d",e=>String(e.day),"day"],["EEEE",(e,t)=>{let n=O(t);return K(e,t,{weekday:"long"},"weekday",n?.weekdayLong,e.dayOfWeek-1)},"dayOfWeek"],["EEE",(e,t)=>{let n=O(t);return K(e,t,{weekday:"short"},"weekday",n?.weekdayShort,e.dayOfWeek-1)},"dayOfWeek"],["HH",e=>k(e.hour,2),"hour"],["H",e=>String(e.hour),"hour"],["hh",e=>k(e.hour%12||12,2),"hour"],["h",e=>String(e.hour%12||12),"hour"],["mm",e=>k(e.minute,2),"minute"],["m",e=>String(e.minute),"minute"],["ss",e=>k(e.second,2),"second"],["s",e=>String(e.second),"second"],["SSS",e=>k(e.millisecond,3),"millisecond"],["a",(e,t)=>Je(e.hour,t),"hour"],["zzz",e=>e.timeZoneId,"timeZoneId"],["do",e=>{let t=e.day,n=t%10,r=t%100;return r>=11&&r<=13?t+"th":n===1?t+"st":n===2?t+"nd":n===3?t+"rd":t+"th"},"day"],["Q",e=>String(Math.ceil(e.month/3)),"month"],["QQQ",e=>"Q"+Math.ceil(e.month/3),"month"],["ww",e=>{let{week:t}=de(e.year,e.month,e.day,e.dayOfWeek);return k(t,2)},"dayOfWeek"],["RRRR",e=>{let{isoYear:t}=de(e.year,e.month,e.day,e.dayOfWeek);return k(t,4)},"dayOfWeek"]];var et=W.map(([e])=>e).sort((e,t)=>t.length-e.length);function Q(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(r==="'"){if(e[n+1]==="'"){le(t,"'"),n+=2;continue}let a=n+1,i="",s=!1;for(;a<e.length;){if(e[a]==="'"){if(e[a+1]==="'"){i+="'",a+=2;continue}s=!0,a+=1;break}i+=e[a],a+=1}if(!s)throw new Error(`temporal-fmt: unterminated quote in format string "${e}"`);le(t,i),n=a;continue}let o=et.find(a=>e.startsWith(a,n));if(o){t.push({kind:"token",value:o}),n+=o.length;continue}le(t,r),n+=1}return t}function le(e,t){let n=e[e.length-1];n&&n.kind==="literal"?n.value+=t:e.push({kind:"literal",value:t})}var tt=new Map(W.map(([e,t,n])=>[e,{fn:t,field:n}]));function xe(e,t,n={}){if(t.length>1e3)throw new Error(`temporal-fmt: format string exceeds maximum length of ${1e3} characters (got ${t.length}).`);let r=n.locale??R,o=Q(t),a="";for(let i of o){if(i.kind==="literal"){a+=i.value;continue}let s=tt.get(i.value);if(!s)throw new Error(`temporal-fmt: unknown token "${i.value}"`);if(e[s.field]===void 0)throw new Error(`temporal-fmt: token "${i.value}" requires "${s.field}", which this Temporal object doesn't have. (e.g. PlainDate has no time fields, PlainTime has no date fields)`);a+=s.fn(e,r)}return a}function nt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Y(e,t=!1){let n=e.map(nt);return t?`(?:${n.map(rt).join("|")})`:`(?:${n.join("|")})`}function rt(e){return e.replace(/[a-zA-Z]/g,t=>`[${t.toLowerCase()}${t.toUpperCase()}]`)}var ot="(?:UTC|[+-]\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?|[A-Za-z_]+(?:[+-]\\d{1,2})?(?:\\/[A-Za-z0-9_+-]+)*)";function at(){return ot}var q;function it(){return q||(q=new Set(Intl.supportedValuesOf("timeZone")),q.add("UTC")),q}var st=/^[+-]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?$/;function Me(e){return st.test(e)||it().has(e)}var mt={yy:"\\d{2}",MM:"(?:0[1-9]|1[0-2])",M:"(?:1[0-2]|[1-9])",dd:"(?:0[1-9]|[12]\\d|3[01])",d:"(?:[12]\\d|3[01]|[1-9])",HH:"(?:[01]\\d|2[0-3])",H:"(?:1\\d|2[0-3]|[0-9])",hh:"(?:0[1-9]|1[0-2])",h:"(?:1[0-2]|[1-9])",mm:"(?:[0-5]\\d)",m:"(?:[1-5]\\d|[0-9])",ss:"(?:[0-5]\\d)",s:"(?:[1-5]\\d|[0-9])",SSS:"\\d{3}",Q:"[1-4]"},ut="Q[1-4]",dt=new Set(["do","ww","RRRR"]),lt="-?\\d{4}",ct="-?\\d{4,}",ft=new Set(["yyyy","yy","MM","M","dd","d","HH","H","hh","h","mm","m","ss","s","SSS"]);function Pe(e,t,n){if(e==="yyyy")return n!==void 0&&ft.has(n)?lt:ct;let r=mt[e];if(r)return r;if(e==="QQQ")return ut;if(dt.has(e))throw new Error(`temporal-fmt: token "${e}" is format-only \u2014 it can't be parsed back into a value. Use a different token in the parse format string (e.g. "d" for "do", "MM" for "ww").`);let o=N(t);switch(e){case"MMMM":return Y(o.monthLong);case"MMM":return Y(o.monthShort);case"EEEE":return Y(o.weekdayLong);case"EEE":return Y(o.weekdayShort);case"a":return Y(o.dayPeriod,!0);case"zzz":return at();default:throw new Error(`temporal-fmt: unknown token "${e}"`)}}var ve=new Set(["M","d","H","h","m","s"]),ht={M:[{digits:1,min:1,max:9},{digits:2,min:10,max:12}],d:[{digits:1,min:1,max:9},{digits:2,min:10,max:31}],H:[{digits:1,min:0,max:9},{digits:2,min:10,max:23}],h:[{digits:1,min:1,max:9},{digits:2,min:10,max:12}],m:[{digits:1,min:0,max:9},{digits:2,min:10,max:59}],s:[{digits:1,min:0,max:9},{digits:2,min:10,max:59}]};function Se(e,t){let n=new Map;function r(o,a){let i=`${o}:${a}`,s=n.get(i);if(s)return s;if(o===t.length){let l=a===e.length?[[]]:[];return n.set(i,l),l}let m=t[o],c=ht[m];if(!c)throw new Error(`temporal-fmt: internal error \u2014 "${m}" is not an unpadded numeric token`);let u=[];for(let{digits:l,min:d,max:f}of c){if(a+l>e.length)continue;let p=e.slice(a,a+l);if(l===2&&p[0]==="0")continue;let w=Number(p);if(!(w<d||w>f)){for(let b of r(o+1,a+l))if(u.push([w,...b]),u.length===2)break;if(u.length===2)break}}return n.set(i,u),u}return r(0,0)}function gt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function $e(e,t){let n=[],r=[],o="",a=0,i={groupNames:[],tokens:[]},s=()=>{i.tokens.length>=2&&r.push(i),i={groupNames:[],tokens:[]}};for(let[m,c]of e.entries()){if(c.kind==="literal"){o+=gt(c.value),s();continue}let u=`g${a++}`;n.push({name:u,token:c.value});let l=e[m+1],d=l?.kind==="token"?l.value:void 0;o+=`(?<${u}>${Pe(c.value,t,d)})`,ve.has(c.value)?(i.groupNames.push(u),i.tokens.push(c.value)):s()}return s(),{regex:new RegExp(`^(?:${o})$`,"u"),groups:n,ambiguousRuns:r}}var Z=new Map,yt=500;function wt(e,t){let n=JSON.stringify([P(t),e]),r=Z.get(n);if(r)return r;if(Z.size>=yt){let o=Z.keys().next().value;o!==void 0&&Z.delete(o)}return r=$e(Q(e),t),Z.set(n,r),r}var A=new Map,bt=500;function kt(e){let t=new Intl.Locale(e).toString().toLowerCase();if(A.has(t))return A.get(t);if(A.size>=bt){let i=A.keys().next().value;i!==void 0&&A.delete(i)}let n,r=t.split("-"),o=r.indexOf("u"),a=o===-1?-1:r.indexOf("ca",o+1);if(a!==-1&&a+1<r.length){let i=new Intl.DateTimeFormat(t).resolvedOptions().calendar;n=i==="gregory"?void 0:i}return A.set(t,n),n}function g(e,t,n){e[t]=n}function Et(e,t,n,r,o){let a=N(r);switch(t){case"yyyy":g(e,"year",Number(n));break;case"yy":g(e,"twoDigitYear",Number(n));break;case"MM":case"M":g(e,"month",Number(n));break;case"MMMM":g(e,"month",a.monthLong.indexOf(n)+1);break;case"MMM":g(e,"month",a.monthShort.indexOf(n)+1);break;case"dd":case"d":g(e,"day",Number(n));break;case"EEEE":g(e,"weekdayRaw",n),g(e,"weekdayExpected",a.weekdayLong.indexOf(n)+1);break;case"EEE":g(e,"weekdayRaw",n),g(e,"weekdayExpected",a.weekdayShort.indexOf(n)+1);break;case"HH":case"H":g(e,"hour",Number(n));break;case"hh":case"h":g(e,"hour12",Number(n));break;case"mm":case"m":g(e,"minute",Number(n));break;case"ss":case"s":g(e,"second",Number(n));break;case"SSS":g(e,"millisecond",Number(n));break;case"a":{let i=a.dayPeriod.findIndex(s=>s.toLowerCase()===n.toLowerCase());if(i<0)throw new Error(`temporal-fmt: unknown day period "${n}" for locale "${r}".`);g(e,"dayPeriodRaw",n),g(e,"isPM",i===1);break}case"zzz":g(e,"timeZoneId",n);break;case"Q":g(e,"quarter",Number(n));break;case"QQQ":g(e,"quarter",Number(n.slice(1)));break}}function Tt(e,t){let n=t.indexOf("d");if(n!==-1){let r=e.filter(o=>o[n]<=12);if(r.length>0)return r[0]}return e[0]}function Dt(e){if(e.year!==void 0&&e.twoDigitYear!==void 0)throw new Error('temporal-fmt: format string mixes "yyyy" and "yy" year representations.');if(e.year!==void 0)return e.year;if(e.twoDigitYear!==void 0)return e.twoDigitYear<=68?2e3+e.twoDigitYear:1900+e.twoDigitYear}function xt(e,t,n){if(e.hour!==void 0&&e.hour12!==void 0)throw new Error(`temporal-fmt: format string "${t}" mixes a 24-hour token ("HH"/"H") with a 12-hour token ("hh"/"h").`);if(e.hour!==void 0){if(e.dayPeriodRaw!==void 0){let r=N(n),o=e.hour<12?r.dayPeriod[0]:r.dayPeriod[1];if(e.dayPeriodRaw.toLowerCase()!==o?.toLowerCase())throw new Error(`temporal-fmt: format string "${t}" contains a day period that contradicts the 24-hour value.`)}return e.hour}if(e.hour12!==void 0){if(e.isPM===void 0)throw new Error(`temporal-fmt: format string "${t}" uses a 12-hour token ("hh"/"h") without an "a" token, so parse() can't tell AM from PM.`);return e.hour12%12+(e.isPM?12:0)}}function Fe(e,t,n={}){if(e.length>1e3)throw new Error(`temporal-fmt: format string exceeds maximum length of ${1e3} characters (got ${e.length}).`);if(t.length>1e5)throw new Error(`temporal-fmt: input exceeds maximum length of ${1e5} characters (got ${t.length}).`);let r=n.locale??R,o=kt(r),a=wt(e,r),i=a.regex.exec(t);if(!i)throw new Error("temporal-fmt: no valid pattern matches the format string and input shape");if(a.groups.length===0)throw new Error(`temporal-fmt: format string "${e}" has no tokens \u2014 nothing to parse into a value.`);for(let{name:h,token:E}of a.groups)if(E==="zzz"&&!Me(i.groups[h]))throw new Error("temporal-fmt: no valid pattern matches the format string and input shape");let s=[];for(let h of a.ambiguousRuns){let E=h.groupNames.map(ae=>i.groups[ae]).join(""),D=Se(E,h.tokens);if(D.length>1){if(!n.lenient)throw new Error(`temporal-fmt: "${E}" in format string "${e}" is ambiguous \u2014 ${D.length} different ways to read tokens "${h.tokens.join("")}" (with no separator between them) are all individually valid (e.g. ${JSON.stringify(D[0])} vs ${JSON.stringify(D[1])}). parse() won't guess; add a separator between these tokens, or use their padded form (e.g. "MM" instead of "M") so each one has a fixed width. Pass { lenient: true } to opt into a documented heuristic that picks one.`);s.push({groupNames:h.groupNames,values:Tt(D,h.tokens)})}}let m={},c=new Map;for(let{groupNames:h,values:E}of s)h.forEach((D,ae)=>c.set(D,String(E[ae])));for(let{name:h,token:E}of a.groups){let D=c.get(h)??i.groups[h];Et(m,E,D,r,e)}let u=Dt(m),l=xt(m,e,r),{month:d,day:f,minute:p,second:w,millisecond:b,timeZoneId:y,weekdayExpected:T,weekdayRaw:Ie,quarter:te}=m,_e=u!==void 0||d!==void 0||f!==void 0,v=u!==void 0&&d!==void 0&&f!==void 0;if(_e&&!v)throw new Error(`temporal-fmt: format string "${e}" has an incomplete date \u2014 year, month, and day tokens must all be present together.`);let ne=l!==void 0||p!==void 0||w!==void 0||b!==void 0;if(y!==void 0&&!(v&&ne))throw new Error(`temporal-fmt: format string "${e}" has a "zzz" token but needs a full date and time to build a ZonedDateTime.`);if(T!==void 0&&!v)throw new Error(`temporal-fmt: format string "${e}" has a weekday token ("EEEE"/"EEE") but needs a full date to validate it against.`);if(!v&&!ne)throw new Error(`temporal-fmt: format string "${e}" has no date or time tokens to parse.`);let j=$(),re={hour:l??0,minute:p??0,second:w??0,millisecond:b??0},oe=o?{calendar:o}:{},z={overflow:"reject"},S;try{y!==void 0?S=j.ZonedDateTime.from({year:u,month:d,day:f,...re,...oe,timeZone:y},z):v&&ne?S=j.PlainDateTime.from({year:u,month:d,day:f,...re,...oe},z):v?S=j.PlainDate.from({year:u,month:d,day:f,...oe},z):S=j.PlainTime.from(re,z)}catch(h){throw new Error(`temporal-fmt: "${t}" doesn't describe a valid date/time for format "${e}": ${h.message}`)}if(T!==void 0){let h=S.dayOfWeek;if(h!==T){let E=N(r);throw new Error(`temporal-fmt: "${Ie}" doesn't match the actual weekday (${E.weekdayLong[h-1]}) for the parsed date.`)}}if(te!==void 0&&d!==void 0){let h=Math.ceil(d/3);if(te!==h)throw new Error(`temporal-fmt: format string "${e}" contains a quarter token (Q/QQQ) whose value (Q${te}) disagrees with the parsed month's actual quarter \u2014 month ${d} is in Q${h}.`)}return S}var Le={y:{longSingular:"year",longPlural:"years",shortSingular:"yr",shortPlural:"yrs",field:"years"},o:{longSingular:"month",longPlural:"months",shortSingular:"mo",shortPlural:"mos",field:"months"},w:{longSingular:"week",longPlural:"weeks",shortSingular:"wk",shortPlural:"wks",field:"weeks"},d:{longSingular:"day",longPlural:"days",shortSingular:"d",shortPlural:"d",field:"days"},h:{longSingular:"hour",longPlural:"hours",shortSingular:"h",shortPlural:"h",field:"hours"},m:{longSingular:"minute",longPlural:"minutes",shortSingular:"m",shortPlural:"m",field:"minutes"},s:{longSingular:"second",longPlural:"seconds",shortSingular:"s",shortPlural:"s",field:"seconds"},S:{longSingular:"millisecond",longPlural:"milliseconds",shortSingular:"ms",shortPlural:"ms",field:"milliseconds"}},Mt=Object.keys(Le).flatMap(e=>[e+e+e,e+e,e]).sort((e,t)=>t.length-e.length);function Pt(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(r==="'"){if(e[n+1]==="'"){ce(t,"'"),n+=2;continue}let a=n+1,i="",s=!1;for(;a<e.length;){if(e[a]==="'"){if(e[a+1]==="'"){i+="'",a+=2;continue}s=!0,a+=1;break}i+=e[a],a+=1}if(!s)throw new Error(`temporal-fmt: unterminated quote in duration format string "${e}"`);ce(t,i),n=a;continue}let o=Mt.find(a=>e.startsWith(a,n));if(o){let a=o[0],i=o.length===1?"numeric":o.length===2?"short":"long";t.push({kind:"token",value:o,unit:a,form:i}),n+=o.length;continue}ce(t,r),n+=1}return t}function ce(e,t){let n=e[e.length-1];n&&n.kind==="literal"?n.value+=t:e.push({kind:"literal",value:t})}function vt(e,t){let n=e[t];if(n==null)return 0;if(typeof n=="number"&&Number.isFinite(n))return n;let r=Number(n);if(!Number.isFinite(r))throw new Error(`temporal-fmt: duration field "${t}" is not a finite number (got ${String(n)}).`);return r}function Oe(e,t,n={}){if(t.length>1e3)throw new Error(`temporal-fmt: duration format string exceeds maximum length of ${1e3} characters (got ${t.length}).`);n.locale;let r=n.showZeroValues===!0,o=Pt(t),a="";for(let i of o){if(i.kind==="literal"){a+=i.value;continue}let s=Le[i.unit];if(!s)throw new Error(`temporal-fmt: unknown duration token "${i.value}"`);let m=vt(e,s.field);m===0&&!r||(i.form==="numeric"?a+=String(m):i.form==="short"?a+=m+(m===1||m===-1?s.shortSingular:s.shortPlural):a+=m+" "+(m===1||m===-1?s.longSingular:s.longPlural))}return a}function Ne(e,t){if(e===null||typeof e!="object")throw new Error(`temporal-fmt: formatDistance expects Temporal values, got ${t} = ${String(e)}.`);let n=e,r=typeof n.year=="number",o=typeof n.month=="number",a=typeof n.day=="number";if(r!==o||o!==a)throw new Error(`temporal-fmt: formatDistance got a ${t} with a partial date (some of year/month/day missing). Pass a full Temporal.PlainDate / PlainDateTime / ZonedDateTime.`);return{year:r?n.year:void 0,month:o?n.month:void 0,day:a?n.day:void 0,hour:typeof n.hour=="number"?n.hour:void 0,minute:typeof n.minute=="number"?n.minute:void 0,second:typeof n.second=="number"?n.second:void 0,millisecond:typeof n.millisecond=="number"?n.millisecond:void 0}}var fe=2e3,he=1e3,G=60*he,X=60*G,x=24*X;function St(e,t,n){let r=0;if(e>=fe)for(let o=fe;o<e;o++)r+=I(o)?366:365;else for(let o=e;o<fe;o++)r-=I(o)?366:365;return r+=ue(e,t,n)-1,r}function Re(e){if(e.year===void 0||e.month===void 0||e.day===void 0)throw new Error("temporal-fmt: formatDistance needs a Temporal value with year/month/day fields (PlainDate, PlainDateTime, or ZonedDateTime). A PlainTime or other shape has no anchor date to diff against.");let t=St(e.year,e.month,e.day),n=e.hour??0,r=e.minute??0,o=e.second??0,a=e.millisecond??0;return t*x+n*X+r*G+o*he+a}var $t=[{maxMs:G,unit:"second"},{maxMs:X,unit:"minute"},{maxMs:x,unit:"hour"},{maxMs:30*x,unit:"day"},{maxMs:365*x,unit:"month"}],H=new Map,Ft=100;function Lt(e,t){let n=`${Ot(e)}|${t}`,r=H.get(n);if(r)return r;if(H.size>=Ft){let o=H.keys().next().value;o!==void 0&&H.delete(o)}return r=new Intl.RelativeTimeFormat(e,{numeric:t}),H.set(n,r),r}function Ot(e){try{return new Intl.Locale(e.replace(/_/g,"-")).toString().toLowerCase()}catch{return e}}function Ae(e,t,n={}){let r=Ne(e,"date1"),o=Ne(t,"date2"),a=Re(r)-Re(o),i=Math.abs(a),s="year";for(let{maxMs:f,unit:p}of $t)if(i<f){s=p;break}let m=Nt(s),c=Math.round(a/m),u=n.numeric??"auto",l=n.locale??R;return Lt(l,u).format(c,s)}function Nt(e){switch(e){case"second":return he;case"minute":return G;case"hour":return X;case"day":return x;case"week":return 7*x;case"month":return 30*x;case"quarter":return 91*x;case"year":return 365*x;default:throw new Error(`temporal-fmt: formatDistance hit unhandled unit "${String(e)}".`)}}var pe=["January","February","March","April","May","June","July","August","September","October","November","December"],Rt=pe.flatMap((e,t)=>[[e,t+1],[e.slice(0,3),t+1]]),At=Rt.map(([e])=>e).join("|"),ye=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],Ct=ye.join("|");function It(e){let t=e.toLowerCase(),n=ye.find(r=>r.toLowerCase()===t);return ye.indexOf(n??e)+1}function _t(e){let t=e.toLowerCase(),n=pe.findIndex(o=>o.toLowerCase()===t);return n>=0?n+1:pe.findIndex(o=>o.slice(0,3).toLowerCase()===t)+1}function Ut(e){let t=e.dayOfWeek;if(typeof t!="number")throw new Error("temporal-fmt: parseRelative needs a reference date exposing dayOfWeek (a Temporal.PlainDate / PlainDateTime / ZonedDateTime).");return t}function B(e){if(typeof e.year!="number")throw new Error("temporal-fmt: parseRelative reference date is missing year.");return e.year}function J(e){if(typeof e.month!="number")throw new Error("temporal-fmt: parseRelative reference date is missing month.");return e.month}function ee(e){if(typeof e.day!="number")throw new Error("temporal-fmt: parseRelative reference date is missing day.");return e.day}function Ce(e,t,n={}){n.locale;let r=t,o=$(),a=(e??"").trim().replace(/\s+/g," ");if(a.length===0)throw new Error("temporal-fmt: parseRelative got an empty input string.");let i=a.toLowerCase();if(i==="today")return Yt(o,B(r),J(r),ee(r));if(i==="tomorrow")return ge(o,r,1);if(i==="yesterday")return ge(o,r,-1);let s=a.match(new RegExp(`^(next|last|this)\\s+(${Ct})$`,"i"));if(s){let u=s[1].toLowerCase(),l=s[2],d=Ut(r),f=It(l),p=Vt(u,d,f);return ge(o,r,p)}let m=a.match(/^(in\s+)?(\d+)\s+(day|week|month|year)s?(?:\s+ago)?$/i);if(m){let u=m[1],l=m[2],d=m[3].toLowerCase(),f=!!u,p=/\bago\b/i.test(a);if(!f&&!p)throw new Error(`temporal-fmt: parseRelative can't tell whether "${a}" is past or future \u2014 use "in ${l} ${d}s" or "${l} ${d}s ago".`);return Zt(o,r,(f?1:-1)*Number(l),d)}let c=a.match(new RegExp(`^(${At})\\s+(\\d{1,2})(?:st|nd|rd|th)?(?:,?\\s*(\\d{4}))?$`,"i"));if(c){let u=c[1],l=c[2],d=_t(u),f=Number(l);return Ht(o,r,d,f)}throw new Error(`temporal-fmt: parseRelative doesn't recognize "${a}". Supported: weekday refs ("next Tuesday"), day offsets ("today"/"tomorrow"/"yesterday"), unit offsets ("in 3 days", "2 weeks ago"), and month-day ("March 5th").`)}function Vt(e,t,n){if(e==="next"){let r=n-t;return r<=0&&(r+=7),r}if(e==="last"){let r=n-t;return r>=0&&(r-=7),r}return n-t}function Yt(e,t,n,r){return e.PlainDate.from({year:t,month:n,day:r},{overflow:"reject"})}function ge(e,t,n){return e.PlainDate.from({year:B(t),month:J(t),day:ee(t)}).add({days:n})}function Zt(e,t,n,r){let o=e.PlainDate.from({year:B(t),month:J(t),day:ee(t)}),a={};return r==="day"&&(a.days=n),r==="week"&&(a.weeks=n),r==="month"&&(a.months=n),r==="year"&&(a.years=n),o.add(a)}function Ht(e,t,n,r){let o=B(t),a=e.PlainDate.from({year:o,month:J(t),day:ee(t)});try{let i=e.PlainDate.from({year:o,month:n,day:r},{overflow:"reject"});if(!e.PlainDate.compare)throw new Error("temporal-fmt: parseRelative needs Temporal.PlainDate.compare to resolve month-day phrases; the active implementation does not expose it.");return e.PlainDate.compare(i,a)>=0?i:e.PlainDate.from({year:o+1,month:n,day:r},{overflow:"reject"})}catch(i){try{return e.PlainDate.from({year:o+1,month:n,day:r},{overflow:"reject"})}catch{throw new Error(`temporal-fmt: parseRelative can't resolve month ${n} day ${r} \u2014 it isn't a valid date in either ${o} or ${o+1}. Original error: ${i.message}`)}}}0&&(module.exports={format,formatDistance,formatDuration,parse,parseRelative,registerLocaleVocab,setTemporal});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|