temporal-fmt 0.9.0 → 0.9.2

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.
Files changed (105) hide show
  1. package/dist/calendarUtils.cjs +4 -259
  2. package/dist/calendarUtils.cjs.map +1 -1
  3. package/dist/calendarUtils.js +1 -33
  4. package/dist/chunk-2JHEV7ZF.js +7 -0
  5. package/dist/chunk-2JHEV7ZF.js.map +1 -0
  6. package/dist/chunk-3MZLTVP3.js +2 -0
  7. package/dist/{chunk-MXXYIMFJ.js.map → chunk-3MZLTVP3.js.map} +1 -1
  8. package/dist/chunk-4JWGUR4O.js +11 -0
  9. package/dist/{chunk-AXQLUIDY.js.map → chunk-4JWGUR4O.js.map} +1 -1
  10. package/dist/chunk-5U5WJ465.js +36 -0
  11. package/dist/chunk-5U5WJ465.js.map +1 -0
  12. package/dist/chunk-C5YESWFT.js +2 -0
  13. package/dist/chunk-C5YESWFT.js.map +1 -0
  14. package/dist/chunk-C6ZZ62ET.js +2 -0
  15. package/dist/{chunk-YS52LOMJ.js.map → chunk-C6ZZ62ET.js.map} +1 -1
  16. package/dist/chunk-EHLRZULM.js +5 -0
  17. package/dist/{chunk-4ZBGVYLR.js.map → chunk-EHLRZULM.js.map} +1 -1
  18. package/dist/chunk-F4RGUDA3.js +2 -0
  19. package/dist/chunk-F4RGUDA3.js.map +1 -0
  20. package/dist/chunk-J2AQNXF2.js +2 -0
  21. package/dist/{chunk-GRJQHQLW.js.map → chunk-J2AQNXF2.js.map} +1 -1
  22. package/dist/chunk-NBXF7V5B.js +2 -0
  23. package/dist/chunk-NBXF7V5B.js.map +1 -0
  24. package/dist/chunk-R52YOKI3.js +7 -0
  25. package/dist/{chunk-M33NSC4E.js.map → chunk-R52YOKI3.js.map} +1 -1
  26. package/dist/chunk-UJR6DHXY.js +2 -0
  27. package/dist/chunk-UJR6DHXY.js.map +1 -0
  28. package/dist/chunk-VQXUMFB2.js +21 -0
  29. package/dist/{chunk-VHSZL3P3.js.map → chunk-VQXUMFB2.js.map} +1 -1
  30. package/dist/chunk-XH46JNPK.js +2 -0
  31. package/dist/chunk-XH46JNPK.js.map +1 -0
  32. package/dist/chunk-YB6YAG7E.js +35 -0
  33. package/dist/chunk-YB6YAG7E.js.map +1 -0
  34. package/dist/chunk-ZGMTY52O.js +2 -0
  35. package/dist/chunk-ZGMTY52O.js.map +1 -0
  36. package/dist/duration.cjs +9 -624
  37. package/dist/duration.cjs.map +1 -1
  38. package/dist/duration.js +1 -29
  39. package/dist/format.cjs +18 -769
  40. package/dist/format.cjs.map +1 -1
  41. package/dist/format.js +1 -20
  42. package/dist/formatDuration.d.cts +6 -0
  43. package/dist/formatDuration.d.ts +6 -0
  44. package/dist/index.cjs +146 -6672
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.js +58 -3004
  47. package/dist/index.js.map +1 -1
  48. package/dist/interval.cjs +18 -952
  49. package/dist/interval.cjs.map +1 -1
  50. package/dist/interval.js +1 -41
  51. package/dist/localeRegistry.cjs +15 -328
  52. package/dist/localeRegistry.cjs.map +1 -1
  53. package/dist/localeRegistry.js +1 -11
  54. package/dist/localeVocab.d.cts +3 -0
  55. package/dist/localeVocab.d.ts +3 -0
  56. package/dist/parse.cjs +53 -1637
  57. package/dist/parse.cjs.map +1 -1
  58. package/dist/parse.js +1 -20
  59. package/dist/parsePattern.d.cts +1 -0
  60. package/dist/parsePattern.d.ts +1 -0
  61. package/dist/pattern.d.cts +1 -0
  62. package/dist/pattern.d.ts +1 -0
  63. package/dist/recurrence.cjs +20 -450
  64. package/dist/recurrence.cjs.map +1 -1
  65. package/dist/recurrence.js +1 -20
  66. package/dist/relativeTime.cjs +24 -177
  67. package/dist/relativeTime.cjs.map +1 -1
  68. package/dist/relativeTime.js +1 -14
  69. package/dist/rounding.d.cts +1 -0
  70. package/dist/rounding.d.ts +1 -0
  71. package/dist/serialization.d.cts +1 -1
  72. package/dist/serialization.d.ts +1 -1
  73. package/dist/timezone.cjs +20 -387
  74. package/dist/timezone.cjs.map +1 -1
  75. package/dist/timezone.js +1 -26
  76. package/dist/typeGuards.d.cts +9 -9
  77. package/dist/typeGuards.d.ts +9 -9
  78. package/package.json +4 -2
  79. package/dist/chunk-4ZBGVYLR.js +0 -182
  80. package/dist/chunk-AXQLUIDY.js +0 -183
  81. package/dist/chunk-CKVHXFX7.js +0 -902
  82. package/dist/chunk-CKVHXFX7.js.map +0 -1
  83. package/dist/chunk-CSUIKL73.js +0 -215
  84. package/dist/chunk-CSUIKL73.js.map +0 -1
  85. package/dist/chunk-EDUFSRWJ.js +0 -9
  86. package/dist/chunk-EDUFSRWJ.js.map +0 -1
  87. package/dist/chunk-FQA4XJME.js +0 -57
  88. package/dist/chunk-FQA4XJME.js.map +0 -1
  89. package/dist/chunk-FTMLZ4EN.js +0 -196
  90. package/dist/chunk-FTMLZ4EN.js.map +0 -1
  91. package/dist/chunk-GRJQHQLW.js +0 -170
  92. package/dist/chunk-JCIMP43G.js +0 -602
  93. package/dist/chunk-JCIMP43G.js.map +0 -1
  94. package/dist/chunk-KDYK72Z2.js +0 -75
  95. package/dist/chunk-KDYK72Z2.js.map +0 -1
  96. package/dist/chunk-M33NSC4E.js +0 -169
  97. package/dist/chunk-MXXYIMFJ.js +0 -29
  98. package/dist/chunk-NFKQ3EXC.js +0 -188
  99. package/dist/chunk-NFKQ3EXC.js.map +0 -1
  100. package/dist/chunk-O6GVMBLW.js +0 -403
  101. package/dist/chunk-O6GVMBLW.js.map +0 -1
  102. package/dist/chunk-VHSZL3P3.js +0 -242
  103. package/dist/chunk-VSUCBUTC.js +0 -295
  104. package/dist/chunk-VSUCBUTC.js.map +0 -1
  105. package/dist/chunk-YS52LOMJ.js +0 -51
