temporal-fmt 0.9.71 → 0.9.81
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +304 -528
- package/dist/chunk-6FPOCDZV.js +129 -0
- package/dist/chunk-6FPOCDZV.js.map +1 -0
- package/dist/{chunk-CQJYB7E7.js → chunk-ACGCGXP5.js} +4 -10
- package/dist/chunk-ACGCGXP5.js.map +1 -0
- package/dist/chunk-E4DD23HH.js +241 -0
- package/dist/chunk-E4DD23HH.js.map +1 -0
- package/dist/{chunk-MXXTJ5CW.js → chunk-EEPLAE3H.js} +5 -3
- package/dist/{chunk-ZT3UXRAA.js → chunk-EXIJZ4JG.js} +3 -8
- package/dist/chunk-EXIJZ4JG.js.map +1 -0
- package/dist/{chunk-BQET6RUR.js → chunk-GRBQ5FRO.js} +6 -23
- package/dist/{chunk-BQET6RUR.js.map → chunk-GRBQ5FRO.js.map} +1 -1
- package/dist/{chunk-3FMUGYE2.js → chunk-KV6GMX4D.js} +4 -159
- package/dist/chunk-KV6GMX4D.js.map +1 -0
- package/dist/{chunk-3SC5AVSY.js → chunk-TDQYKYVJ.js} +5 -5
- package/dist/chunk-UGYSEYUQ.js +168 -0
- package/dist/chunk-UGYSEYUQ.js.map +1 -0
- package/dist/{chunk-LHR5PCP4.js → chunk-UYKKGBZ3.js} +7 -7
- package/dist/{chunk-64UB3WDT.js → chunk-YQGUTK4E.js} +4 -4
- package/dist/duration.js +3 -3
- package/dist/format.cjs +0 -17
- package/dist/format.cjs.map +1 -1
- package/dist/format.js +4 -4
- package/dist/index.cjs +3908 -4671
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -103
- package/dist/index.d.ts +21 -103
- package/dist/index.js +2474 -893
- package/dist/index.js.map +1 -1
- package/dist/interval.cjs +106 -4773
- package/dist/interval.cjs.map +1 -1
- package/dist/interval.js +7 -12
- package/dist/legacy/index.d.cts +23 -0
- package/dist/legacy/index.d.ts +23 -0
- package/dist/legacy/matchesFormat.d.cts +6 -0
- package/dist/legacy/matchesFormat.d.ts +6 -0
- package/dist/legacy.cjs +2153 -0
- package/dist/legacy.cjs.map +1 -0
- package/dist/legacy.d.cts +1 -0
- package/dist/legacy.d.ts +1 -0
- package/dist/legacy.js +31 -0
- package/dist/legacy.js.map +1 -0
- package/dist/parse.cjs +0 -13
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +4 -4
- package/dist/recurrence.js +2 -1
- package/dist/relativeTime.cjs.map +1 -1
- package/dist/relativeTime.js +4 -4
- package/dist/timezone.js +2 -2
- package/dist/tokens.d.cts +0 -4
- package/dist/tokens.d.ts +0 -4
- package/legacy.d.cts +1 -0
- package/legacy.d.ts +1 -0
- package/package.json +17 -21
- package/MODS.md +0 -148
- package/dist/chunk-3FMUGYE2.js.map +0 -1
- package/dist/chunk-CQJYB7E7.js.map +0 -1
- package/dist/chunk-ZT3UXRAA.js.map +0 -1
- package/dist/chunk-ZTIF4ZHX.js +0 -3041
- package/dist/chunk-ZTIF4ZHX.js.map +0 -1
- package/dist/modApi.d.cts +0 -147
- package/dist/modApi.d.ts +0 -147
- package/dist/runtime.d.cts +0 -206
- package/dist/runtime.d.ts +0 -206
- package/scripts/cli.mjs +0 -324
- package/scripts/loadMods.d.mts +0 -37
- package/scripts/loadMods.mjs +0 -801
- package/scripts/managePermissions.mjs +0 -126
- package/scripts/modConfig.mjs +0 -96
- package/scripts/modSandbox.d.mts +0 -13
- package/scripts/modSandbox.mjs +0 -855
- package/scripts/modWire.mjs +0 -241
- package/scripts/modWorker.mjs +0 -574
- package/scripts/semverRange.mjs +0 -157
- package/scripts/versions.json +0 -42
- /package/dist/{chunk-MXXTJ5CW.js.map → chunk-EEPLAE3H.js.map} +0 -0
- /package/dist/{chunk-3SC5AVSY.js.map → chunk-TDQYKYVJ.js.map} +0 -0
- /package/dist/{chunk-LHR5PCP4.js.map → chunk-UYKKGBZ3.js.map} +0 -0
- /package/dist/{chunk-64UB3WDT.js.map → chunk-YQGUTK4E.js.map} +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
compileFormat,
|
|
3
|
+
format,
|
|
4
|
+
formatToParts
|
|
5
|
+
} from "./chunk-ACGCGXP5.js";
|
|
6
|
+
import {
|
|
7
|
+
buildCapturingPattern,
|
|
8
|
+
compileParser,
|
|
9
|
+
enumerateValidSplits,
|
|
10
|
+
parse,
|
|
11
|
+
parseToParts,
|
|
12
|
+
safeParse,
|
|
13
|
+
tryParse
|
|
14
|
+
} from "./chunk-EEPLAE3H.js";
|
|
15
|
+
import {
|
|
16
|
+
tokenize
|
|
17
|
+
} from "./chunk-EXIJZ4JG.js";
|
|
18
|
+
import {
|
|
19
|
+
DEFAULT_LOCALE
|
|
20
|
+
} from "./chunk-GRBQ5FRO.js";
|
|
21
|
+
import {
|
|
22
|
+
MAX_FORMAT_LENGTH
|
|
23
|
+
} from "./chunk-SOPTTXUI.js";
|
|
24
|
+
import {
|
|
25
|
+
TemporalFmtError
|
|
26
|
+
} from "./chunk-QRLQ7RR7.js";
|
|
27
|
+
|
|
28
|
+
// src/legacy/matchesFormat.ts
|
|
29
|
+
var patternCache = /* @__PURE__ */ new Map();
|
|
30
|
+
var MAX_CACHE_SIZE = 500;
|
|
31
|
+
function getPattern(formatStr, locale) {
|
|
32
|
+
const key = locale + "\0" + formatStr;
|
|
33
|
+
const cached = patternCache.get(key);
|
|
34
|
+
if (cached) return cached;
|
|
35
|
+
if (patternCache.size >= MAX_CACHE_SIZE) {
|
|
36
|
+
const oldestKey = patternCache.keys().next().value;
|
|
37
|
+
if (oldestKey !== void 0) patternCache.delete(oldestKey);
|
|
38
|
+
}
|
|
39
|
+
const pattern = buildCapturingPattern(tokenize(formatStr), locale);
|
|
40
|
+
patternCache.set(key, pattern);
|
|
41
|
+
return pattern;
|
|
42
|
+
}
|
|
43
|
+
function matchesFormat(formatStr, input, options = {}) {
|
|
44
|
+
try {
|
|
45
|
+
if (formatStr.length > MAX_FORMAT_LENGTH) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters (got ${formatStr.length}).`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const locale = options.locale ?? DEFAULT_LOCALE;
|
|
51
|
+
const pattern = getPattern(formatStr, locale);
|
|
52
|
+
const match = pattern.regex.exec(input);
|
|
53
|
+
if (!match) return false;
|
|
54
|
+
for (const run of pattern.ambiguousRuns) {
|
|
55
|
+
const range = match.indices?.groups?.[run.groupName];
|
|
56
|
+
if (!range || enumerateValidSplits(input.slice(range[0], range[1]), run.tokens).length === 0) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return true;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (error instanceof TemporalFmtError) throw new Error(error.message);
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/legacy/index.ts
|
|
68
|
+
function withLegacyErrors(operation) {
|
|
69
|
+
try {
|
|
70
|
+
return operation();
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (error instanceof TemporalFmtError) {
|
|
73
|
+
throw new Error(error.message);
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function toLegacySafeParseResult(result) {
|
|
79
|
+
return result.ok ? result : { ok: false, error: new Error(result.error.message) };
|
|
80
|
+
}
|
|
81
|
+
function format2(temporal, formatStr, options = {}) {
|
|
82
|
+
return withLegacyErrors(() => format(temporal, formatStr, options));
|
|
83
|
+
}
|
|
84
|
+
function formatToParts2(temporal, formatStr, options = {}) {
|
|
85
|
+
return withLegacyErrors(() => formatToParts(temporal, formatStr, options));
|
|
86
|
+
}
|
|
87
|
+
function compileFormat2(formatStr) {
|
|
88
|
+
const compiled = withLegacyErrors(() => compileFormat(formatStr));
|
|
89
|
+
return {
|
|
90
|
+
...compiled,
|
|
91
|
+
format: (temporal, options) => withLegacyErrors(() => compiled.format(temporal, options)),
|
|
92
|
+
formatToParts: (temporal, options) => withLegacyErrors(() => compiled.formatToParts(temporal, options))
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function parse2(formatStr, input, options = {}) {
|
|
96
|
+
return withLegacyErrors(() => parse(formatStr, input, options));
|
|
97
|
+
}
|
|
98
|
+
function safeParse2(formatStr, input, options = {}) {
|
|
99
|
+
return toLegacySafeParseResult(safeParse(formatStr, input, options));
|
|
100
|
+
}
|
|
101
|
+
function tryParse2(formatStr, input, options = {}) {
|
|
102
|
+
return tryParse(formatStr, input, options);
|
|
103
|
+
}
|
|
104
|
+
function parseToParts2(formatStr, input, options = {}) {
|
|
105
|
+
return withLegacyErrors(() => parseToParts(formatStr, input, options));
|
|
106
|
+
}
|
|
107
|
+
function compileParser2(formatStr, options = {}) {
|
|
108
|
+
const compiled = withLegacyErrors(() => compileParser(formatStr, options));
|
|
109
|
+
return {
|
|
110
|
+
...compiled,
|
|
111
|
+
parse: (input, callOptions) => withLegacyErrors(() => compiled.parse(input, callOptions)),
|
|
112
|
+
safeParse: (input, callOptions) => toLegacySafeParseResult(compiled.safeParse(input, callOptions)),
|
|
113
|
+
tryParse: (input, callOptions) => compiled.tryParse(input, callOptions),
|
|
114
|
+
parseToParts: (input, callOptions) => withLegacyErrors(() => compiled.parseToParts(input, callOptions))
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
matchesFormat,
|
|
120
|
+
format2 as format,
|
|
121
|
+
formatToParts2 as formatToParts,
|
|
122
|
+
compileFormat2 as compileFormat,
|
|
123
|
+
parse2 as parse,
|
|
124
|
+
safeParse2 as safeParse,
|
|
125
|
+
tryParse2 as tryParse,
|
|
126
|
+
parseToParts2 as parseToParts,
|
|
127
|
+
compileParser2 as compileParser
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=chunk-6FPOCDZV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/legacy/matchesFormat.ts","../src/legacy/index.ts"],"sourcesContent":["/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { DEFAULT_LOCALE, type FormatOptions } from '../tokens.js';\nimport { tokenize } from '../tokenize.js';\nimport { buildCapturingPattern, type CapturingPattern } from '../parsePattern.js';\nimport { MAX_FORMAT_LENGTH } from '../constants.js';\nimport { TemporalFmtError } from '../errors.js';\nimport { enumerateValidSplits } from '../pattern.js';\n\nconst patternCache = new Map<string, CapturingPattern>();\nconst MAX_CACHE_SIZE = 500;\n\nfunction getPattern(formatStr: string, locale: string) {\n const key = locale + '\\0' + formatStr;\n const cached = patternCache.get(key);\n if (cached) return cached;\n\n if (patternCache.size >= MAX_CACHE_SIZE) {\n const oldestKey = patternCache.keys().next().value;\n if (oldestKey !== undefined) patternCache.delete(oldestKey);\n }\n\n const pattern = buildCapturingPattern(tokenize(formatStr), locale);\n patternCache.set(key, pattern);\n return pattern;\n}\n\n/**\n * Checks whether `input` could plausibly be output from `format()` for the\n * given format. It checks shape and locale vocabulary, not date validity.\n */\nexport function matchesFormat(formatStr: string, input: string, options: FormatOptions = {}): boolean {\n try {\n if (formatStr.length > MAX_FORMAT_LENGTH) {\n throw new Error(\n `temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters ` +\n `(got ${formatStr.length}).`,\n );\n }\n const locale = options.locale ?? DEFAULT_LOCALE;\n const pattern = getPattern(formatStr, locale);\n const match = pattern.regex.exec(input);\n if (!match) return false;\n\n for (const run of pattern.ambiguousRuns) {\n const range = match.indices?.groups?.[run.groupName];\n if (!range || enumerateValidSplits(input.slice(range[0], range[1]), run.tokens).length === 0) {\n return false;\n }\n }\n return true;\n } catch (error) {\n if (error instanceof TemporalFmtError) throw new Error(error.message);\n throw error;\n }\n}\n","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n format as typedFormat,\n formatToParts as typedFormatToParts,\n compileFormat as typedCompileFormat,\n type CompiledFormat,\n type FormattedPart,\n} from '../format.js';\nimport {\n parse as typedParse,\n safeParse as typedSafeParse,\n tryParse as typedTryParse,\n parseToParts as typedParseToParts,\n compileParser as typedCompileParser,\n type CompiledParser,\n type ParsedPart,\n} from '../parse.js';\nimport type { TemporalLike } from '../tokens.js';\nimport type { NumberingFormatOptions, NumberingParseOptions } from '../numbering.js';\nimport { TemporalFmtError } from '../errors.js';\n\nexport type LegacySafeParseResult =\n | { ok: true; value: unknown }\n | { ok: false; error: Error };\n\nexport type LegacyCompiledParser = Omit<CompiledParser, 'safeParse'> & {\n safeParse(input: string, options?: NumberingParseOptions): LegacySafeParseResult;\n};\n\nfunction withLegacyErrors<T>(operation: () => T): T {\n try {\n return operation();\n } catch (error) {\n if (error instanceof TemporalFmtError) {\n throw new Error(error.message);\n }\n throw error;\n }\n}\n\nfunction toLegacySafeParseResult(result: ReturnType<typeof typedSafeParse>): LegacySafeParseResult {\n return result.ok\n ? result\n : { ok: false, error: new Error(result.error.message) };\n}\n\nexport function format(\n temporal: TemporalLike,\n formatStr: string,\n options: NumberingFormatOptions = {},\n): string {\n return withLegacyErrors(() => typedFormat(temporal, formatStr, options));\n}\n\nexport function formatToParts(\n temporal: TemporalLike,\n formatStr: string,\n options: NumberingFormatOptions = {},\n): FormattedPart[] {\n return withLegacyErrors(() => typedFormatToParts(temporal, formatStr, options));\n}\n\nexport function compileFormat(formatStr: string): CompiledFormat {\n const compiled = withLegacyErrors(() => typedCompileFormat(formatStr));\n return {\n ...compiled,\n format: (temporal, options) => withLegacyErrors(() => compiled.format(temporal, options)),\n formatToParts: (temporal, options) => withLegacyErrors(() => compiled.formatToParts(temporal, options)),\n };\n}\n\nexport function parse(formatStr: string, input: string, options: NumberingParseOptions = {}): unknown | undefined {\n return withLegacyErrors(() => typedParse(formatStr, input, options));\n}\n\nexport function safeParse(\n formatStr: string,\n input: string,\n options: NumberingParseOptions = {},\n): LegacySafeParseResult {\n return toLegacySafeParseResult(typedSafeParse(formatStr, input, options));\n}\n\nexport function tryParse(formatStr: string, input: string, options: NumberingParseOptions = {}): unknown | undefined {\n return typedTryParse(formatStr, input, options);\n}\n\nexport function parseToParts(\n formatStr: string,\n input: string,\n options: NumberingParseOptions = {},\n): ParsedPart[] {\n return withLegacyErrors(() => typedParseToParts(formatStr, input, options));\n}\n\nexport function compileParser(formatStr: string, options: NumberingParseOptions = {}): LegacyCompiledParser {\n const compiled = withLegacyErrors(() => typedCompileParser(formatStr, options));\n return {\n ...compiled,\n parse: (input, callOptions) => withLegacyErrors(() => compiled.parse(input, callOptions)),\n safeParse: (input, callOptions) => toLegacySafeParseResult(compiled.safeParse(input, callOptions)),\n tryParse: (input, callOptions) => compiled.tryParse(input, callOptions),\n parseToParts: (input, callOptions) => withLegacyErrors(() => compiled.parseToParts(input, callOptions)),\n };\n}\n\nexport { matchesFormat } from './matchesFormat.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAM,eAAe,oBAAI,IAA8B;AACvD,IAAM,iBAAiB;AAEvB,SAAS,WAAW,WAAmB,QAAgB;AACrD,QAAM,MAAM,SAAS,OAAO;AAC5B,QAAM,SAAS,aAAa,IAAI,GAAG;AACnC,MAAI,OAAQ,QAAO;AAEnB,MAAI,aAAa,QAAQ,gBAAgB;AACvC,UAAM,YAAY,aAAa,KAAK,EAAE,KAAK,EAAE;AAC7C,QAAI,cAAc,OAAW,cAAa,OAAO,SAAS;AAAA,EAC5D;AAEA,QAAM,UAAU,sBAAsB,SAAS,SAAS,GAAG,MAAM;AACjE,eAAa,IAAI,KAAK,OAAO;AAC7B,SAAO;AACT;AAMO,SAAS,cAAc,WAAmB,OAAe,UAAyB,CAAC,GAAY;AACpG,MAAI;AACF,QAAI,UAAU,SAAS,mBAAmB;AACxC,YAAM,IAAI;AAAA,QACR,yDAAyD,iBAAiB,oBAClE,UAAU,MAAM;AAAA,MAC1B;AAAA,IACF;AACA,UAAM,SAAS,QAAQ,UAAU;AACjC,UAAM,UAAU,WAAW,WAAW,MAAM;AAC5C,UAAM,QAAQ,QAAQ,MAAM,KAAK,KAAK;AACtC,QAAI,CAAC,MAAO,QAAO;AAEnB,eAAW,OAAO,QAAQ,eAAe;AACvC,YAAM,QAAQ,MAAM,SAAS,SAAS,IAAI,SAAS;AACnD,UAAI,CAAC,SAAS,qBAAqB,MAAM,MAAM,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,IAAI,MAAM,EAAE,WAAW,GAAG;AAC5F,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,iBAAkB,OAAM,IAAI,MAAM,MAAM,OAAO;AACpE,UAAM;AAAA,EACR;AACF;;;ACzBA,SAAS,iBAAoB,WAAuB;AAClD,MAAI;AACF,WAAO,UAAU;AAAA,EACnB,SAAS,OAAO;AACd,QAAI,iBAAiB,kBAAkB;AACrC,YAAM,IAAI,MAAM,MAAM,OAAO;AAAA,IAC/B;AACA,UAAM;AAAA,EACR;AACF;AAEA,SAAS,wBAAwB,QAAkE;AACjG,SAAO,OAAO,KACV,SACA,EAAE,IAAI,OAAO,OAAO,IAAI,MAAM,OAAO,MAAM,OAAO,EAAE;AAC1D;AAEO,SAASA,QACd,UACA,WACA,UAAkC,CAAC,GAC3B;AACR,SAAO,iBAAiB,MAAM,OAAY,UAAU,WAAW,OAAO,CAAC;AACzE;AAEO,SAASC,eACd,UACA,WACA,UAAkC,CAAC,GAClB;AACjB,SAAO,iBAAiB,MAAM,cAAmB,UAAU,WAAW,OAAO,CAAC;AAChF;AAEO,SAASC,eAAc,WAAmC;AAC/D,QAAM,WAAW,iBAAiB,MAAM,cAAmB,SAAS,CAAC;AACrE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,CAAC,UAAU,YAAY,iBAAiB,MAAM,SAAS,OAAO,UAAU,OAAO,CAAC;AAAA,IACxF,eAAe,CAAC,UAAU,YAAY,iBAAiB,MAAM,SAAS,cAAc,UAAU,OAAO,CAAC;AAAA,EACxG;AACF;AAEO,SAASC,OAAM,WAAmB,OAAe,UAAiC,CAAC,GAAwB;AAChH,SAAO,iBAAiB,MAAM,MAAW,WAAW,OAAO,OAAO,CAAC;AACrE;AAEO,SAASC,WACd,WACA,OACA,UAAiC,CAAC,GACX;AACvB,SAAO,wBAAwB,UAAe,WAAW,OAAO,OAAO,CAAC;AAC1E;AAEO,SAASC,UAAS,WAAmB,OAAe,UAAiC,CAAC,GAAwB;AACnH,SAAO,SAAc,WAAW,OAAO,OAAO;AAChD;AAEO,SAASC,cACd,WACA,OACA,UAAiC,CAAC,GACpB;AACd,SAAO,iBAAiB,MAAM,aAAkB,WAAW,OAAO,OAAO,CAAC;AAC5E;AAEO,SAASC,eAAc,WAAmB,UAAiC,CAAC,GAAyB;AAC1G,QAAM,WAAW,iBAAiB,MAAM,cAAmB,WAAW,OAAO,CAAC;AAC9E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,CAAC,OAAO,gBAAgB,iBAAiB,MAAM,SAAS,MAAM,OAAO,WAAW,CAAC;AAAA,IACxF,WAAW,CAAC,OAAO,gBAAgB,wBAAwB,SAAS,UAAU,OAAO,WAAW,CAAC;AAAA,IACjG,UAAU,CAAC,OAAO,gBAAgB,SAAS,SAAS,OAAO,WAAW;AAAA,IACtE,cAAc,CAAC,OAAO,gBAAgB,iBAAiB,MAAM,SAAS,aAAa,OAAO,WAAW,CAAC;AAAA,EACxG;AACF;","names":["format","formatToParts","compileFormat","parse","safeParse","tryParse","parseToParts","compileParser"]}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyNumbering,
|
|
3
3
|
tokenize
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EXIJZ4JG.js";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_LOCALE,
|
|
7
|
-
TOKENS
|
|
8
|
-
|
|
9
|
-
onTokenTableChange
|
|
10
|
-
} from "./chunk-BQET6RUR.js";
|
|
7
|
+
TOKENS
|
|
8
|
+
} from "./chunk-GRBQ5FRO.js";
|
|
11
9
|
import {
|
|
12
10
|
MAX_FORMAT_LENGTH
|
|
13
11
|
} from "./chunk-SOPTTXUI.js";
|
|
@@ -20,10 +18,6 @@ import {
|
|
|
20
18
|
var HANDLER_BY_TOKEN = new Map(TOKENS.map(([tok, fn, field]) => [tok, { fn, field }]));
|
|
21
19
|
var tokenizeCache = /* @__PURE__ */ new Map();
|
|
22
20
|
var MAX_TOKENIZE_CACHE_SIZE = 500;
|
|
23
|
-
onTokenTableChange(() => {
|
|
24
|
-
HANDLER_BY_TOKEN = new Map(getEffectiveTokens().map(([tok, fn, field]) => [tok, { fn, field }]));
|
|
25
|
-
tokenizeCache.clear();
|
|
26
|
-
});
|
|
27
21
|
function getPieces(formatStr) {
|
|
28
22
|
let pieces = tokenizeCache.get(formatStr);
|
|
29
23
|
if (pieces) return pieces;
|
|
@@ -195,4 +189,4 @@ export {
|
|
|
195
189
|
_getPieces,
|
|
196
190
|
_handlerFor
|
|
197
191
|
};
|
|
198
|
-
//# sourceMappingURL=chunk-
|
|
192
|
+
//# sourceMappingURL=chunk-ACGCGXP5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/format.ts"],"sourcesContent":["/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TOKENS, DEFAULT_LOCALE, type TemporalLike, type FormatOptions } from './tokens.js';\nimport { tokenize, type Piece } from './tokenize.js';\nimport { MAX_FORMAT_LENGTH } from './constants.js';\nimport { applyNumbering, type NumberingFormatOptions } from './numbering.js';\nimport { FormatSyntaxError, UnknownTokenError } from './errors.js';\n\nconst HANDLER_BY_TOKEN = new Map(TOKENS.map(([tok, fn, field]) => [tok, { fn, field }]));\n\n// Pre-tokenized format strings, keyed by (formatStr) — locale doesn't\n// change the tokenization step, only the per-token rendering, so the\n// piece list is shared across locales. Same eviction shape as the\n// other caches in this library.\nconst tokenizeCache = new Map<string, Piece[]>();\nconst MAX_TOKENIZE_CACHE_SIZE = 500;\n\nfunction getPieces(formatStr: string): Piece[] {\n let pieces = tokenizeCache.get(formatStr);\n if (pieces) return pieces;\n if (tokenizeCache.size >= MAX_TOKENIZE_CACHE_SIZE) {\n const oldestKey = tokenizeCache.keys().next().value;\n if (oldestKey !== undefined) tokenizeCache.delete(oldestKey);\n }\n pieces = tokenize(formatStr);\n // Deep-freeze before caching: the SAME array instance is handed out\n // by compileFormat().pieces and _getPieces() (documented as readonly\n // inspection surface). Read-only at the type level alone didn't stop\n // runtime mutation — a caller writing pieces[0].value used to poison\n // the shared cache and corrupt every subsequent format() for that\n // string process-wide. Frozen objects make the mutation attempt\n // throw (ESM is strict mode) instead of silently corrupting state.\n for (const piece of pieces) Object.freeze(piece);\n Object.freeze(pieces);\n tokenizeCache.set(formatStr, pieces);\n return pieces;\n}\n\n/**\n * Format a Temporal.PlainDate, PlainTime, PlainDateTime, or ZonedDateTime\n * using a date-fns-style token string.\n *\n * @example\n * format(Temporal.Now.plainDateISO(), 'yyyy-MM-dd') // \"2026-08-04\"\n * format(zdt, \"MMM d, yyyy 'at' h:mm a\") // \"Aug 4, 2026 at 3:45 PM\"\n * format(zdt, 'MMMM d, yyyy', { locale: 'fr-FR' }) // \"août 4, 2026\"\n *\n * Throws on a token the input type doesn't support (e.g. 'HH' on a PlainDate).\n */\nexport function format(temporal: TemporalLike, formatStr: string, options: NumberingFormatOptions = {}): string {\n if (formatStr.length > MAX_FORMAT_LENGTH) {\n throw new FormatSyntaxError({\n format: formatStr,\n message:\n `temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters ` +\n `(got ${formatStr.length}).`,\n });\n }\n // Null/undefined input used to leak a raw V8 TypeError from the\n // first field read (\"Cannot read properties of null (reading 'year')\")\n // — every other entry point validates its input with a typed error,\n // and null/undefined is by far the most common wrong input. A null\n // `options` object hits the same class (the default parameter only\n // covers undefined).\n if (temporal === null || temporal === undefined) {\n throw new FormatSyntaxError({\n input: String(temporal),\n reason: `format() expected a Temporal.PlainDate / PlainTime / PlainDateTime / ZonedDateTime (or a TemporalLike field bag), got ${String(temporal)}`,\n });\n }\n const opts = options ?? {};\n\n const locale = opts.locale ?? DEFAULT_LOCALE;\n const pieces = getPieces(formatStr);\n let result = '';\n\n for (const piece of pieces) {\n if (piece.kind === 'literal') {\n result += piece.value;\n continue;\n }\n\n const handler = HANDLER_BY_TOKEN.get(piece.value);\n /* c8 ignore start @preserve -- unreachable: tokenize() only ever emits\n tokens present in TOKENS, and HANDLER_BY_TOKEN is built from that\n same list, so every token piece.value can hold already has an entry\n here. Same defensive-guard category as the twin checks in\n analyze.ts/formatDuration.ts. */\n if (!handler) {\n throw new UnknownTokenError({ token: piece.value, format: formatStr, message: `temporal-fmt: unknown token \"${piece.value}\"` });\n }\n /* c8 ignore stop @preserve */\n\n if (temporal[handler.field] === undefined) {\n throw new FormatSyntaxError({\n format: formatStr,\n token: piece.value,\n message:\n `temporal-fmt: token \"${piece.value}\" requires \"${handler.field}\", ` +\n `which this Temporal object doesn't have. ` +\n `(e.g. PlainDate has no time fields, PlainTime has no date fields)`,\n });\n }\n\n result += handler.fn(temporal, locale);\n }\n\n // Numeral transliteration happens last and only on request — every\n // upstream token handler still emits plain ASCII digits, so this is\n // the single place output digits can diverge from that default.\n return applyNumbering(result, opts);\n}\n\n// Shape mirrors Intl.DateTimeFormat.formatToParts: each entry is either\n// a literal (carrying no token info) or a token piece (carrying the\n// token string and the formatted value). Letting callers iterate parts\n// means they can build custom output — strip a token, swap a separator,\n// render each token to its own DOM node — without re-implementing the\n// tokenizer or the field-check logic.\nexport interface FormattedPart {\n type: 'literal' | 'token';\n value: string;\n // Present when `type === 'token'`. Carries the token string (e.g. \"yyyy\")\n // so a caller can look up its metadata via tokenInfo() from analyze.ts.\n token?: string;\n}\n\nexport function formatToParts(temporal: TemporalLike, formatStr: string, options: NumberingFormatOptions = {}): FormattedPart[] {\n if (formatStr.length > MAX_FORMAT_LENGTH) {\n throw new FormatSyntaxError({\n format: formatStr,\n message:\n `temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters ` +\n `(got ${formatStr.length}).`,\n });\n }\n const locale = options.locale ?? DEFAULT_LOCALE;\n const pieces = getPieces(formatStr);\n const result: FormattedPart[] = [];\n for (const piece of pieces) {\n if (piece.kind === 'literal') {\n // Collapse adjacent literals so formatToParts stays consistent with\n // how format() walks pieces — a multi-char literal \"at \" is one\n // entry, not one per character. Same merge logic as appendLiteral\n // in tokenize.ts.\n const last = result[result.length - 1];\n /* c8 ignore start @preserve -- unreachable through tokenize()'s own\n output: appendLiteral() in tokenize.ts already merges every\n adjacent literal character before pieces ever reaches here, so\n two 'literal' pieces never sit back-to-back in the array this\n loop walks. Kept as defense-in-depth in case that invariant ever\n changes upstream. */\n if (last && last.type === 'literal') {\n last.value += piece.value;\n } else {\n /* c8 ignore stop @preserve */\n result.push({ type: 'literal', value: piece.value });\n }\n continue;\n }\n const handler = HANDLER_BY_TOKEN.get(piece.value);\n /* c8 ignore start @preserve -- unreachable, see the note in format() above */\n if (!handler) {\n throw new UnknownTokenError({ token: piece.value, format: formatStr, message: `temporal-fmt: unknown token \"${piece.value}\"` });\n }\n /* c8 ignore stop @preserve */\n if (temporal[handler.field] === undefined) {\n throw new FormatSyntaxError({\n format: formatStr,\n token: piece.value,\n message:\n `temporal-fmt: token \"${piece.value}\" requires \"${handler.field}\", ` +\n `which this Temporal object doesn't have. ` +\n `(e.g. PlainDate has no time fields, PlainTime has no date fields)`,\n });\n }\n // Numeral transliteration applies per-token-part here, rather than\n // once at the end like format() does, so a caller styling individual\n // parts (e.g. one <span> per token) still gets correctly-transliterated\n // digits in each part instead of plain ASCII.\n result.push({ type: 'token', value: applyNumbering(handler.fn(temporal, locale), options), token: piece.value });\n }\n return result;\n}\n\n// Pre-compiles a format string into an object whose format()/formatToParts()\n// methods skip the tokenization step on every call. The tokenizeCache in\n// this module means a plain format(temporal, fmt) call already pays only\n// a Map lookup for tokenization after the first call, so compileFormat()\n// is mostly a typing/ergonomics affordance — useful for callers who want\n// to hold onto a compiled form explicitly (e.g. to inspect the pieces\n// via the .pieces property, or to pass the compiled object around\n// instead of the string).\nexport interface CompiledFormat {\n format(temporal: TemporalLike, options?: NumberingFormatOptions): string;\n formatToParts(temporal: TemporalLike, options?: NumberingFormatOptions): FormattedPart[];\n readonly pieces: ReadonlyArray<Piece>;\n readonly formatStr: string;\n}\n\nexport function compileFormat(formatStr: string): CompiledFormat {\n if (formatStr.length > MAX_FORMAT_LENGTH) {\n throw new FormatSyntaxError({\n format: formatStr,\n message:\n `temporal-fmt: format string exceeds maximum length of ${MAX_FORMAT_LENGTH} characters ` +\n `(got ${formatStr.length}).`,\n });\n }\n // Pre-tokenize once. Validation (unknown tokens, unterminated quotes)\n // happens here, not lazily on first format() call — surfaces a bad\n // format string at compile time rather than at first use, which is\n // the point of compiling up front.\n const pieces = getPieces(formatStr);\n return {\n formatStr,\n pieces,\n format(temporal: TemporalLike, options: NumberingFormatOptions = {}) {\n const locale = options.locale ?? DEFAULT_LOCALE;\n let result = '';\n for (const piece of pieces) {\n if (piece.kind === 'literal') {\n result += piece.value;\n continue;\n }\n const handler = HANDLER_BY_TOKEN.get(piece.value);\n /* c8 ignore next -- unreachable, see the note in format() above */\n if (!handler) throw new UnknownTokenError({ token: piece.value, format: formatStr, message: `temporal-fmt: unknown token \"${piece.value}\"` });\n if (temporal[handler.field] === undefined) {\n throw new FormatSyntaxError({\n format: formatStr,\n token: piece.value,\n message:\n `temporal-fmt: token \"${piece.value}\" requires \"${handler.field}\", ` +\n `which this Temporal object doesn't have. ` +\n `(e.g. PlainDate has no time fields, PlainTime has no date fields)`,\n });\n }\n result += handler.fn(temporal, locale);\n }\n return applyNumbering(result, options);\n },\n formatToParts(temporal: TemporalLike, options: NumberingFormatOptions = {}) {\n const locale = options.locale ?? DEFAULT_LOCALE;\n const out: FormattedPart[] = [];\n for (const piece of pieces) {\n if (piece.kind === 'literal') {\n const last = out[out.length - 1];\n /* c8 ignore next -- unreachable, see the note in formatToParts() above */\n if (last && last.type === 'literal') last.value += piece.value;\n else out.push({ type: 'literal', value: piece.value });\n continue;\n }\n const handler = HANDLER_BY_TOKEN.get(piece.value);\n /* c8 ignore next -- unreachable, see the note in format() above */\n if (!handler) throw new UnknownTokenError({ token: piece.value, format: formatStr, message: `temporal-fmt: unknown token \"${piece.value}\"` });\n if (temporal[handler.field] === undefined) {\n throw new FormatSyntaxError({\n format: formatStr,\n token: piece.value,\n message:\n `temporal-fmt: token \"${piece.value}\" requires \"${handler.field}\", ` +\n `which this Temporal object doesn't have. ` +\n `(e.g. PlainDate has no time fields, PlainTime has no date fields)`,\n });\n }\n out.push({ type: 'token', value: applyNumbering(handler.fn(temporal, locale), options), token: piece.value });\n }\n return out;\n },\n };\n}\n\n// Exported so analyze.ts can reuse the same tokenization cache rather\n// than re-tokenizing when a caller asks for both a format() and an\n// analyzeFormat() on the same string.\nexport function _getPieces(formatStr: string): Piece[] {\n return getPieces(formatStr);\n}\n\n// Exported for analyze.ts — same reason as above. The handler map is\n// the source of truth for \"what field does this token need\" — analyze\n// consumes it to compute requiredFields and compatibleTypes.\nexport function _handlerFor(token: string): { fn: (t: TemporalLike, locale: string) => string; field: keyof TemporalLike } | undefined {\n return HANDLER_BY_TOKEN.get(token);\n}"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import {
|
|
2
|
+
compare
|
|
3
|
+
} from "./chunk-UGYSEYUQ.js";
|
|
4
|
+
import {
|
|
5
|
+
asDateFieldView
|
|
6
|
+
} from "./chunk-KEPIXQK7.js";
|
|
7
|
+
import {
|
|
8
|
+
format,
|
|
9
|
+
formatToParts
|
|
10
|
+
} from "./chunk-ACGCGXP5.js";
|
|
11
|
+
import {
|
|
12
|
+
daysFromCivil
|
|
13
|
+
} from "./chunk-BLZDBPSV.js";
|
|
14
|
+
import {
|
|
15
|
+
normalizeLocaleTag
|
|
16
|
+
} from "./chunk-QRLQ7RR7.js";
|
|
17
|
+
|
|
18
|
+
// src/interval.ts
|
|
19
|
+
function interval(start, end, bounds = "closed") {
|
|
20
|
+
const cmp = compare(start, end);
|
|
21
|
+
if (cmp > 0) {
|
|
22
|
+
throw new Error(
|
|
23
|
+
`temporal-fmt: interval start must be \u2264 end (got start > end). Pass them in chronological order.`
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
return { start, end, bounds };
|
|
27
|
+
}
|
|
28
|
+
function startIncluded(bounds) {
|
|
29
|
+
return bounds === "closed" || bounds === "half-open-end";
|
|
30
|
+
}
|
|
31
|
+
function endIncluded(bounds) {
|
|
32
|
+
return bounds === "closed" || bounds === "half-open-start";
|
|
33
|
+
}
|
|
34
|
+
function contains(iv, value) {
|
|
35
|
+
const startCmp = compare(value, iv.start);
|
|
36
|
+
const endCmp = compare(value, iv.end);
|
|
37
|
+
const afterStart = startIncluded(iv.bounds) ? startCmp >= 0 : startCmp > 0;
|
|
38
|
+
const beforeEnd = endIncluded(iv.bounds) ? endCmp <= 0 : endCmp < 0;
|
|
39
|
+
return afterStart && beforeEnd;
|
|
40
|
+
}
|
|
41
|
+
function overlaps(a, b) {
|
|
42
|
+
return intersects(a, b);
|
|
43
|
+
}
|
|
44
|
+
function intersects(a, b) {
|
|
45
|
+
const loCmp = compare(a.start, b.start);
|
|
46
|
+
const lo = loCmp >= 0 ? a.start : b.start;
|
|
47
|
+
const hiCmp = compare(a.end, b.end);
|
|
48
|
+
const hi = hiCmp <= 0 ? a.end : b.end;
|
|
49
|
+
const inner = compare(lo, hi);
|
|
50
|
+
if (inner < 0) return true;
|
|
51
|
+
if (inner > 0) return false;
|
|
52
|
+
return contains(a, lo) && contains(b, lo);
|
|
53
|
+
}
|
|
54
|
+
function isBefore(a, b) {
|
|
55
|
+
return compare(a.end, b.start) < 0;
|
|
56
|
+
}
|
|
57
|
+
function isAfter(a, b) {
|
|
58
|
+
return compare(a.start, b.end) > 0;
|
|
59
|
+
}
|
|
60
|
+
function intersection(a, b) {
|
|
61
|
+
if (!intersects(a, b)) return null;
|
|
62
|
+
const aStartLater = compare(a.start, b.start) > 0;
|
|
63
|
+
const start = aStartLater ? a.start : b.start;
|
|
64
|
+
const aEndEarlier = compare(a.end, b.end) < 0;
|
|
65
|
+
const end = aEndEarlier ? a.end : b.end;
|
|
66
|
+
const startInc = aStartLater ? startIncluded(a.bounds) : compare(b.start, a.start) > 0 ? startIncluded(b.bounds) : startIncluded(a.bounds) && startIncluded(b.bounds);
|
|
67
|
+
const endInc = aEndEarlier ? endIncluded(a.bounds) : compare(a.end, b.end) > 0 ? endIncluded(b.bounds) : endIncluded(a.bounds) && endIncluded(b.bounds);
|
|
68
|
+
const bounds = startInc ? endInc ? "closed" : "half-open-end" : endInc ? "half-open-start" : "open";
|
|
69
|
+
return { start, end, bounds };
|
|
70
|
+
}
|
|
71
|
+
function union(a, b) {
|
|
72
|
+
if (!intersects(a, b)) return null;
|
|
73
|
+
const aStartEarlier = compare(a.start, b.start) < 0;
|
|
74
|
+
const start = aStartEarlier ? a.start : b.start;
|
|
75
|
+
const aEndLater = compare(a.end, b.end) > 0;
|
|
76
|
+
const end = aEndLater ? a.end : b.end;
|
|
77
|
+
const startInc = aStartEarlier ? startIncluded(a.bounds) : compare(b.start, a.start) < 0 ? startIncluded(b.bounds) : startIncluded(a.bounds) || startIncluded(b.bounds);
|
|
78
|
+
const endInc = aEndLater ? endIncluded(a.bounds) : compare(a.end, b.end) < 0 ? endIncluded(b.bounds) : endIncluded(a.bounds) || endIncluded(b.bounds);
|
|
79
|
+
const bounds = startInc ? endInc ? "closed" : "half-open-end" : endInc ? "half-open-start" : "open";
|
|
80
|
+
return { start, end, bounds };
|
|
81
|
+
}
|
|
82
|
+
function difference(a, b) {
|
|
83
|
+
if (!intersects(a, b)) return [a];
|
|
84
|
+
const result = [];
|
|
85
|
+
if (compare(a.start, b.start) < 0) {
|
|
86
|
+
const endInc = contains(a, b.start) && !contains(b, b.start);
|
|
87
|
+
result.push({
|
|
88
|
+
start: a.start,
|
|
89
|
+
end: b.start,
|
|
90
|
+
bounds: startIncluded(a.bounds) ? endInc ? "closed" : "half-open-end" : endInc ? "half-open-start" : "open"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (compare(a.end, b.end) > 0) {
|
|
94
|
+
const startInc = contains(a, b.end) && !contains(b, b.end);
|
|
95
|
+
result.push({
|
|
96
|
+
start: b.end,
|
|
97
|
+
end: a.end,
|
|
98
|
+
bounds: startInc ? endIncluded(a.bounds) ? "closed" : "half-open-end" : endIncluded(a.bounds) ? "half-open-start" : "open"
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
var subtract = difference;
|
|
104
|
+
function mergeIntervals(intervals) {
|
|
105
|
+
if (intervals.length === 0) return [];
|
|
106
|
+
const sorted = [...intervals].sort((a, b) => compare(a.start, b.start));
|
|
107
|
+
const result = [{ ...sorted[0] }];
|
|
108
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
109
|
+
const current = sorted[i];
|
|
110
|
+
const last = result[result.length - 1];
|
|
111
|
+
const touching = compare(last.end, current.start) === 0;
|
|
112
|
+
const touchMerges = touching && (endIncluded(last.bounds) || startIncluded(current.bounds));
|
|
113
|
+
if (intersects(last, current) || touchMerges) {
|
|
114
|
+
const endCmp = compare(current.end, last.end);
|
|
115
|
+
if (endCmp > 0) {
|
|
116
|
+
last.end = current.end;
|
|
117
|
+
last.bounds = startIncluded(last.bounds) ? endIncluded(current.bounds) ? "closed" : "half-open-end" : endIncluded(current.bounds) ? "half-open-start" : "open";
|
|
118
|
+
} else if (endCmp === 0) {
|
|
119
|
+
last.bounds = startIncluded(last.bounds) ? endIncluded(last.bounds) || endIncluded(current.bounds) ? "closed" : "half-open-end" : endIncluded(last.bounds) || endIncluded(current.bounds) ? "half-open-start" : "open";
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
result.push({ ...current });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
var MAX_DATE_MS = 864e13;
|
|
128
|
+
function splitInterval(iv, n) {
|
|
129
|
+
if (n <= 0) throw new Error(`temporal-fmt: splitInterval requires n > 0 (got ${n}).`);
|
|
130
|
+
if (n === 1) return [iv];
|
|
131
|
+
const startFields = asDateFieldView(iv.start);
|
|
132
|
+
const endFields = asDateFieldView(iv.end);
|
|
133
|
+
const startMs = toMs(startFields);
|
|
134
|
+
const endMs = toMs(endFields);
|
|
135
|
+
if (Math.abs(startMs) > MAX_DATE_MS || Math.abs(endMs) > MAX_DATE_MS) {
|
|
136
|
+
throw new RangeError(
|
|
137
|
+
`temporal-fmt: splitInterval() endpoints are outside the representable Date range (approximately \xB1275,760 years). Split the interval into smaller ranges first.`
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const step = (endMs - startMs) / n;
|
|
141
|
+
const result = [];
|
|
142
|
+
const ivStartInc = startIncluded(iv.bounds);
|
|
143
|
+
const ivEndInc = endIncluded(iv.bounds);
|
|
144
|
+
for (let i = 0; i < n; i++) {
|
|
145
|
+
const sliceStart = startMs + i * step;
|
|
146
|
+
const sliceEnd = i === n - 1 ? endMs : sliceStart + step;
|
|
147
|
+
const startInc = i === 0 ? ivStartInc : true;
|
|
148
|
+
const endInc = i === n - 1 ? ivEndInc : false;
|
|
149
|
+
result.push({
|
|
150
|
+
start: fromMs(sliceStart, startFields),
|
|
151
|
+
end: fromMs(sliceEnd, endFields),
|
|
152
|
+
// The 'half-open-start' arm on the last line below is structurally
|
|
153
|
+
// unreachable: startInc is false only for slice 0 (later slices
|
|
154
|
+
// start included), and slice 0's endInc is always false (only the
|
|
155
|
+
// last slice carries the input's end inclusivity) — a slice with an
|
|
156
|
+
// exclusive start AND inclusive end would require n === 1, which
|
|
157
|
+
// returns [iv] unchanged above. The other arms are live and covered.
|
|
158
|
+
/* c8 ignore next 3 @preserve */
|
|
159
|
+
bounds: startInc ? endInc ? "closed" : "half-open-end" : endInc ? "half-open-start" : "open"
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
function toMs(v) {
|
|
165
|
+
const days = daysFromCivil(v.year, v.month, v.day);
|
|
166
|
+
return days * 864e5 + (v.hour ?? 0) * 36e5 + (v.minute ?? 0) * 6e4 + (v.second ?? 0) * 1e3 + (v.millisecond ?? 0);
|
|
167
|
+
}
|
|
168
|
+
function fromMs(ms, base) {
|
|
169
|
+
const MS_PER_DAY = 864e5;
|
|
170
|
+
const dayOverflow = Math.floor(ms / MS_PER_DAY);
|
|
171
|
+
let withinDay = ms % MS_PER_DAY;
|
|
172
|
+
if (withinDay < 0) withinDay += MS_PER_DAY;
|
|
173
|
+
const hour = Math.floor(withinDay / 36e5);
|
|
174
|
+
const minute = Math.floor(withinDay % 36e5 / 6e4);
|
|
175
|
+
const second = Math.floor(withinDay % 6e4 / 1e3);
|
|
176
|
+
const millisecond = withinDay % 1e3;
|
|
177
|
+
const newMs = dayOverflow * MS_PER_DAY;
|
|
178
|
+
const d = new Date(newMs);
|
|
179
|
+
return {
|
|
180
|
+
...base,
|
|
181
|
+
year: d.getUTCFullYear(),
|
|
182
|
+
month: d.getUTCMonth() + 1,
|
|
183
|
+
day: d.getUTCDate(),
|
|
184
|
+
hour,
|
|
185
|
+
minute,
|
|
186
|
+
second,
|
|
187
|
+
millisecond
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function formatRange(iv, formatStr, options = {}) {
|
|
191
|
+
try {
|
|
192
|
+
const startStr = format(iv.start, formatStr, options);
|
|
193
|
+
const endStr = format(iv.end, formatStr, options);
|
|
194
|
+
return `${startStr} \u2013 ${endStr}`;
|
|
195
|
+
} catch (err) {
|
|
196
|
+
try {
|
|
197
|
+
const fmt = new Intl.DateTimeFormat(normalizeLocaleTag(options.locale ?? "en-US"), {});
|
|
198
|
+
const startDate = toJSDate(iv.start);
|
|
199
|
+
const endDate = toJSDate(iv.end);
|
|
200
|
+
return fmt.formatRange(startDate, endDate);
|
|
201
|
+
} catch {
|
|
202
|
+
throw err;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
function formatRangeToParts(iv, formatStr, options = {}) {
|
|
207
|
+
const startParts = formatToParts(iv.start, formatStr, options);
|
|
208
|
+
const endParts = formatToParts(iv.end, formatStr, options);
|
|
209
|
+
const result = [...startParts];
|
|
210
|
+
result.push({ type: "literal", value: " \u2013 " });
|
|
211
|
+
result.push(...endParts);
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
function toJSDate(value) {
|
|
215
|
+
const v = value;
|
|
216
|
+
if (typeof v?.toInstant === "function") {
|
|
217
|
+
return new Date(v.toInstant().epochMilliseconds);
|
|
218
|
+
}
|
|
219
|
+
if (typeof v?.year === "number" && typeof v?.month === "number" && typeof v?.day === "number") {
|
|
220
|
+
return new Date(Date.UTC(v.year, v.month - 1, v.day, v.hour ?? 0, v.minute ?? 0, v.second ?? 0, v.millisecond ?? 0));
|
|
221
|
+
}
|
|
222
|
+
throw new Error(`temporal-fmt: formatRange() expected Temporal values with year/month/day, got ${typeof value}.`);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export {
|
|
226
|
+
interval,
|
|
227
|
+
contains,
|
|
228
|
+
overlaps,
|
|
229
|
+
intersects,
|
|
230
|
+
isBefore,
|
|
231
|
+
isAfter,
|
|
232
|
+
intersection,
|
|
233
|
+
union,
|
|
234
|
+
difference,
|
|
235
|
+
subtract,
|
|
236
|
+
mergeIntervals,
|
|
237
|
+
splitInterval,
|
|
238
|
+
formatRange,
|
|
239
|
+
formatRangeToParts
|
|
240
|
+
};
|
|
241
|
+
//# sourceMappingURL=chunk-E4DD23HH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/interval.ts"],"sourcesContent":["/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Intervals / ranges. An interval is a pair of\n// (start, end) Temporal values with bounds semantics: open, closed,\n// or half-open. Operations: contains, overlaps, intersects, isBefore,\n// isAfter, intersection, union, difference, subtract, mergeIntervals,\n// splitInterval. Plus formatRange / formatRangeToParts with intelligent\n// collapsing.\n//\n// All operations are field-based (no instanceof), matching the rest of\n// the library. Internally uses the comparison helpers from comparison.ts\n// to order endpoints.\n\nimport { compare } from './comparison.js';\nimport { formatToParts, format as baseFormat, type FormattedPart } from './format.js';\nimport { asDateFieldView, type DateFieldView } from './calendarUtils.js';\nimport { normalizeLocaleTag } from './localeVocab.js';\nimport { daysFromCivil } from './isoWeek.js';\nimport type { FormatOptions } from './tokens.js';\n\nexport type IntervalBounds = 'open' | 'closed' | 'half-open-start' | 'half-open-end';\n\nexport interface Interval {\n start: unknown;\n end: unknown;\n bounds: IntervalBounds;\n}\n\nexport function interval(start: unknown, end: unknown, bounds: IntervalBounds = 'closed'): Interval {\n // Validate that start ≤ end, otherwise the interval is malformed.\n const cmp = compare(start, end);\n if (cmp > 0) {\n throw new Error(\n `temporal-fmt: interval start must be ≤ end (got start > end). Pass them in chronological order.`\n );\n }\n return { start, end, bounds };\n}\n\n// Inclusive containment check accounting for bounds semantics.\n// - 'closed': [start, end] — both endpoints included\n// - 'open': (start, end) — neither endpoint included\n// - 'half-open-start': (start, end] — start excluded, end included\n// - 'half-open-end': [start, end) — start included, end excluded\n//\n// The two half-open conditions below used to have their labels swapped —\n// 'half-open-end' excluded the start and included the end (the exact\n// behavior 'half-open-start' documents, and vice versa) — which made\n// contains() disagree with difference() (whose labels were correct all\n// along) and silently broke splitInterval's partition (see below).\n// startOpen/beginOpen naming below says which *endpoint* is excluded, so\n// the mapping to the label can't drift again.\nfunction startIncluded(bounds: IntervalBounds): boolean {\n return bounds === 'closed' || bounds === 'half-open-end';\n}\nfunction endIncluded(bounds: IntervalBounds): boolean {\n return bounds === 'closed' || bounds === 'half-open-start';\n}\n\nexport function contains(iv: Interval, value: unknown): boolean {\n const startCmp = compare(value, iv.start);\n const endCmp = compare(value, iv.end);\n const afterStart = startIncluded(iv.bounds) ? startCmp >= 0 : startCmp > 0;\n const beforeEnd = endIncluded(iv.bounds) ? endCmp <= 0 : endCmp < 0;\n return afterStart && beforeEnd;\n}\n\n// Two intervals overlap iff their ranges intersect, regardless of bounds.\n// intersects() is the boolean form; intersection() returns the actual\n// overlap interval.\nexport function overlaps(a: Interval, b: Interval): boolean {\n return intersects(a, b);\n}\n\nexport function intersects(a: Interval, b: Interval): boolean {\n // Two intervals intersect iff they share at least one point. The old\n // version returned true whenever the spans touched, regardless of\n // bounds — so (Jan 1, Jan 5) and (Jan 5, Jan 10), which share no point\n // (Jan 5 belongs to neither), reported as overlapping, and\n // intersection() returned a degenerate non-empty-looking result for\n // the empty intersection. Computing the candidate shared span and\n // consulting contains() at the single shared point handles every\n // bounds combination uniformly.\n const loCmp = compare(a.start, b.start);\n const lo = loCmp >= 0 ? a.start : b.start; // later start\n const hiCmp = compare(a.end, b.end);\n const hi = hiCmp <= 0 ? a.end : b.end; // earlier end\n const inner = compare(lo, hi);\n if (inner < 0) return true; // strictly inside — a real span is shared\n if (inner > 0) return false; // spans don't reach each other\n // lo === hi: the only possible shared point is that single value —\n // it has to be contained in BOTH intervals.\n return contains(a, lo) && contains(b, lo);\n}\n\nexport function isBefore(a: Interval, b: Interval): boolean {\n return compare(a.end, b.start) < 0;\n}\n\nexport function isAfter(a: Interval, b: Interval): boolean {\n return compare(a.start, b.end) > 0;\n}\n\n// Returns the intersection of two intervals, or null if they don't\n// overlap. The result's bounds at each endpoint come from whichever\n// interval OWNS that endpoint (the later start, the earlier end) — when\n// both intervals supply the same endpoint, intersection inclusivity is\n// the AND of the two (a point is in a∩b only if it's in both).\nexport function intersection(a: Interval, b: Interval): Interval | null {\n if (!intersects(a, b)) return null;\n const aStartLater = compare(a.start, b.start) > 0;\n const start = aStartLater ? a.start : b.start;\n const aEndEarlier = compare(a.end, b.end) < 0;\n const end = aEndEarlier ? a.end : b.end;\n // Start-side inclusivity: owned by the later-start interval, or the\n // conjunction when the starts are equal.\n const startInc = aStartLater\n ? startIncluded(a.bounds)\n : compare(b.start, a.start) > 0\n ? startIncluded(b.bounds)\n : startIncluded(a.bounds) && startIncluded(b.bounds);\n // End-side inclusivity: owned by the earlier-end interval, or the\n // conjunction when the ends are equal.\n const endInc = aEndEarlier\n ? endIncluded(a.bounds)\n : compare(a.end, b.end) > 0\n ? endIncluded(b.bounds)\n : endIncluded(a.bounds) && endIncluded(b.bounds);\n const bounds: IntervalBounds = startInc\n ? (endInc ? 'closed' : 'half-open-end')\n : (endInc ? 'half-open-start' : 'open');\n return { start, end, bounds };\n}\n\n// Returns the union of two intervals (the smallest interval containing\n// both), or null if they don't overlap (caller should use mergeIntervals\n// for that case). Union inclusivity at each endpoint comes from the\n// interval that extends further, or the disjunction when both reach the\n// same endpoint.\nexport function union(a: Interval, b: Interval): Interval | null {\n if (!intersects(a, b)) return null;\n const aStartEarlier = compare(a.start, b.start) < 0;\n const start = aStartEarlier ? a.start : b.start;\n const aEndLater = compare(a.end, b.end) > 0;\n const end = aEndLater ? a.end : b.end;\n const startInc = aStartEarlier\n ? startIncluded(a.bounds)\n : compare(b.start, a.start) < 0\n ? startIncluded(b.bounds)\n : startIncluded(a.bounds) || startIncluded(b.bounds);\n const endInc = aEndLater\n ? endIncluded(a.bounds)\n : compare(a.end, b.end) < 0\n ? endIncluded(b.bounds)\n : endIncluded(a.bounds) || endIncluded(b.bounds);\n const bounds: IntervalBounds = startInc\n ? (endInc ? 'closed' : 'half-open-end')\n : (endInc ? 'half-open-start' : 'open');\n return { start, end, bounds };\n}\n\n// Returns the part of `a` that is not in `b`. May produce 0, 1, or 2\n// intervals depending on the overlap shape.\n//\n// Bounds semantics: each surviving piece keeps the inclusivity of the\n// original endpoint it inherits from `a`, and the endpoint created by the\n// cut is always exclusive (it is `b`'s edge, which belongs to the removed\n// overlap). The old implementation derived both bounds from a lossy\n// helper that collapsed several of these combinations — the pieces'\n// endpoints were right, but the bounds metadata was stricter than the\n// actual remainder for open/half-open inputs.\nexport function difference(a: Interval, b: Interval): Interval[] {\n if (!intersects(a, b)) return [a];\n const result: Interval[] = [];\n // Part of `a` before `b` starts. Its end is b.start; that point stays\n // in the remainder iff a still contains it AND b doesn't — a cut edge\n // is only removed when the removed interval actually includes it (a\n // cut against an open-bounded b used to drop the edge point even\n // though b never owned it).\n if (compare(a.start, b.start) < 0) {\n const endInc = contains(a, b.start) && !contains(b, b.start);\n result.push({\n start: a.start,\n end: b.start,\n bounds: startIncluded(a.bounds)\n ? (endInc ? 'closed' : 'half-open-end')\n : (endInc ? 'half-open-start' : 'open'),\n });\n }\n // Part of `a` after `b` ends — mirror image of the above.\n if (compare(a.end, b.end) > 0) {\n const startInc = contains(a, b.end) && !contains(b, b.end);\n result.push({\n start: b.end,\n end: a.end,\n bounds: startInc\n ? (endIncluded(a.bounds) ? 'closed' : 'half-open-end')\n : (endIncluded(a.bounds) ? 'half-open-start' : 'open'),\n });\n }\n return result;\n}\n\n// Alias for difference() — \"subtract\" reads more naturally at some\n// call sites than \"difference\" does.\nexport const subtract = difference;\n\n// Merges a list of intervals, combining overlapping ones. Returns a\n// sorted list of disjoint intervals. The inputs are treated as\n// immutable — the merged result carries shallow copies of any interval\n// object it extends, so a caller's own `end` reference is never\n// reassigned under them (mergeIntervals used to write `last.end =\n// current.end` straight into the caller's object).\nexport function mergeIntervals(intervals: Interval[]): Interval[] {\n if (intervals.length === 0) return [];\n const sorted = [...intervals].sort((a, b) => compare(a.start, b.start));\n // Shallow-copy EVERY interval placed into the result, not just the\n // first — the inputs are documented as immutable and the merged\n // object is mutated below (last.end is reassigned), so aliasing any\n // input would write through to the caller's objects. Non-merged\n // intervals used to be pushed by reference.\n const result: Interval[] = [{ ...sorted[0]! }];\n for (let i = 1; i < sorted.length; i++) {\n const current = sorted[i]!;\n const last = result[result.length - 1]!;\n // Touching endpoints merge only when at least one interval actually\n // contains the shared point — [1,5) + [5,10] union to [1,10], but\n // (1,5) + (5,10) leave a hole at exactly 5 and must stay separate.\n // (Plain overlaps always merge, per intersects().)\n const touching = compare(last.end, current.start) === 0;\n const touchMerges = touching && (endIncluded(last.bounds) || startIncluded(current.bounds));\n if (intersects(last, current) || touchMerges) {\n // Extend to the farther end, carrying that interval's end\n // inclusivity over (and when the ends are equal, the union of the\n // two end inclusivities).\n const endCmp = compare(current.end, last.end);\n if (endCmp > 0) {\n last.end = current.end;\n last.bounds = startIncluded(last.bounds)\n ? (endIncluded(current.bounds) ? 'closed' : 'half-open-end')\n : (endIncluded(current.bounds) ? 'half-open-start' : 'open');\n } else if (endCmp === 0) {\n last.bounds = startIncluded(last.bounds)\n ? (endIncluded(last.bounds) || endIncluded(current.bounds) ? 'closed' : 'half-open-end')\n : (endIncluded(last.bounds) || endIncluded(current.bounds) ? 'half-open-start' : 'open');\n }\n } else {\n result.push({ ...current });\n }\n }\n return result;\n}\n\n// Widest instant JS Date can represent (±8.64e15 ms, i.e. ±100,000,000\n// days from the Unix epoch). splitInterval rebuilds endpoints via Date,\n// so anything outside this window would silently produce Invalid Date\n// objects with NaN year/month/day fields — reject it descriptively\n// instead.\nconst MAX_DATE_MS = 8.64e15;\n\n// Splits an interval into N equal sub-intervals. Throws if N ≤ 0.\n// Equality is by ms-distance between start and end — for date ranges\n// this approximates \"equal time slices\", which is the most useful\n// interpretation. For calendar-bound splits (e.g. \"split this month\n// into weeks\"), callers should use recurrence() instead.\nexport function splitInterval(iv: Interval, n: number): Interval[] {\n if (n <= 0) throw new Error(`temporal-fmt: splitInterval requires n > 0 (got ${n}).`);\n if (n === 1) return [iv];\n const startFields = asDateFieldView(iv.start) as DateFieldView & { hour?: number; minute?: number; second?: number; millisecond?: number };\n const endFields = asDateFieldView(iv.end) as DateFieldView & { hour?: number; minute?: number; second?: number; millisecond?: number };\n const startMs = toMs(startFields);\n const endMs = toMs(endFields);\n if (Math.abs(startMs) > MAX_DATE_MS || Math.abs(endMs) > MAX_DATE_MS) {\n throw new RangeError(\n `temporal-fmt: splitInterval() endpoints are outside the representable Date range ` +\n `(approximately ±275,760 years). Split the interval into smaller ranges first.`\n );\n }\n const step = (endMs - startMs) / n;\n const result: Interval[] = [];\n // A partition: slice 0 keeps the caller's start inclusivity, slices\n // 1..n-1 start exactly where the previous slice ended (exclusively),\n // so their starts are INCLUDED, and every slice except the last\n // excludes its end; the last slice keeps the caller's end inclusivity.\n // Together: [s0, s1) [s1, s2) ... [s_{n-1}, s_n] for a closed input —\n // every point in exactly one slice. (The old version labeled the\n // middle slices 'half-open-start' — which under the pre-fix, swapped\n // contains() semantics accidentally behaved like [s, e) — and left\n // the ORIGINAL end point out of the last slice entirely.)\n const ivStartInc = startIncluded(iv.bounds);\n const ivEndInc = endIncluded(iv.bounds);\n for (let i = 0; i < n; i++) {\n const sliceStart = startMs + i * step;\n const sliceEnd = i === n - 1 ? endMs : sliceStart + step;\n const startInc = i === 0 ? ivStartInc : true;\n const endInc = i === n - 1 ? ivEndInc : false;\n result.push({\n start: fromMs(sliceStart, startFields),\n end: fromMs(sliceEnd, endFields),\n // The 'half-open-start' arm on the last line below is structurally\n // unreachable: startInc is false only for slice 0 (later slices\n // start included), and slice 0's endInc is always false (only the\n // last slice carries the input's end inclusivity) — a slice with an\n // exclusive start AND inclusive end would require n === 1, which\n // returns [iv] unchanged above. The other arms are live and covered.\n /* c8 ignore next 3 @preserve */\n bounds: startInc\n ? (endInc ? 'closed' : 'half-open-end')\n : (endInc ? 'half-open-start' : 'open'),\n });\n }\n return result;\n}\n\nfunction toMs(v: DateFieldView & { hour?: number; minute?: number; second?: number; millisecond?: number }): number {\n // daysFromCivil (isoWeek.ts) is the O(1) Hinnant day count, correct\n // for negative years. The formula previously inlined here carried a\n // Math.floor applied to Hinnant's -399-offset numerator — a double\n // correction that shifted every pre-year-0 date by one day (the\n // offset form is only equivalent under truncating division, which JS\n // doesn't have).\n const days = daysFromCivil(v.year!, v.month!, v.day!);\n return days * 86_400_000\n + (v.hour ?? 0) * 3_600_000\n + (v.minute ?? 0) * 60_000\n + (v.second ?? 0) * 1_000\n + (v.millisecond ?? 0);\n}\n\nfunction fromMs(ms: number, base: DateFieldView & { hour?: number; minute?: number; second?: number; millisecond?: number }): DateFieldView {\n const MS_PER_DAY = 86_400_000;\n const dayOverflow = Math.floor(ms / MS_PER_DAY);\n let withinDay = ms % MS_PER_DAY;\n if (withinDay < 0) withinDay += MS_PER_DAY;\n const hour = Math.floor(withinDay / 3_600_000);\n const minute = Math.floor((withinDay % 3_600_000) / 60_000);\n const second = Math.floor((withinDay % 60_000) / 1_000);\n const millisecond = withinDay % 1_000;\n // `ms` (and therefore `dayOverflow`) is already an absolute epoch-ms /\n // epoch-day value — toMs() computed it via Howard Hinnant's algorithm\n // from scratch, not as an offset from `base`. So the date only needs\n // reconstructing from the Unix epoch itself; `base` is just a template\n // for whatever extra (non-date) fields get spread into the result.\n // (Previously this added dayOverflow on top of base's own epoch-ms,\n // double-counting base's offset and landing tens of thousands of days\n // away from the intended date for any non-epoch base.)\n const newMs = dayOverflow * MS_PER_DAY;\n const d = new Date(newMs);\n return {\n ...base,\n year: d.getUTCFullYear(),\n month: d.getUTCMonth() + 1,\n day: d.getUTCDate(),\n hour,\n minute,\n second,\n millisecond,\n };\n}\n\n// Formats an interval as a single string, collapsing shared fields.\n// E.g. \"August 4 – August 6, 2026\" rather than \"August 4, 2026 – August 6, 2026\".\n// Uses Intl.DateTimeFormat's formatRange when available (most engines),\n// falling back to format(start, fmt) + '–' + format(end, fmt) when not.\n\nexport function formatRange(\n iv: Interval,\n formatStr: string,\n options: FormatOptions = {},\n): string {\n // The formatStr parameter is this function's contract — the caller\n // asked for their token format on both endpoints. Honor it first:\n // format each side with the caller's format string and join with an\n // en dash. (This used to try Intl.DateTimeFormat.formatRange() first,\n // which ignores formatStr entirely — formatRange(iv, 'yyyy-MM-dd')\n // silently returned locale-default output like \"8/4/2026 – 8/6/2026\"\n // instead of \"2026-08-04 – 2026-08-06\".) Intl's range collapsing is\n // kept as a fallback for inputs the token path can't render.\n try {\n const startStr = baseFormat(iv.start as Parameters<typeof baseFormat>[0], formatStr, options);\n const endStr = baseFormat(iv.end as Parameters<typeof baseFormat>[0], formatStr, options);\n return `${startStr} – ${endStr}`;\n } catch (err) {\n // Fallback: Intl.DateTimeFormat.formatRange is the standard\n // mechanism with native field-collapse behavior, but it has no\n // knowledge of the caller's token format string.\n try {\n const fmt = new Intl.DateTimeFormat(normalizeLocaleTag(options.locale ?? 'en-US'), {});\n // Cast the interval endpoints to Date for the Intl call. Both\n // endpoints must be Temporal values that can convert to a Date;\n // for non-ZonedDateTime values we synthesize a Date via the field\n // shape (year/month/day/hour/...).\n const startDate = toJSDate(iv.start);\n const endDate = toJSDate(iv.end);\n return fmt.formatRange(startDate, endDate);\n } catch {\n // Neither path could render — surface the token-path error, since\n // the formatStr contract is the primary one.\n throw err;\n }\n }\n}\n\nexport function formatRangeToParts(\n iv: Interval,\n formatStr: string,\n options: FormatOptions = {},\n): FormattedPart[] {\n // Best-effort: returns formatToParts for the start, then a literal\n // \" – \" part, then formatToParts for the end. Doesn't currently\n // expose Intl.DateTimeFormat.formatRangeToParts's collapsed shape —\n // that would require mapping Intl's part types back to temporal-fmt's\n // token strings, which is locale-dependent and not stable across\n // engines.\n const startParts = formatToParts(iv.start as Parameters<typeof formatToParts>[0], formatStr, options);\n const endParts = formatToParts(iv.end as Parameters<typeof formatToParts>[0], formatStr, options);\n const result: FormattedPart[] = [...startParts];\n result.push({ type: 'literal', value: ' – ' });\n result.push(...endParts);\n return result;\n}\n\nfunction toJSDate(value: unknown): Date {\n const v = value as { year?: number; month?: number; day?: number; hour?: number; minute?: number; second?: number; millisecond?: number; toInstant?: () => { epochMilliseconds: number } };\n if (typeof v?.toInstant === 'function') {\n return new Date(v.toInstant().epochMilliseconds);\n }\n if (typeof v?.year === 'number' && typeof v?.month === 'number' && typeof v?.day === 'number') {\n return new Date(Date.UTC(v.year, v.month - 1, v.day, v.hour ?? 0, v.minute ?? 0, v.second ?? 0, v.millisecond ?? 0));\n }\n throw new Error(`temporal-fmt: formatRange() expected Temporal values with year/month/day, got ${typeof value}.`);\n}"],"mappings":"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","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyParseNumbering,
|
|
3
3
|
tokenize
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EXIJZ4JG.js";
|
|
5
5
|
import {
|
|
6
6
|
DEFAULT_LOCALE
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GRBQ5FRO.js";
|
|
8
8
|
import {
|
|
9
9
|
getTemporal
|
|
10
10
|
} from "./chunk-DFWTCRS3.js";
|
|
@@ -975,10 +975,12 @@ function compileParser(formatStr, options = {}) {
|
|
|
975
975
|
export {
|
|
976
976
|
FORMAT_ONLY_TOKENS,
|
|
977
977
|
UNPADDED_NUMERIC_TOKENS,
|
|
978
|
+
enumerateValidSplits,
|
|
979
|
+
buildCapturingPattern,
|
|
978
980
|
parse,
|
|
979
981
|
safeParse,
|
|
980
982
|
tryParse,
|
|
981
983
|
parseToParts,
|
|
982
984
|
compileParser
|
|
983
985
|
};
|
|
984
|
-
//# sourceMappingURL=chunk-
|
|
986
|
+
//# sourceMappingURL=chunk-EEPLAE3H.js.map
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DEFAULT_LOCALE,
|
|
3
|
-
TOKENS
|
|
4
|
-
|
|
5
|
-
onTokenTableChange
|
|
6
|
-
} from "./chunk-BQET6RUR.js";
|
|
3
|
+
TOKENS
|
|
4
|
+
} from "./chunk-GRBQ5FRO.js";
|
|
7
5
|
import {
|
|
8
6
|
FormatSyntaxError,
|
|
9
7
|
InvalidLocaleError,
|
|
@@ -14,9 +12,6 @@ import {
|
|
|
14
12
|
|
|
15
13
|
// src/tokenize.ts
|
|
16
14
|
var SORTED_TOKEN_STRINGS = TOKENS.map(([tok]) => tok).sort((a, b) => b.length - a.length);
|
|
17
|
-
onTokenTableChange(() => {
|
|
18
|
-
SORTED_TOKEN_STRINGS = getEffectiveTokens().map(([tok]) => tok).sort((a, b) => b.length - a.length);
|
|
19
|
-
});
|
|
20
15
|
function tokenizeWithSpans(format) {
|
|
21
16
|
const pieces = [];
|
|
22
17
|
let i = 0;
|
|
@@ -204,4 +199,4 @@ export {
|
|
|
204
199
|
applyNumbering,
|
|
205
200
|
applyParseNumbering
|
|
206
201
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
202
|
+
//# sourceMappingURL=chunk-EXIJZ4JG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tokenize.ts","../src/numbering.ts"],"sourcesContent":["/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { TOKENS } from './tokens.js';\nimport { FormatSyntaxError, UnknownTokenError } from './errors.js';\n\nexport type Piece =\n | { kind: 'token'; value: string }\n | { kind: 'literal'; value: string };\n\n// A piece plus its exact source span in the ORIGINAL format string.\n// `start`/`end` are UTF-16 code-unit indices, half-open [start, end).\n// Decoded literals can be shorter than their span ('' is 2 source\n// chars → 1 decoded quote), which is exactly why positions computed\n// from decoded lengths (the old approach in analyze.ts) drifted after\n// any quoted text.\nexport interface SpannedPiece {\n kind: 'token' | 'literal';\n value: string;\n start: number;\n end: number;\n}\n\n// gotta sort longest-first or the greedy scan grabs \"M\" when \"MMMM\" was actually there.\nconst SORTED_TOKEN_STRINGS = TOKENS.map(([tok]) => tok).sort((a, b) => b.length - a.length);\n\n/**\n * Splits a format string like `\"yyyy-MM-dd 'at' HH:mm\"` into token/literal\n * pieces, each with its exact source span. Text in single quotes is always\n * literal (e.g. write 'rd' in \"3rd\" so it's not read as the day token). A\n * doubled quote ('') means a literal quote character, both inside a quoted\n * span and standalone.\n */\nexport function tokenizeWithSpans(format: string): SpannedPiece[] {\n const pieces: SpannedPiece[] = [];\n let i = 0;\n\n while (i < format.length) {\n const ch = format[i];\n\n if (ch === \"'\") {\n // gotta check the doubled-quote case first, otherwise \"''best''\" parses wrong\n if (format[i + 1] === \"'\") {\n appendLiteral(pieces, \"'\", i, i + 2);\n i += 2;\n continue;\n }\n\n let j = i + 1;\n let literal = '';\n let closed = false;\n while (j < format.length) {\n if (format[j] === \"'\") {\n if (format[j + 1] === \"'\") {\n literal += \"'\";\n j += 2;\n continue;\n }\n closed = true;\n j += 1;\n break;\n }\n literal += format[j];\n j += 1;\n }\n\n if (!closed) {\n throw new FormatSyntaxError({\n format,\n message: `temporal-fmt: unterminated quote in format string \"${format}\"`,\n });\n }\n\n appendLiteral(pieces, literal, i, j);\n i = j;\n continue;\n }\n\n const match = SORTED_TOKEN_STRINGS.find((tok) => format.startsWith(tok, i));\n if (match) {\n // this is already the longest token that starts here, so if there's\n // one more of the same char after it, that's not a real token — it'd\n // just silently fall through to whatever handles that next char and\n // get glued onto this one. found this the hard way: \"zzzz\" was\n // parsing as zzz + literal \"z\", \"MMMMM\" as MMMM + the M token. so now\n // we just treat the whole overlong run as one bad token instead\n const runChar = match[match.length - 1];\n if (format[i + match.length] === runChar) {\n let end = i + match.length;\n while (format[end] === runChar) end += 1;\n // UnknownTokenError, not FormatSyntaxError: wrapUntypedError's\n // classifier already treats this exact message (\"isn't a\n // recognized token\") as UNKNOWN_TOKEN (see errors.test.js's\n // \"overlong token run classifies as UnknownTokenError\"), and a\n // direct throw here needs to agree with what safeParse's fallback\n // path would have classified it as.\n throw new UnknownTokenError({\n format,\n token: format.slice(i, end),\n message:\n `temporal-fmt: \"${format.slice(i, end)}\" in format string \"${format}\" isn't a recognized token — ` +\n `did you mean \"${match}\"?`,\n });\n }\n pieces.push({ kind: 'token', value: match, start: i, end: i + match.length });\n i += match.length;\n continue;\n }\n\n // not a token or quote — pass through as-is\n appendLiteral(pieces, ch, i, i + 1);\n i += 1;\n }\n\n return pieces;\n}\n\n/**\n * Splits a format string like `\"yyyy-MM-dd 'at' HH:mm\"` into token/literal\n * pieces. Text in single quotes is always literal (e.g. write 'rd' in\n * \"3rd\" so it's not read as the day token). A doubled quote ('') means a\n * literal quote character, both inside a quoted span and standalone.\n */\nexport function tokenize(format: string): Piece[] {\n return tokenizeWithSpans(format).map(({ kind, value }) => ({ kind, value }));\n}\n\n// merges into the previous piece if it's also a literal, so \"---\" is one\n// piece instead of three (spans track the full merged range)\nfunction appendLiteral(pieces: SpannedPiece[], value: string, start: number, end: number): void {\n const last = pieces[pieces.length - 1];\n if (last && last.kind === 'literal' && last.end === start) {\n last.value += value;\n last.end = end;\n } else {\n pieces.push({ kind: 'literal', value, start, end });\n }\n}\n","/*\n * Copyright 2026 DirazCoder\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// numbering systems. latn (ASCII digits) is the default, but arab, deva,\n// beng, etc are all options, configurable per format call.\n//\n// the tokens in this lib always spit out ASCII digits normally (check\n// tokens.ts's pad() — just String(n), which is ASCII). this module bolts\n// on the ability to convert that output to a locale's native digits via\n// Intl.NumberFormat, since that's the standard way JS does digit\n// transliteration anyway.\n//\n// parse side is stricter: parse() only accepts ASCII digits, matches how\n// NUMERIC_FRAGMENTS is already built. parseNumberingSystem converts\n// input digits to ASCII first — an explicit opt-in per call, never\n// silently accepting any numeral system that shows up.\n//\n// both directions also accept 'auto': instead of requiring the caller to\n// know the ICU numbering-system code for their locale, ask\n// Intl.NumberFormat(locale).resolvedOptions().numberingSystem what the\n// locale itself uses and transliterate with that.\n\nimport { DEFAULT_LOCALE, type FormatOptions } from './tokens.js';\nimport { InvalidLocaleError } from './errors.js';\nimport { canonicalCacheKey, normalizeLocaleTag } from './localeVocab.js';\n\nexport type NumberingSystem = 'latn' | 'arab' | 'deva' | 'beng' | 'guru' | 'gujr' | 'orya' | 'tamldec' | 'telu' | 'knda' | 'mlym' | 'fullwide' | 'hanidec';\n\n// What a caller may pass as numberingSystem / parseNumberingSystem: an\n// explicit system name, or 'auto' to derive the system from the call's\n// locale. The `(string & {})` keeps arbitrary strings compiling (the\n// runtime still validates them against SUPPORTED_NUMBERING_SYSTEMS and\n// throws on unknown names, unchanged) while editors still offer the\n// known literals — 'latn', 'arab', ..., 'auto' — as completions.\nexport type NumberingSystemOption = NumberingSystem | 'auto' | (string & {});\n\n// every NumberingSystem value we support. latn's the default and\n// what the rest of this lib naturally produces\nexport const SUPPORTED_NUMBERING_SYSTEMS: ReadonlySet<string> = new Set([\n 'latn', 'arab', 'deva', 'beng', 'guru', 'gujr', 'orya', 'tamldec',\n 'telu', 'knda', 'mlym', 'fullwide', 'hanidec',\n]);\n\nconst digitMapCache = new Map<string, Record<string, string>>();\n\n// 'auto' resolutions, keyed by canonical locale tag (same key discipline\n// as every other locale-keyed cache in this library — 'ar_EG' and 'ar-EG'\n// fold together instead of costing two entries). Intl.NumberFormat\n// construction isn't free and format() runs in loops (a table of dates, one\n// row per record), so resolve each locale once. Bounded, evicting the\n// oldest insertion, mirroring formatterCache in tokens.ts.\nconst autoNumberingCache = new Map<string, string>();\nconst MAX_AUTO_NUMBERING_CACHE = 500;\n\n// Turns 'auto' into a concrete system by asking Intl what the locale\n// itself defaults to (ar-EG -> arab, bn-BD -> beng, en-US -> latn). When\n// the locale's native system isn't one this library can transliterate\n// (thai, laoo, mymr, ... — anything outside SUPPORTED_NUMBERING_SYSTEMS),\n// fall back to 'latn' rather than throwing: 'auto' means \"use whatever\n// this locale naturally uses, if you can\", not \"throw on locales with\n// numerals this library doesn't cover\". A malformed locale tag DOES\n// throw — typed InvalidLocaleError, matching getFormatter() in tokens.ts —\n// since asking to derive from a locale that doesn't exist is a caller bug,\n// not a data condition to paper over.\nfunction resolveAutoNumberingSystem(locale: string): string {\n const key = canonicalCacheKey(locale);\n const cached = autoNumberingCache.get(key);\n if (cached !== undefined) return cached;\n let resolved: string;\n try {\n resolved = new Intl.NumberFormat(normalizeLocaleTag(locale)).resolvedOptions().numberingSystem;\n } catch (err) {\n throw new InvalidLocaleError({ actual: locale, reason: (err as Error).message });\n }\n const system = SUPPORTED_NUMBERING_SYSTEMS.has(resolved) ? resolved : 'latn';\n if (autoNumberingCache.size >= MAX_AUTO_NUMBERING_CACHE) {\n // not real LRU, just evicts oldest insertion — fine for this key space\n const oldestKey = autoNumberingCache.keys().next().value;\n if (oldestKey !== undefined) autoNumberingCache.delete(oldestKey);\n }\n autoNumberingCache.set(key, system);\n return system;\n}\n\n// Shared front door for both option names. undefined stays 'latn' — the\n// default is unchanged; 'auto' is an opt-in, not a new default. Anything\n// else passes through untouched for convertDigits/convertDigitsToAscii\n// to validate against the supported set (they throw on unknown names).\nfunction resolveRequestedSystem(requested: string | undefined, locale: string | undefined): string {\n if (requested === undefined) return 'latn';\n if (requested === 'auto') return resolveAutoNumberingSystem(locale ?? DEFAULT_LOCALE);\n return requested;\n}\n\n// builds a digit-transliteration map per numbering system. renders 0-9\n// through Intl.NumberFormat in the target system, then builds the lookup\n// table from that. caching it since spinning up a formatter isn't free\n// and we reuse the same map for every digit we convert\nfunction getDigitMap(system: string): Record<string, string> {\n let map = digitMapCache.get(system);\n if (map) return map;\n /* c8 ignore start @preserve -- this branch is dead by construction, not\n just untested: both callers (convertDigits, convertDigitsToAscii)\n already bail out early on system === 'latn' before ever calling\n getDigitMap, so it never actually gets invoked with 'latn'. keeping\n it anyway as a defensive fallback rather than betting that stays\n true forever */\n if (system === 'latn') {\n map = {};\n for (let i = 0; i < 10; i++) map[String(i)] = String(i);\n } else {\n /* c8 ignore stop @preserve */\n const fmt = new Intl.NumberFormat('en-US-u-nu-' + system, { useGrouping: false });\n map = {};\n for (let i = 0; i < 10; i++) {\n map[String(i)] = fmt.format(i);\n }\n }\n digitMapCache.set(system, map);\n return map;\n}\n\n// swaps every ASCII digit in `s` for its equivalent in the target\n// numbering system. anything that's not a digit passes through untouched\nexport function convertDigits(s: string, system: string): string {\n if (system === 'latn') return s;\n if (!SUPPORTED_NUMBERING_SYSTEMS.has(system)) {\n throw new InvalidLocaleError({ actual: system, reason: `numbering system \"${system}\" is not supported. Supported: ${[...SUPPORTED_NUMBERING_SYSTEMS].join(', ')}.` });\n }\n const map = getDigitMap(system);\n let result = '';\n for (const ch of s) {\n if (ch >= '0' && ch <= '9') {\n // map[ch] is always populated for 0-9 — getDigitMap builds all ten\n // keys for every system we support, and ch is already range-checked\n // above. the ?? ch is really just there to satisfy TS about Record's\n // implicit undefined, not because this path is actually reachable\n /* c8 ignore next */\n result += map[ch] ?? ch;\n } else {\n result += ch;\n }\n }\n return result;\n}\n\n// inverse of convertDigits — takes non-ASCII digits back to ASCII. used\n// by parse() when someone passes an explicit numberingSystem option.\n// throws on anything unsupported\nexport function convertDigitsToAscii(s: string, system: string): string {\n // same dead-by-construction thing as the 'latn' guard above —\n // applyParseNumbering (the only caller) already returns early on\n // 'latn' before this ever gets called, so system's never actually\n // 'latn' here in practice. leaving the guard anyway in case someone\n // calls this directly someday without going through that guard\n /* c8 ignore next */\n if (system === 'latn') return s;\n if (!SUPPORTED_NUMBERING_SYSTEMS.has(system)) {\n throw new InvalidLocaleError({ actual: system, reason: `numbering system \"${system}\" is not supported.` });\n }\n const map = getDigitMap(system);\n // just flip the map around\n const reverse: Record<string, string> = {};\n for (const k of Object.keys(map)) reverse[map[k]!] = k;\n let result = '';\n for (const ch of s) {\n result += reverse[ch] ?? ch;\n }\n return result;\n}\n\n// FormatOptions plus a numberingSystem field. pass { numberingSystem: 'arab' }\n// to format() to get Arabic-Indic digits out, or { numberingSystem: 'auto' }\n// to use whichever numeral system the call's locale itself defaults to\n// (ar-EG -> arab, bn-BD -> beng, en-US -> latn), resolved via\n// Intl.NumberFormat(locale).resolvedOptions().numberingSystem with a\n// 'latn' fallback for locales whose native system isn't supported here.\n// Unset still means 'latn' — 'auto' is an opt-in, not a default change.\nexport interface NumberingFormatOptions extends FormatOptions {\n numberingSystem?: NumberingSystemOption;\n}\n\n// same idea but for the parse side. called parseNumberingSystem instead of\n// just numberingSystem so someone mixing format() and parse() options in\n// one config object can set both independently — the two directions\n// aren't always symmetric (you might want native digits out without\n// wanting to accept them back in, or vice versa). 'auto' works here too,\n// resolving from the parse call's own locale the same way the format\n// side does.\nexport interface NumberingParseOptions extends FormatOptions {\n parseNumberingSystem?: NumberingSystemOption;\n}\n\n// format-path helper: takes format()'s ASCII output and converts digits\n// if numberingSystem was asked for. lives here so format.ts doesn't need\n// to know anything about numbering systems\nexport function applyNumbering(s: string, options: NumberingFormatOptions): string {\n const system = resolveRequestedSystem(options.numberingSystem, options.locale);\n if (system === 'latn') return s;\n return convertDigits(s, system);\n}\n\n// parse-path helper: converts input digits to ASCII before matching, if\n// parseNumberingSystem got set. kept as a separate option name from the\n// format side so callers can be explicit about which direction they\n// actually want transliterated\nexport function applyParseNumbering(s: string, options: { parseNumberingSystem?: string; locale?: string }): string {\n // both call sites for this (both in parse.ts) already guard with\n // `if (options.parseNumberingSystem)` before calling, so an undefined\n // parseNumberingSystem never actually reaches here from parse() itself —\n // the undefined handling inside resolveRequestedSystem is dead by\n // construction from that direction. leaving it in as a safety net\n // rather than betting every future caller replicates the same guard\n // (this is a public export; direct calls don't come pre-guarded).\n const system = resolveRequestedSystem(options.parseNumberingSystem, options.locale);\n if (system === 'latn') return s;\n return convertDigitsToAscii(s, system);\n}"],"mappings":"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","names":[]}
|