package/dist/duration.cjs CHANGED
@@ -1,176 +1,4 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/duration.ts
21
- var duration_exports = {};
22
- __export(duration_exports, {
23
- addDuration: () => addDuration,
24
- balanceDuration: () => balanceDuration,
25
- compareDuration: () => compareDuration,
26
- formatDurationToParts: () => formatDurationToParts,
27
- formatISODuration: () => formatISODuration,
28
- parseDuration: () => parseDuration,
29
- parseISODuration: () => parseISODuration,
30
- roundDuration: () => roundDuration,
31
- subtractDuration: () => subtractDuration,
32
- totalDuration: () => totalDuration
33
- });
34
- module.exports = __toCommonJS(duration_exports);
35
-
36
- // src/rounding.ts
37
- var DURATION_UNIT_TO_NS = {
38
- years: 0n,
39
- // calendar-bound, can't convert without relativeTo
40
- months: 0n,
41
- // same
42
- weeks: 0n,
43
- // same
44
- days: 86400n * 1000000000n,
45
- hours: 3600n * 1000000000n,
46
- minutes: 60n * 1000000000n,
47
- seconds: 1000000000n,
48
- milliseconds: 1000000n,
49
- microseconds: 1000n,
50
- nanoseconds: 1n
51
- };
52
- function isCalendarBound(unit) {
53
- return unit === "years" || unit === "months" || unit === "weeks";
54
- }
55
- function roundDuration(duration, options) {
56
- const mode = options.mode ?? "nearest";
57
- const increment = BigInt(options.roundingIncrement ?? 1);
58
- if (increment <= 0n) {
59
- throw new Error(`temporal-fmt: roundDuration() requires a positive roundingIncrement (got ${options.roundingIncrement}).`);
60
- }
61
- if (isCalendarBound(options.unit)) {
62
- throw new Error(
63
- `temporal-fmt: roundDuration() to "${options.unit}" requires a Temporal.Duration with a relativeTo \u2014 this helper operates on plain field bags without calendar context. Use Temporal.Duration.prototype.round() directly.`
64
- );
65
- }
66
- let totalNs = 0n;
67
- for (const u of ["days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]) {
68
- const v = duration[u] ?? 0;
69
- totalNs += BigInt(v) * DURATION_UNIT_TO_NS[u];
70
- }
71
- const stepNs = increment * DURATION_UNIT_TO_NS[options.unit];
72
- const sign = totalNs < 0n ? -1n : 1n;
73
- const abs = totalNs < 0n ? -totalNs : totalNs;
74
- const stepped = abs / stepNs;
75
- const remainder = abs % stepNs;
76
- let rounded;
77
- switch (mode) {
78
- case "nearest":
79
- rounded = remainder * 2n >= stepNs ? stepped + 1n : stepped;
80
- break;
81
- case "floor":
82
- rounded = stepped;
83
- break;
84
- case "ceil":
85
- rounded = remainder > 0n ? stepped + 1n : stepped;
86
- break;
87
- case "trunc":
88
- rounded = stepped;
89
- break;
90
- }
91
- const newTotalNs = sign * rounded * stepNs;
92
- const result = { ...duration };
93
- let remaining = newTotalNs;
94
- for (const u of ["days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"]) {
95
- if (u === options.unit || isLargerUnit(u, options.unit) || u === options.unit) {
96
- }
97
- result[u] = 0;
98
- }
99
- const unitsInOrder = ["days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"];
100
- const startIdx = unitsInOrder.indexOf(options.unit);
101
- for (let i = 0; i <= startIdx; i++) {
102
- const u = unitsInOrder[i];
103
- const unitNs = DURATION_UNIT_TO_NS[u];
104
- if (unitNs === 0n) continue;
105
- const count = remaining / unitNs;
106
- remaining -= count * unitNs;
107
- if (count !== 0n) {
108
- result[u] = Number(count);
109
- }
110
- }
111
- return result;
112
- }
113
- function isLargerUnit(_a, _b) {
114
- return false;
115
- }
116
-
117
- // src/constants.ts
118
- var MAX_FORMAT_LENGTH = 1e3;
119
-
120
- // src/errors.ts
121
- var TemporalFmtError = class extends Error {
122
- code;
123
- input;
124
- format;
125
- token;
126
- position;
127
- expected;
128
- actual;
129
- reason;
130
- constructor(message, fields) {
131
- super(message);
132
- this.name = "TemporalFmtError";
133
- this.code = fields.code;
134
- this.input = fields.input;
135
- this.format = fields.format;
136
- this.token = fields.token;
137
- this.position = fields.position;
138
- this.expected = fields.expected;
139
- this.actual = fields.actual;
140
- this.reason = fields.reason;
141
- const capture = Error.captureStackTrace;
142
- if (typeof capture === "function") {
143
- capture(this, this.constructor);
144
- }
145
- }
146
- // Lets callers do `err.toJSON()` for logging. Plain `Error` doesn't
147
- // serialize its non-enumerable fields; this picks them up explicitly.
148
- toJSON() {
149
- return {
150
- name: this.name,
151
- message: this.message,
152
- code: this.code,
153
- input: this.input,
154
- format: this.format,
155
- token: this.token,
156
- position: this.position,
157
- expected: this.expected,
158
- actual: this.actual,
159
- reason: this.reason
160
- };
161
- }
162
- };
163
- var FormatSyntaxError = class extends TemporalFmtError {
164
- constructor(fields) {
165
- const { message, ...rest } = fields;
166
- super(
167
- message ?? `format string "${fields.format ?? ""}" has a syntax error${fields.reason ? `: ${fields.reason}` : ""}.`,
168
- { code: "FORMAT_SYNTAX_ERROR", ...rest }
169
- );
170
- this.name = "FormatSyntaxError";
171
- }
172
- };
173
- /* c8 ignore start @preserve -- InvalidTimeError is part of the public
1
+ "use strict";var T=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var z=(e,t)=>{for(var n in t)T(e,n,{get:t[n],enumerable:!0})},K=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of U(t))!C.call(e,r)&&r!==n&&T(e,r,{get:()=>t[r],enumerable:!(o=R(t,r))||o.enumerable});return e};var Z=e=>K(T({},"__esModule",{value:!0}),e);var ue={};z(ue,{addDuration:()=>v,balanceDuration:()=>oe,compareDuration:()=>se,formatDurationToParts:()=>J,formatISODuration:()=>ee,parseDuration:()=>ne,parseISODuration:()=>Q,roundDuration:()=>A,subtractDuration:()=>ie,totalDuration:()=>re});module.exports=Z(ue);var p=class extends Error{code;input;format;token;position;expected;actual;reason;constructor(t,n){super(t),this.name="TemporalFmtError",this.code=n.code,this.input=n.input,this.format=n.format,this.token=n.token,this.position=n.position,this.expected=n.expected,this.actual=n.actual,this.reason=n.reason;let o=Error.captureStackTrace;typeof o=="function"&&o(this,this.constructor)}toJSON(){return{name:this.name,message:this.message,code:this.code,input:this.input,format:this.format,token:this.token,position:this.position,expected:this.expected,actual:this.actual,reason:this.reason}}},f=class extends p{constructor(t){let{message:n,...o}=t;super(n??`format string "${t.format??""}" has a syntax error${t.reason?`: ${t.reason}`:""}.`,{code:"FORMAT_SYNTAX_ERROR",...o}),this.name="FormatSyntaxError"}};/* c8 ignore start @preserve -- InvalidTimeError is part of the public
174
2
  error-class surface (exported from index.ts, code 'INVALID_TIME')
175
3
  but nothing in this package constructs one. Investigated wiring it
176
4
  in the same way InvalidTimeZoneError was just wired (see parse.ts's
@@ -182,9 +10,7 @@ var FormatSyntaxError = class extends TemporalFmtError {
182
10
  is rejected as a plain shape mismatch before any semantic check
183
11
  could run. There's no live gap to hook this into without inventing a
184
12
  redundant check purely to give this class a body. Left unconstructed
185
- until the library actually has a real invalid-time case to report. */
186
- /* c8 ignore stop @preserve */
187
- /* c8 ignore start @preserve -- InvalidCalendarError is part of the
13
+ until the library actually has a real invalid-time case to report. *//* c8 ignore stop @preserve *//* c8 ignore start @preserve -- InvalidCalendarError is part of the
188
14
  public error-class surface (exported from index.ts, code
189
15
  'INVALID_CALENDAR') but nothing in this package constructs one.
190
16
  Checked for a wiring opportunity the same way InvalidTimeZoneError
@@ -194,452 +20,11 @@ var FormatSyntaxError = class extends TemporalFmtError {
194
20
  of the locale string — it's never handed an arbitrary "calendar"
195
21
  value a caller could get wrong. There's no live input to reject.
196
22
  Left unconstructed until the library actually accepts a calendar
197
- parameter that could be invalid. */
198
- /* c8 ignore stop @preserve */
199
- var InvalidDurationError = class extends TemporalFmtError {
200
- constructor(fields) {
201
- const { message, ...rest } = fields;
202
- super(
203
- message ?? `duration is invalid${fields.reason ? `: ${fields.reason}` : ""}.`,
204
- { code: "INVALID_DURATION", ...rest }
205
- );
206
- this.name = "InvalidDurationError";
207
- }
208
- };
209
- /* c8 ignore start @preserve -- unreachable from the current test suite,
210
- see rationale above */
211
- /* c8 ignore stop @preserve */
212
-
213
- // src/localeVocab.ts
214
- function canonicalCacheKey(locale) {
215
- try {
216
- return new Intl.Locale(locale.replace(/_/g, "-")).toString().toLowerCase();
217
- } catch {
218
- return locale;
219
- }
220
- }
221
-
222
- // src/formatDuration.ts
223
- var DURATION_UNITS = {
224
- y: { longSingular: "year", longPlural: "years", shortSingular: "yr", shortPlural: "yrs", field: "years", intlUnit: "year" },
225
- o: { longSingular: "month", longPlural: "months", shortSingular: "mo", shortPlural: "mos", field: "months", intlUnit: "month" },
226
- w: { longSingular: "week", longPlural: "weeks", shortSingular: "wk", shortPlural: "wks", field: "weeks", intlUnit: "week" },
227
- d: { longSingular: "day", longPlural: "days", shortSingular: "d", shortPlural: "d", field: "days", intlUnit: "day" },
228
- h: { longSingular: "hour", longPlural: "hours", shortSingular: "h", shortPlural: "h", field: "hours", intlUnit: "hour" },
229
- m: { longSingular: "minute", longPlural: "minutes", shortSingular: "m", shortPlural: "m", field: "minutes", intlUnit: "minute" },
230
- s: { longSingular: "second", longPlural: "seconds", shortSingular: "s", shortPlural: "s", field: "seconds", intlUnit: "second" },
231
- S: { longSingular: "millisecond", longPlural: "milliseconds", shortSingular: "ms", shortPlural: "ms", field: "milliseconds", intlUnit: "millisecond" }
232
- };
233
- var DURATION_TOKEN_STRINGS = Object.keys(DURATION_UNITS).flatMap((single) => [single + single + single, single + single, single]).sort((a, b) => b.length - a.length);
234
- function tokenizeDuration(format) {
235
- const pieces = [];
236
- let i = 0;
237
- while (i < format.length) {
238
- const ch = format[i];
239
- if (ch === "'") {
240
- if (format[i + 1] === "'") {
241
- appendLiteral(pieces, "'");
242
- i += 2;
243
- continue;
244
- }
245
- let j = i + 1;
246
- let literal = "";
247
- let closed = false;
248
- while (j < format.length) {
249
- if (format[j] === "'") {
250
- if (format[j + 1] === "'") {
251
- literal += "'";
252
- j += 2;
253
- continue;
254
- }
255
- closed = true;
256
- j += 1;
257
- break;
258
- }
259
- literal += format[j];
260
- j += 1;
261
- }
262
- if (!closed) {
263
- throw new Error(`temporal-fmt: unterminated quote in duration format string "${format}"`);
264
- }
265
- appendLiteral(pieces, literal);
266
- i = j;
267
- continue;
268
- }
269
- const match = DURATION_TOKEN_STRINGS.find((tok) => format.startsWith(tok, i));
270
- if (match) {
271
- const unit = match[0];
272
- const form = match.length === 1 ? "numeric" : match.length === 2 ? "short" : "long";
273
- pieces.push({ kind: "token", value: match, unit, form });
274
- i += match.length;
275
- continue;
276
- }
277
- appendLiteral(pieces, ch);
278
- i += 1;
279
- }
280
- return pieces;
281
- }
282
- function appendLiteral(pieces, value) {
283
- const last = pieces[pieces.length - 1];
284
- if (last && last.kind === "literal") {
285
- last.value += value;
286
- } else {
287
- pieces.push({ kind: "literal", value });
288
- }
289
- }
290
- function readUnit(duration, field) {
291
- const value = duration[field];
292
- if (value === void 0 || value === null) return 0;
293
- if (typeof value === "number" && Number.isFinite(value)) return value;
294
- const coerced = Number(value);
295
- if (!Number.isFinite(coerced)) {
296
- throw new Error(
297
- `temporal-fmt: duration field "${field}" is not a finite number (got ${String(value)}).`
298
- );
299
- }
300
- return coerced;
301
- }
302
- var unitFormatterCache = /* @__PURE__ */ new Map();
303
- var MAX_UNIT_FORMATTER_CACHE_SIZE = 200;
304
- function getUnitFormatter(locale, intlUnit, unitDisplay) {
305
- const key = `${canonicalCacheKey(locale)}|${intlUnit}|${unitDisplay}`;
306
- const cached = unitFormatterCache.get(key);
307
- if (cached) return cached;
308
- if (unitFormatterCache.size >= MAX_UNIT_FORMATTER_CACHE_SIZE) {
309
- const oldestKey = unitFormatterCache.keys().next().value;
310
- if (oldestKey !== void 0) unitFormatterCache.delete(oldestKey);
311
- }
312
- const formatter = new Intl.NumberFormat(locale, {
313
- style: "unit",
314
- unit: intlUnit,
315
- unitDisplay
316
- });
317
- unitFormatterCache.set(key, formatter);
318
- return formatter;
319
- }
320
- function formatDuration(duration, formatStr, options = {}) {
321
- if (formatStr.length > MAX_FORMAT_LENGTH) {
322
- throw new Error(
323
- `temporal-fmt: duration format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters (got ${formatStr.length}).`
324
- );
325
- }
326
- const showZeroes = options.showZeroValues === true;
327
- const locale = options.locale;
328
- const useIntl = locale !== void 0;
329
- const pieces = tokenizeDuration(formatStr);
330
- let result = "";
331
- for (const piece of pieces) {
332
- if (piece.kind === "literal") {
333
- result += piece.value;
334
- continue;
335
- }
336
- const unit = DURATION_UNITS[piece.unit];
337
- if (!unit) {
338
- throw new Error(`temporal-fmt: unknown duration token "${piece.value}"`);
339
- }
340
- const value = readUnit(duration, unit.field);
341
- if (value === 0 && !showZeroes) {
342
- continue;
343
- }
344
- if (piece.form === "numeric") {
345
- result += String(value);
346
- continue;
347
- }
348
- if (useIntl) {
349
- const unitDisplay = piece.form === "short" ? "short" : "long";
350
- const formatter = getUnitFormatter(locale, unit.intlUnit, unitDisplay);
351
- result += formatter.format(value);
352
- continue;
353
- }
354
- if (piece.form === "short") {
355
- result += value + (value === 1 || value === -1 ? unit.shortSingular : unit.shortPlural);
356
- } else {
357
- result += value + " " + (value === 1 || value === -1 ? unit.longSingular : unit.longPlural);
358
- }
359
- }
360
- return result;
361
- }
362
-
363
- // src/duration.ts
364
- function formatDurationToParts(duration, formatStr, options = {}) {
365
- const full = formatDuration(duration, formatStr, options);
366
- const tokens = tokenizeDurationFormat(formatStr);
367
- const parts = [];
368
- let pos = 0;
369
- for (const tok of tokens) {
370
- if (tok.kind === "literal") {
371
- const lit = tok.value;
372
- if (full.slice(pos, pos + lit.length) === lit) {
373
- parts.push({ type: "literal", value: lit });
374
- pos += lit.length;
375
- /* c8 ignore start @preserve -- unreachable given current formatDuration(): every
376
- literal is appended to `full` unconditionally regardless of adjacent
377
- zero-value tokens, and pos tracking never desyncs from the true
378
- literal position (verified via adversarial testing: duplicate
379
- literals, skipped tokens before/after, ambiguous text — all still
380
- found via indexOf as expected). Kept as a guard against a future
381
- formatDuration() change that conditionally drops literals. */
382
- } else {
383
- }
384
- /* c8 ignore stop @preserve */
385
- } else {
386
- const nextLiteralStart = findNextLiteralStart(tokens, tok, full, pos);
387
- const value = full.slice(pos, nextLiteralStart);
388
- parts.push({ type: "token", value, token: tok.value });
389
- pos = nextLiteralStart;
390
- }
391
- }
392
- return parts;
393
- }
394
- function tokenizeDurationFormat(formatStr) {
395
- const DURATION_TOKEN_STRINGS2 = ["y", "o", "w", "d", "h", "m", "s", "S"].flatMap((single) => [single + single + single, single + single, single]).sort((a, b) => b.length - a.length);
396
- const pieces = [];
397
- let i = 0;
398
- while (i < formatStr.length) {
399
- const ch = formatStr[i];
400
- if (ch === "'") {
401
- if (formatStr[i + 1] === "'") {
402
- appendLiteral2(pieces, "'");
403
- i += 2;
404
- continue;
405
- }
406
- let j = i + 1;
407
- let literal = "";
408
- let closed = false;
409
- while (j < formatStr.length) {
410
- if (formatStr[j] === "'") {
411
- if (formatStr[j + 1] === "'") {
412
- literal += "'";
413
- j += 2;
414
- continue;
415
- }
416
- closed = true;
417
- j += 1;
418
- break;
419
- }
420
- literal += formatStr[j];
421
- j += 1;
422
- }
423
- if (!closed) throw new FormatSyntaxError({ format: formatStr, reason: "unterminated quote" });
424
- appendLiteral2(pieces, literal);
425
- i = j;
426
- continue;
427
- }
428
- const match = DURATION_TOKEN_STRINGS2.find((tok) => formatStr.startsWith(tok, i));
429
- if (match) {
430
- pieces.push({ kind: "token", value: match, unit: match[0] });
431
- i += match.length;
432
- continue;
433
- }
434
- appendLiteral2(pieces, ch);
435
- i += 1;
436
- }
437
- return pieces;
438
- }
439
- function appendLiteral2(pieces, value) {
440
- const last = pieces[pieces.length - 1];
441
- if (last && last.kind === "literal") {
442
- last.value += value;
443
- } else {
444
- pieces.push({ kind: "literal", value });
445
- }
446
- }
447
- function findNextLiteralStart(tokens, _currentTok, full, pos) {
448
- const idx = tokens.indexOf(_currentTok);
449
- for (let j = idx + 1; j < tokens.length; j++) {
450
- const t = tokens[j];
451
- if (t.kind === "literal") {
452
- const found = full.indexOf(t.value, pos);
453
- if (found >= 0) return found;
454
- }
455
- }
456
- return full.length;
457
- }
458
- function parseISODuration(input) {
459
- const re = /^P(?:(?:(\d+(?:\.\d+)?)Y)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)W)?(?:(\d+(?:\.\d+)?)D)?)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/;
460
- const m = re.exec(input);
461
- if (!m) {
462
- throw new InvalidDurationError({ input, reason: "does not match ISO 8601 duration grammar (P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S)" });
463
- }
464
- if (m.slice(1).every((g) => g === void 0)) {
465
- throw new InvalidDurationError({ input, reason: 'duration has no fields (use "P0D" for zero duration)' });
466
- }
467
- const toNum = (s) => s === void 0 ? 0 : Number(s);
468
- return {
469
- years: toNum(m[1]),
470
- months: toNum(m[2]),
471
- weeks: toNum(m[3]),
472
- days: toNum(m[4]),
473
- hours: toNum(m[5]),
474
- minutes: toNum(m[6]),
475
- seconds: toNum(m[7])
476
- };
477
- }
478
- function formatISODuration(duration) {
479
- const parts = ["P"];
480
- const years = duration.years ?? 0;
481
- const months = duration.months ?? 0;
482
- const weeks = duration.weeks ?? 0;
483
- const days = duration.days ?? 0;
484
- const hours = duration.hours ?? 0;
485
- const minutes = duration.minutes ?? 0;
486
- const seconds = duration.seconds ?? 0;
487
- if (years) parts.push(`${years}Y`);
488
- if (months) parts.push(`${months}M`);
489
- if (weeks) parts.push(`${weeks}W`);
490
- if (days) parts.push(`${days}D`);
491
- if (hours || minutes || seconds) {
492
- parts.push("T");
493
- if (hours) parts.push(`${hours}H`);
494
- if (minutes) parts.push(`${minutes}M`);
495
- if (seconds) parts.push(`${seconds}S`);
496
- }
497
- if (parts.length === 1) parts.push("0D");
498
- return parts.join("");
499
- }
500
- function parseDuration(input, formatStr, options = {}) {
501
- const tokens = tokenizeDurationFormat(formatStr);
502
- const fields = {};
503
- const groupSpecs = [];
504
- let regex = "";
505
- for (const tok of tokens) {
506
- if (tok.kind === "literal") {
507
- regex += tok.value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
508
- } else {
509
- const unit = tok.unit;
510
- const form = tok.value.length === 1 ? "numeric" : tok.value.length === 2 ? "short" : "long";
511
- /* c8 ignore start @preserve -- the final `: null` branch, and the
512
- `if (key === null)` throw it feeds, are both unreachable: tok.unit
513
- is always one of the 8 letters in DURATION_TOKEN_STRINGS (the same
514
- source set this ternary checks against), so `null` can't be
515
- produced by any token the tokenizer emits. Kept as a guard against
516
- a future letter being added to one set without the other. */
517
- const key = unit === "y" ? "years" : unit === "o" ? "months" : unit === "w" ? "weeks" : unit === "d" ? "days" : unit === "h" ? "hours" : unit === "m" ? "minutes" : unit === "s" ? "seconds" : unit === "S" ? "milliseconds" : null;
518
- if (key === null) {
519
- throw new FormatSyntaxError({ format: formatStr, token: tok.value, reason: "unknown duration token" });
520
- }
521
- /* c8 ignore stop @preserve */
522
- if (form === "numeric") {
523
- regex += "(-?\\d+)";
524
- } else {
525
- regex += "(\\d+)\\s*\\w*";
526
- }
527
- groupSpecs.push({ unit: key, form });
528
- }
529
- }
530
- const re = new RegExp(`^${regex}$`, "u");
531
- const m = re.exec(input);
532
- if (!m) {
533
- throw new FormatSyntaxError({ input, format: formatStr, reason: "does not match duration format" });
534
- }
535
- groupSpecs.forEach((spec, i) => {
536
- const raw = m[i + 1];
537
- const value = Number(raw);
538
- if (!Number.isFinite(value)) {
539
- throw new InvalidDurationError({ input, reason: `token for ${spec.unit} matched "${raw}" but isn't a finite number` });
540
- }
541
- fields[spec.unit] = value;
542
- });
543
- return fields;
544
- }
545
- function balanceDuration(duration) {
546
- const NS_PER = [
547
- ["days", 86400n * 1000000000n],
548
- ["hours", 3600n * 1000000000n],
549
- ["minutes", 60n * 1000000000n],
550
- ["seconds", 1000000000n],
551
- ["milliseconds", 1000000n],
552
- ["microseconds", 1000n],
553
- ["nanoseconds", 1n]
554
- ];
555
- let totalNs = 0n;
556
- for (const [k, nsPer] of NS_PER) {
557
- const v = duration[k];
558
- if (typeof v === "number") totalNs += BigInt(v) * nsPer;
559
- }
560
- const result = { ...duration };
561
- let remaining = totalNs;
562
- for (const [k, nsPer] of NS_PER) {
563
- const count = remaining / nsPer;
564
- remaining -= count * nsPer;
565
- result[k] = Number(count);
566
- }
567
- return result;
568
- }
569
- function totalDuration(duration, unit) {
570
- const NS_PER = {
571
- days: 86400n * 1000000000n,
572
- hours: 3600n * 1000000000n,
573
- minutes: 60n * 1000000000n,
574
- seconds: 1000000000n,
575
- milliseconds: 1000000n,
576
- microseconds: 1000n,
577
- nanoseconds: 1n
578
- };
579
- let totalNs = 0n;
580
- for (const k of Object.keys(NS_PER)) {
581
- const v = duration[k];
582
- if (typeof v === "number") totalNs += BigInt(v) * NS_PER[k];
583
- }
584
- const divisor = NS_PER[unit];
585
- if (!divisor) {
586
- throw new InvalidDurationError({ reason: `totalDuration() does not support unit "${unit}" (calendar-bound units need a relativeTo)` });
587
- }
588
- return Number(totalNs) / Number(divisor);
589
- }
590
- function compareDuration(a, b) {
591
- const aNs = totalDurationNs(a);
592
- const bNs = totalDurationNs(b);
593
- if (aNs < bNs) return -1;
594
- if (aNs > bNs) return 1;
595
- return 0;
596
- }
597
- function totalDurationNs(d) {
598
- const NS_PER = {
599
- days: 86400n * 1000000000n,
600
- hours: 3600n * 1000000000n,
601
- minutes: 60n * 1000000000n,
602
- seconds: 1000000000n,
603
- milliseconds: 1000000n,
604
- microseconds: 1000n,
605
- nanoseconds: 1n
606
- };
607
- let total = 0n;
608
- for (const k of Object.keys(NS_PER)) {
609
- const v = d[k];
610
- if (typeof v === "number") total += BigInt(v) * NS_PER[k];
611
- }
612
- return total;
613
- }
614
- function addDuration(a, b) {
615
- const keys = ["years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds", "microseconds", "nanoseconds"];
616
- const result = {};
617
- for (const k of keys) {
618
- result[k] = (a[k] ?? 0) + (b[k] ?? 0);
619
- }
620
- return result;
621
- }
622
- function subtractDuration(a, b) {
623
- return addDuration(a, negateDuration(b));
624
- }
625
- function negateDuration(d) {
626
- const result = {};
627
- for (const k of Object.keys(d)) {
628
- result[k] = -(d[k] ?? 0);
629
- }
630
- return result;
631
- }
632
- // Annotate the CommonJS export names for ESM import in node:
633
- 0 && (module.exports = {
634
- addDuration,
635
- balanceDuration,
636
- compareDuration,
637
- formatDurationToParts,
638
- formatISODuration,
639
- parseDuration,
640
- parseISODuration,
641
- roundDuration,
642
- subtractDuration,
643
- totalDuration
644
- });
23
+ parameter that could be invalid. *//* c8 ignore stop @preserve */var b=class extends p{constructor(t){let{message:n,...o}=t;super(n??`locale "${t.actual??""}" is not a valid BCP-47 tag${t.reason?`: ${t.reason}`:""}.`,{code:"INVALID_LOCALE",...o}),this.name="InvalidLocaleError"}},g=class extends p{constructor(t){let{message:n,...o}=t;super(n??`duration is invalid${t.reason?`: ${t.reason}`:""}.`,{code:"INVALID_DURATION",...o}),this.name="InvalidDurationError"}};/* c8 ignore start @preserve -- unreachable from the current test suite,
24
+ see rationale above *//* c8 ignore stop @preserve */function y(e,t,n){if(Number.isInteger(e))return BigInt(e)*t;let o=e*Number(t);if(Number.isSafeInteger(o))return BigInt(o);throw new g({reason:`field "${n}" (${e}) cannot be converted to nanoseconds exactly \u2014 the value is too large for a fractional unit; use smaller units`})}var E={years:0n,months:0n,weeks:0n,days:86400n*1000000000n,hours:3600n*1000000000n,minutes:60n*1000000000n,seconds:1000000000n,milliseconds:1000000n,microseconds:1000n,nanoseconds:1n};function q(e){return e==="years"||e==="months"||e==="weeks"}function A(e,t){let n=t.mode??"nearest",o=BigInt(t.roundingIncrement??1);if(o<=0n)throw new Error(`temporal-fmt: roundDuration() requires a positive roundingIncrement (got ${t.roundingIncrement}).`);if(q(t.unit))throw new Error(`temporal-fmt: roundDuration() to "${t.unit}" requires a Temporal.Duration with a relativeTo \u2014 this helper operates on plain field bags without calendar context. Use Temporal.Duration.prototype.round() directly.`);let r=0n;for(let d of["days","hours","minutes","seconds","milliseconds","microseconds","nanoseconds"]){let _=e[d]??0;r+=y(_,E[d],d)}let s=o*E[t.unit],i=r<0n?-1n:1n,u=r<0n?-r:r,a=u/s,l=u%s,c;switch(n){case"nearest":c=l*2n>=s?a+1n:a;break;case"floor":c=a;break;case"ceil":c=l>0n?a+1n:a;break;case"trunc":c=a;break}let h=i*c*s,m={...e},I=h,D=["days","hours","minutes","seconds","milliseconds","microseconds","nanoseconds"],N=D.indexOf(t.unit);for(let d=N+1;d<D.length;d++)m[D[d]]=0;for(let d=0;d<=N;d++){let _=D[d],F=E[_];if(F===0n)continue;let x=I/F;I-=x*F,m[_]=Number(x)}return m}function L(e){return e.replace(/_/g,"-")}var w=new Map,B=500;function P(e){let t=w.get(e);if(t!==void 0)return t;let n;try{n=new Intl.Locale(e.replace(/_/g,"-")).toString().toLowerCase()}catch{n=e}if(w.size>=B){let o=w.keys().next().value;o!==void 0&&w.delete(o)}return w.set(e,n),n}var S={y:{longSingular:"year",longPlural:"years",shortSingular:"yr",shortPlural:"yrs",field:"years",intlUnit:"year"},o:{longSingular:"month",longPlural:"months",shortSingular:"mo",shortPlural:"mos",field:"months",intlUnit:"month"},w:{longSingular:"week",longPlural:"weeks",shortSingular:"wk",shortPlural:"wks",field:"weeks",intlUnit:"week"},d:{longSingular:"day",longPlural:"days",shortSingular:"d",shortPlural:"d",field:"days",intlUnit:"day"},h:{longSingular:"hour",longPlural:"hours",shortSingular:"h",shortPlural:"h",field:"hours",intlUnit:"hour"},m:{longSingular:"minute",longPlural:"minutes",shortSingular:"m",shortPlural:"m",field:"minutes",intlUnit:"minute"},s:{longSingular:"second",longPlural:"seconds",shortSingular:"s",shortPlural:"s",field:"seconds",intlUnit:"second"},S:{longSingular:"millisecond",longPlural:"milliseconds",shortSingular:"ms",shortPlural:"ms",field:"milliseconds",intlUnit:"millisecond"}},j=Object.keys(S).flatMap(e=>[e+e+e,e+e,e]).sort((e,t)=>t.length-e.length);function X(e){let t=[],n=0;for(;n<e.length;){let o=e[n];if(o==="'"){if(e[n+1]==="'"){M(t,"'"),n+=2;continue}let s=n+1,i="",u=!1;for(;s<e.length;){if(e[s]==="'"){if(e[s+1]==="'"){i+="'",s+=2;continue}u=!0,s+=1;break}i+=e[s],s+=1}if(!u)throw new Error(`temporal-fmt: unterminated quote in duration format string "${e}"`);M(t,i),n=s;continue}let r=j.find(s=>e.startsWith(s,n));if(r){let s=r[0],i=r.length===1?"numeric":r.length===2?"short":"long";t.push({kind:"token",value:r,unit:s,form:i}),n+=r.length;continue}M(t,o),n+=1}return t}function M(e,t){let n=e[e.length-1];n&&n.kind==="literal"?n.value+=t:e.push({kind:"literal",value:t})}function G(e,t){let n=e[t];if(n==null)return 0;if(typeof n=="number"&&Number.isFinite(n))return n;let o=Number(n);if(!Number.isFinite(o))throw new Error(`temporal-fmt: duration field "${t}" is not a finite number (got ${String(n)}).`);return o}var k=new Map,Y=200;function W(e,t,n){let o=`${P(e)}|${t}|${n}`,r=k.get(o);if(r)return r;if(k.size>=Y){let i=k.keys().next().value;i!==void 0&&k.delete(i)}let s;try{s=new Intl.NumberFormat(L(e),{style:"unit",unit:t,unitDisplay:n})}catch(i){throw new b({actual:e,reason:i.message})}return k.set(o,s),s}function O(e,t,n={}){if(t.length>1e3)throw new Error(`temporal-fmt: duration format string exceeds maximum length of ${1e3} characters (got ${t.length}).`);let o=n.showZeroValues===!0,r=n.locale,s=r!==void 0,i=X(t),u=[];for(let a of i){if(a.kind==="literal"){u.push({kind:"literal",value:a.value});continue}let l=S[a.unit];if(!l)throw new Error(`temporal-fmt: unknown duration token "${a.value}"`);let c=G(e,l.field);if(c===0&&!o){u.push({kind:"token",value:"",token:a.value});continue}if(a.form==="numeric"){u.push({kind:"token",value:String(c),token:a.value});continue}if(s){let h=a.form==="short"?"short":"long",m=W(r,l.intlUnit,h);u.push({kind:"token",value:m.format(c),token:a.value});continue}a.form==="short"?u.push({kind:"token",value:c+(c===1||c===-1?l.shortSingular:l.shortPlural),token:a.value}):u.push({kind:"token",value:c+" "+(c===1||c===-1?l.longSingular:l.longPlural),token:a.value})}return u}function J(e,t,n={}){return O(e,t,n).map(o=>o.kind==="token"?{type:"token",value:o.value,token:o.token}:{type:"literal",value:o.value})}function Q(e){let n=/^P(?:(?:(\d+(?:\.\d+)?)Y)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)W)?(?:(\d+(?:\.\d+)?)D)?)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/.exec(e);if(!n)throw new g({input:e,reason:"does not match ISO 8601 duration grammar (P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S)"});if(n.slice(1).every(r=>r===void 0))throw new g({input:e,reason:'duration has no fields (use "P0D" for zero duration)'});let o=r=>r===void 0?0:Number(r);return{years:o(n[1]),months:o(n[2]),weeks:o(n[3]),days:o(n[4]),hours:o(n[5]),minutes:o(n[6]),seconds:o(n[7])}}function ee(e){let t=["P"],n=e.years??0,o=e.months??0,r=e.weeks??0,s=e.days??0,i=e.hours??0,u=e.minutes??0,a=e.seconds??0;return n&&t.push(`${n}Y`),o&&t.push(`${o}M`),r&&t.push(`${r}W`),s&&t.push(`${s}D`),(i||u||a)&&(t.push("T"),i&&t.push(`${i}H`),u&&t.push(`${u}M`),a&&t.push(`${a}S`)),t.length===1&&t.push("0D"),t.join("")}function te(e){let t=["y","o","w","d","h","m","s","S"].flatMap(r=>[r+r+r,r+r,r]).sort((r,s)=>s.length-r.length),n=[],o=0;for(;o<e.length;){let r=e[o];if(r==="'"){if(e[o+1]==="'"){$(n,"'"),o+=2;continue}let i=o+1,u="",a=!1;for(;i<e.length;){if(e[i]==="'"){if(e[i+1]==="'"){u+="'",i+=2;continue}a=!0,i+=1;break}u+=e[i],i+=1}if(!a)throw new f({format:e,reason:"unterminated quote"});$(n,u),o=i;continue}let s=t.find(i=>e.startsWith(i,o));if(s){n.push({kind:"token",value:s,unit:s[0]}),o+=s.length;continue}$(n,r),o+=1}return n}function $(e,t){let n=e[e.length-1];n&&n.kind==="literal"?n.value+=t:e.push({kind:"literal",value:t})}function ne(e,t,n={}){let o=te(t),r={},s=[],i="";for(let l of o)if(l.kind==="literal")i+=l.value.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");else{let c=l.unit,h=l.value.length===1?"numeric":l.value.length===2?"short":"long";/* c8 ignore start @preserve -- the final `: null` branch, and the
25
+ `if (key === null)` throw it feeds, are both unreachable: tok.unit
26
+ is always one of the 8 letters in DURATION_TOKEN_STRINGS (the same
27
+ source set this ternary checks against), so `null` can't be
28
+ produced by any token the tokenizer emits. Kept as a guard against
29
+ a future letter being added to one set without the other. */let m=c==="y"?"years":c==="o"?"months":c==="w"?"weeks":c==="d"?"days":c==="h"?"hours":c==="m"?"minutes":c==="s"?"seconds":c==="S"?"milliseconds":null;if(m===null)throw new f({format:t,token:l.value,reason:"unknown duration token"});/* c8 ignore stop @preserve */h==="numeric"?i+="(-?\\d+)":i+="(\\d+)\\s*\\w*",s.push({unit:m,form:h})}let a=new RegExp(`^${i}$`,"u").exec(e);if(!a)throw new f({input:e,format:t,reason:"does not match duration format"});return s.forEach((l,c)=>{let h=a[c+1],m=Number(h);if(!Number.isFinite(m))throw new g({input:e,reason:`token for ${l.unit} matched "${h}" but isn't a finite number`});r[l.unit]=m}),r}function oe(e){let t=[["days",86400n*1000000000n],["hours",3600n*1000000000n],["minutes",60n*1000000000n],["seconds",1000000000n],["milliseconds",1000000n],["microseconds",1000n],["nanoseconds",1n]],n=0n;for(let[s,i]of t){let u=e[s];typeof u=="number"&&(n+=y(u,i,s))}let o={...e},r=n;for(let[s,i]of t){let u=r/i;r-=u*i,o[s]=Number(u)}return o}function re(e,t){let n={days:86400n*1000000000n,hours:3600n*1000000000n,minutes:60n*1000000000n,seconds:1000000000n,milliseconds:1000000n,microseconds:1000n,nanoseconds:1n},o=0n;for(let s of Object.keys(n)){let i=e[s];typeof i=="number"&&(o+=y(i,n[s],s))}let r=n[t];if(!r)throw new g({reason:`totalDuration() does not support unit "${t}" (calendar-bound units need a relativeTo)`});return Number(o)/Number(r)}function se(e,t){let n=V(e),o=V(t);return n<o?-1:n>o?1:0}function V(e){let t={days:86400n*1000000000n,hours:3600n*1000000000n,minutes:60n*1000000000n,seconds:1000000000n,milliseconds:1000000n,microseconds:1000n,nanoseconds:1n},n=0n;for(let o of Object.keys(t)){let r=e[o];typeof r=="number"&&(n+=y(r,t[o],o))}return n}function v(e,t){let n=["years","months","weeks","days","hours","minutes","seconds","milliseconds","microseconds","nanoseconds"],o={};for(let r of n)o[r]=(e[r]??0)+(t[r]??0);return o}function ie(e,t){return v(e,ae(t))}function ae(e){let t={};for(let n of Object.keys(e))t[n]=-(e[n]??0);return t}0&&(module.exports={addDuration,balanceDuration,compareDuration,formatDurationToParts,formatISODuration,parseDuration,parseISODuration,roundDuration,subtractDuration,totalDuration});
645
30
  //# sourceMappingURL=duration.cjs.map