temporal-fmt 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +480 -9
- package/dist/calendarUtils.cjs +259 -4
- package/dist/calendarUtils.cjs.map +1 -1
- package/dist/calendarUtils.js +33 -1
- package/dist/chunk-4N3WCGEY.js +183 -0
- package/dist/{chunk-4JWGUR4O.js.map → chunk-4N3WCGEY.js.map} +1 -1
- package/dist/chunk-5UTV5VP6.js +984 -0
- package/dist/chunk-5UTV5VP6.js.map +1 -0
- package/dist/chunk-ACKKWH5Z.js +578 -0
- package/dist/{chunk-2JHEV7ZF.js.map → chunk-ACKKWH5Z.js.map} +1 -1
- package/dist/chunk-EGUUO6LE.js +439 -0
- package/dist/chunk-EGUUO6LE.js.map +1 -0
- package/dist/chunk-FBPHNRVW.js +2939 -0
- package/dist/chunk-FBPHNRVW.js.map +1 -0
- package/dist/chunk-GPB4JHGI.js +65 -0
- package/dist/chunk-GPB4JHGI.js.map +1 -0
- package/dist/chunk-H7YQX25T.js +170 -0
- package/dist/{chunk-J2AQNXF2.js.map → chunk-H7YQX25T.js.map} +1 -1
- package/dist/chunk-HXY2GUUM.js +182 -0
- package/dist/{chunk-EHLRZULM.js.map → chunk-HXY2GUUM.js.map} +1 -1
- package/dist/chunk-L24NPTAJ.js +328 -0
- package/dist/chunk-L24NPTAJ.js.map +1 -0
- package/dist/chunk-M3GDTHMT.js +169 -0
- package/dist/chunk-M3GDTHMT.js.map +1 -0
- package/dist/chunk-MKPDLQKD.js +51 -0
- package/dist/chunk-MKPDLQKD.js.map +1 -0
- package/dist/chunk-TSLPIURC.js +242 -0
- package/dist/{chunk-VQXUMFB2.js.map → chunk-TSLPIURC.js.map} +1 -1
- package/dist/chunk-UOPAV3WX.js +75 -0
- package/dist/chunk-UOPAV3WX.js.map +1 -0
- package/dist/chunk-VNIUIQA4.js +398 -0
- package/dist/chunk-VNIUIQA4.js.map +1 -0
- package/dist/chunk-YEUASGDK.js +9 -0
- package/dist/chunk-YEUASGDK.js.map +1 -0
- package/dist/chunk-ZQZF5EXW.js +29 -0
- package/dist/chunk-ZQZF5EXW.js.map +1 -0
- package/dist/config.d.cts +4 -2
- package/dist/config.d.ts +4 -2
- package/dist/duration.cjs +638 -26
- package/dist/duration.cjs.map +1 -1
- package/dist/duration.js +28 -1
- package/dist/format.cjs +833 -35
- package/dist/format.cjs.map +1 -1
- package/dist/format.js +20 -1
- package/dist/index.cjs +7698 -163
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +108 -24
- package/dist/index.d.ts +108 -24
- package/dist/index.js +1536 -58
- package/dist/index.js.map +1 -1
- package/dist/interval.cjs +5480 -35
- package/dist/interval.cjs.map +1 -1
- package/dist/interval.js +46 -1
- package/dist/localeRegistry.cjs +375 -32
- package/dist/localeRegistry.cjs.map +1 -1
- package/dist/localeRegistry.js +11 -1
- package/dist/modApi.d.cts +131 -0
- package/dist/modApi.d.ts +131 -0
- package/dist/parse.cjs +1797 -70
- package/dist/parse.cjs.map +1 -1
- package/dist/parse.js +20 -1
- package/dist/pattern.d.cts +1 -0
- package/dist/pattern.d.ts +1 -0
- package/dist/recurrence.cjs +452 -20
- package/dist/recurrence.cjs.map +1 -1
- package/dist/recurrence.js +19 -1
- package/dist/relativeTime.cjs +268 -21
- package/dist/relativeTime.cjs.map +1 -1
- package/dist/relativeTime.js +14 -1
- package/dist/runtime.d.cts +201 -0
- package/dist/runtime.d.ts +201 -0
- package/dist/timezone.cjs +387 -20
- package/dist/timezone.cjs.map +1 -1
- package/dist/timezone.js +26 -1
- package/package.json +4 -6
- package/scripts/cli.mjs +27 -5
- package/dist/chunk-2JHEV7ZF.js +0 -7
- package/dist/chunk-3MZLTVP3.js +0 -2
- package/dist/chunk-3MZLTVP3.js.map +0 -1
- package/dist/chunk-4JWGUR4O.js +0 -11
- package/dist/chunk-5U5WJ465.js +0 -36
- package/dist/chunk-5U5WJ465.js.map +0 -1
- package/dist/chunk-C5YESWFT.js +0 -2
- package/dist/chunk-C5YESWFT.js.map +0 -1
- package/dist/chunk-C6ZZ62ET.js +0 -2
- package/dist/chunk-C6ZZ62ET.js.map +0 -1
- package/dist/chunk-EHLRZULM.js +0 -5
- package/dist/chunk-F4RGUDA3.js +0 -2
- package/dist/chunk-F4RGUDA3.js.map +0 -1
- package/dist/chunk-J2AQNXF2.js +0 -2
- package/dist/chunk-NBXF7V5B.js +0 -2
- package/dist/chunk-NBXF7V5B.js.map +0 -1
- package/dist/chunk-R52YOKI3.js +0 -7
- package/dist/chunk-R52YOKI3.js.map +0 -1
- package/dist/chunk-UJR6DHXY.js +0 -2
- package/dist/chunk-UJR6DHXY.js.map +0 -1
- package/dist/chunk-VQXUMFB2.js +0 -21
- package/dist/chunk-XH46JNPK.js +0 -2
- package/dist/chunk-XH46JNPK.js.map +0 -1
- package/dist/chunk-YB6YAG7E.js +0 -35
- package/dist/chunk-YB6YAG7E.js.map +0 -1
- package/dist/chunk-ZGMTY52O.js +0 -2
- package/dist/chunk-ZGMTY52O.js.map +0 -1
package/dist/parse.js
CHANGED
|
@@ -1,2 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
compileParser,
|
|
3
|
+
parse,
|
|
4
|
+
parseToParts,
|
|
5
|
+
safeParse,
|
|
6
|
+
tryParse
|
|
7
|
+
} from "./chunk-5UTV5VP6.js";
|
|
8
|
+
import "./chunk-M3GDTHMT.js";
|
|
9
|
+
import "./chunk-L24NPTAJ.js";
|
|
10
|
+
import "./chunk-ZQZF5EXW.js";
|
|
11
|
+
import "./chunk-YEUASGDK.js";
|
|
12
|
+
import "./chunk-EGUUO6LE.js";
|
|
13
|
+
import "./chunk-MKPDLQKD.js";
|
|
14
|
+
export {
|
|
15
|
+
compileParser,
|
|
16
|
+
parse,
|
|
17
|
+
parseToParts,
|
|
18
|
+
safeParse,
|
|
19
|
+
tryParse
|
|
20
|
+
};
|
|
2
21
|
//# sourceMappingURL=parse.js.map
|
package/dist/pattern.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare function isValidTimeZone(raw: string): boolean;
|
|
2
2
|
export declare const FORMAT_ONLY_TOKENS: Set<string>;
|
|
3
3
|
export declare const DIGIT_LEADING_TOKENS: Set<string>;
|
|
4
|
+
export declare const UNBOUNDED_WIDTH_TOKENS: Set<string>;
|
|
4
5
|
export declare function tokenFragment(token: string, locale: string, nextToken?: string): string;
|
|
5
6
|
export declare const UNPADDED_NUMERIC_TOKENS: Set<string>;
|
|
6
7
|
export declare const UNPADDED_NUMERIC_RANGES: Record<string, Array<{
|
package/dist/pattern.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare function isValidTimeZone(raw: string): boolean;
|
|
2
2
|
export declare const FORMAT_ONLY_TOKENS: Set<string>;
|
|
3
3
|
export declare const DIGIT_LEADING_TOKENS: Set<string>;
|
|
4
|
+
export declare const UNBOUNDED_WIDTH_TOKENS: Set<string>;
|
|
4
5
|
export declare function tokenFragment(token: string, locale: string, nextToken?: string): string;
|
|
5
6
|
export declare const UNPADDED_NUMERIC_TOKENS: Set<string>;
|
|
6
7
|
export declare const UNPADDED_NUMERIC_RANGES: Record<string, Array<{
|
package/dist/recurrence.cjs
CHANGED
|
@@ -1,21 +1,453 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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/recurrence.ts
|
|
21
|
+
var recurrence_exports = {};
|
|
22
|
+
__export(recurrence_exports, {
|
|
23
|
+
between: () => between,
|
|
24
|
+
formatRRule: () => formatRRule,
|
|
25
|
+
parseRRule: () => parseRRule,
|
|
26
|
+
recurrence: () => recurrence,
|
|
27
|
+
skip: () => skip,
|
|
28
|
+
take: () => take
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(recurrence_exports);
|
|
31
|
+
|
|
32
|
+
// src/isoWeek.ts
|
|
33
|
+
function isGregorianLeapYear(year) {
|
|
34
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/calendarUtils.ts
|
|
38
|
+
function requireFields(view, fields) {
|
|
39
|
+
for (const f of fields) {
|
|
40
|
+
if (typeof view[f] !== "number") {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`temporal-fmt: calendar helper requires "${String(f)}", which this value doesn't have. Pass a Temporal.PlainDate / PlainDateTime / ZonedDateTime.`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function daysInMonth(view) {
|
|
48
|
+
requireFields(view, ["year", "month"]);
|
|
49
|
+
const { year, month } = view;
|
|
50
|
+
const LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
51
|
+
if (month === 2 && isGregorianLeapYear(year)) return 29;
|
|
52
|
+
return LENGTHS[month - 1];
|
|
53
|
+
}
|
|
54
|
+
function asDateFieldView(value) {
|
|
55
|
+
if (typeof value !== "object" || value === null) {
|
|
56
|
+
throw new Error(`temporal-fmt: expected a date-carrying Temporal value, got ${String(value)}.`);
|
|
57
|
+
}
|
|
58
|
+
const v = value;
|
|
59
|
+
const out = {};
|
|
60
|
+
if (typeof v.year === "number") out.year = v.year;
|
|
61
|
+
if (typeof v.month === "number") out.month = v.month;
|
|
62
|
+
if (typeof v.day === "number") out.day = v.day;
|
|
63
|
+
if (typeof v.hour === "number") out.hour = v.hour;
|
|
64
|
+
if (typeof v.minute === "number") out.minute = v.minute;
|
|
65
|
+
if (typeof v.second === "number") out.second = v.second;
|
|
66
|
+
if (typeof v.millisecond === "number") out.millisecond = v.millisecond;
|
|
67
|
+
if (typeof v.dayOfWeek === "number") out.dayOfWeek = v.dayOfWeek;
|
|
68
|
+
if (typeof v.calendarId === "string") out.calendarId = v.calendarId;
|
|
69
|
+
if (out.year === void 0 || out.month === void 0 || out.day === void 0) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`temporal-fmt: value is missing year/month/day fields \u2014 pass a Temporal.PlainDate / PlainDateTime / ZonedDateTime.`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/arithmetic.ts
|
|
78
|
+
function asDateTime(value) {
|
|
79
|
+
return asDateFieldView(value);
|
|
80
|
+
}
|
|
81
|
+
function recomputeDayOfWeek(view) {
|
|
82
|
+
if (typeof view.dayOfWeek !== "number") return;
|
|
83
|
+
/* c8 ignore start @preserve -- unreachable: every call site (add()'s
|
|
84
|
+
'years'/'months' cases, shiftDays()) passes a `result` whose
|
|
85
|
+
year/month/day were just explicitly set, and the value originally
|
|
86
|
+
came from asDateTime()/asDateFieldView(), which throws unless
|
|
87
|
+
year/month/day are all present as numbers. So by the time this guard
|
|
88
|
+
runs, all three are guaranteed valid. Kept in case a future caller
|
|
89
|
+
constructs a DateTimeFieldView bypassing that validation. */
|
|
90
|
+
if (typeof view.year !== "number" || typeof view.month !== "number" || typeof view.day !== "number") return;
|
|
91
|
+
/* c8 ignore stop @preserve */
|
|
92
|
+
const jsDow = new Date(Date.UTC(view.year, view.month - 1, view.day)).getUTCDay();
|
|
93
|
+
view.dayOfWeek = jsDow === 0 ? 7 : jsDow;
|
|
94
|
+
}
|
|
95
|
+
function add(value, amount, unit) {
|
|
96
|
+
const v = asDateTime(value);
|
|
97
|
+
let result = { ...v };
|
|
98
|
+
switch (unit) {
|
|
99
|
+
case "years": {
|
|
100
|
+
/* c8 ignore start @preserve -- the `?? 0` fallback is unreachable:
|
|
101
|
+
asDateTime()/asDateFieldView() (called at the top of add()) throws
|
|
102
|
+
unless year is present as a number, so result.year is never
|
|
103
|
+
undefined here. Kept as a guard against a future change that
|
|
104
|
+
relaxes that validation. */
|
|
105
|
+
result.year = (result.year ?? 0) + amount;
|
|
106
|
+
/* c8 ignore stop @preserve */
|
|
107
|
+
const maxDay = daysInMonth({ year: result.year, month: result.month });
|
|
108
|
+
if (result.day > maxDay) result.day = maxDay;
|
|
109
|
+
recomputeDayOfWeek(result);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "months": {
|
|
113
|
+
/* c8 ignore start @preserve -- both `??` fallbacks are unreachable
|
|
114
|
+
for the same reason as the 'years' case above: asDateFieldView()
|
|
115
|
+
guarantees year and month are present numbers before add() ever
|
|
116
|
+
reaches here. */
|
|
117
|
+
const total = (result.year ?? 0) * 12 + (result.month ?? 1) - 1 + amount;
|
|
118
|
+
/* c8 ignore stop @preserve */
|
|
119
|
+
result.year = Math.floor(total / 12);
|
|
120
|
+
result.month = total % 12 + 1;
|
|
121
|
+
if (result.month < 1) {
|
|
122
|
+
result.month += 12;
|
|
123
|
+
result.year -= 1;
|
|
124
|
+
}
|
|
125
|
+
/* c8 ignore start @preserve -- unreachable: (total % 12) + 1 can never
|
|
126
|
+
exceed 12 for any integer total in JS (its range is [-10, 12] since
|
|
127
|
+
JS's % can return a negative remainder but never one with
|
|
128
|
+
magnitude >= 12, so adding 1 tops out at 12). Only the < 1 branch
|
|
129
|
+
above is reachable; this was written symmetrically with it but the
|
|
130
|
+
overflow direction it guards against can't occur. Kept rather than
|
|
131
|
+
removed since it costs nothing and documents the intent. */
|
|
132
|
+
if (result.month > 12) {
|
|
133
|
+
result.month -= 12;
|
|
134
|
+
result.year += 1;
|
|
135
|
+
}
|
|
136
|
+
/* c8 ignore stop @preserve */
|
|
137
|
+
const maxDay = daysInMonth({ year: result.year, month: result.month });
|
|
138
|
+
if (result.day > maxDay) result.day = maxDay;
|
|
139
|
+
recomputeDayOfWeek(result);
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case "weeks":
|
|
143
|
+
result = shiftDays(result, amount * 7);
|
|
144
|
+
break;
|
|
145
|
+
case "days":
|
|
146
|
+
result = shiftDays(result, amount);
|
|
147
|
+
break;
|
|
148
|
+
case "hours":
|
|
149
|
+
result = shiftTime(result, amount * 36e5);
|
|
150
|
+
break;
|
|
151
|
+
case "minutes":
|
|
152
|
+
result = shiftTime(result, amount * 6e4);
|
|
153
|
+
break;
|
|
154
|
+
case "seconds":
|
|
155
|
+
result = shiftTime(result, amount * 1e3);
|
|
156
|
+
break;
|
|
157
|
+
case "milliseconds":
|
|
158
|
+
result = shiftTime(result, amount);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
function shiftDays(v, days) {
|
|
164
|
+
const y = v.year, m = v.month, d = v.day;
|
|
165
|
+
const y2 = m <= 2 ? y - 1 : y;
|
|
166
|
+
const era = Math.floor((y2 >= 0 ? y2 : y2 - 399) / 400);
|
|
167
|
+
const yoe = y2 - era * 400;
|
|
168
|
+
const m2 = m > 2 ? m - 3 : m + 9;
|
|
169
|
+
const doy = Math.floor((153 * m2 + 2) / 5) + d - 1;
|
|
170
|
+
const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy;
|
|
171
|
+
const totalDays = era * 146097 + doe - 719468 + days;
|
|
172
|
+
const z = totalDays + 719468;
|
|
173
|
+
const era2 = Math.floor((z >= 0 ? z : z - 146096) / 146097);
|
|
174
|
+
const doe2 = z - era2 * 146097;
|
|
175
|
+
const yoe2 = Math.floor((doe2 - Math.floor(doe2 / 1460) + Math.floor(doe2 / 36524) - Math.floor(doe2 / 146096)) / 365);
|
|
176
|
+
const y2out = yoe2 + era2 * 400;
|
|
177
|
+
const doy2 = doe2 - (365 * yoe2 + Math.floor(yoe2 / 4) - Math.floor(yoe2 / 100));
|
|
178
|
+
const mp = Math.floor((5 * doy2 + 2) / 153);
|
|
179
|
+
const d2 = doy2 - Math.floor((153 * mp + 2) / 5) + 1;
|
|
180
|
+
const m2out = mp < 10 ? mp + 3 : mp - 9;
|
|
181
|
+
const yOut = m2out <= 2 ? y2out + 1 : y2out;
|
|
182
|
+
const result = { ...v, year: yOut, month: m2out, day: d2 };
|
|
183
|
+
recomputeDayOfWeek(result);
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
function shiftTime(v, msDelta) {
|
|
187
|
+
const MS_PER_DAY = 864e5;
|
|
188
|
+
const MS_PER_HOUR = 36e5;
|
|
189
|
+
const MS_PER_MINUTE = 6e4;
|
|
190
|
+
const MS_PER_SECOND = 1e3;
|
|
191
|
+
const totalMs = (v.hour ?? 0) * MS_PER_HOUR + (v.minute ?? 0) * MS_PER_MINUTE + (v.second ?? 0) * MS_PER_SECOND + (v.millisecond ?? 0) + msDelta;
|
|
192
|
+
const dayOverflow = Math.floor(totalMs / MS_PER_DAY);
|
|
193
|
+
let withinDay = totalMs % MS_PER_DAY;
|
|
194
|
+
if (withinDay < 0) {
|
|
195
|
+
withinDay += MS_PER_DAY;
|
|
196
|
+
}
|
|
197
|
+
const hour = Math.floor(withinDay / MS_PER_HOUR);
|
|
198
|
+
const minute = Math.floor(withinDay % MS_PER_HOUR / MS_PER_MINUTE);
|
|
199
|
+
const second = Math.floor(withinDay % MS_PER_MINUTE / MS_PER_SECOND);
|
|
200
|
+
const millisecond = withinDay % MS_PER_SECOND;
|
|
201
|
+
const result = { ...v, hour, minute, second, millisecond };
|
|
202
|
+
if (dayOverflow !== 0) {
|
|
203
|
+
return shiftDays(result, dayOverflow);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/comparison.ts
|
|
209
|
+
function toComparableMs(view) {
|
|
210
|
+
const y = view.year, m = view.month, d = view.day;
|
|
211
|
+
const y2 = m <= 2 ? y - 1 : y;
|
|
212
|
+
const era = Math.floor((y2 >= 0 ? y2 : y2 - 399) / 400);
|
|
213
|
+
const yoe = y2 - era * 400;
|
|
214
|
+
const m2 = m > 2 ? m - 3 : m + 9;
|
|
215
|
+
const doy = Math.floor((153 * m2 + 2) / 5) + d - 1;
|
|
216
|
+
const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy;
|
|
217
|
+
const days = era * 146097 + doe - 719468;
|
|
218
|
+
const MS_PER_HOUR = 36e5;
|
|
219
|
+
const MS_PER_MINUTE = 6e4;
|
|
220
|
+
const MS_PER_SECOND = 1e3;
|
|
221
|
+
return days * 864e5 + (view.hour ?? 0) * MS_PER_HOUR + (view.minute ?? 0) * MS_PER_MINUTE + (view.second ?? 0) * MS_PER_SECOND + (view.millisecond ?? 0);
|
|
222
|
+
}
|
|
223
|
+
function asDateTimeFieldView(value) {
|
|
224
|
+
const v = asDateFieldView(value);
|
|
225
|
+
return v;
|
|
226
|
+
}
|
|
227
|
+
function compare(a, b) {
|
|
228
|
+
const av = asDateTimeFieldView(a);
|
|
229
|
+
const bv = asDateTimeFieldView(b);
|
|
230
|
+
const am = toComparableMs(av);
|
|
231
|
+
const bm = toComparableMs(bv);
|
|
232
|
+
if (am < bm) return -1;
|
|
233
|
+
if (am > bm) return 1;
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// src/recurrence.ts
|
|
238
|
+
function recurrence(start, rule) {
|
|
239
|
+
let current = start;
|
|
240
|
+
let count = 0;
|
|
241
|
+
const history = [];
|
|
242
|
+
const MAX_HISTORY = 1e4;
|
|
243
|
+
let atEnd = false;
|
|
244
|
+
let atStart = true;
|
|
245
|
+
function matches(value) {
|
|
246
|
+
const v = value;
|
|
247
|
+
if (rule.byWeekday && rule.byWeekday.length > 0) {
|
|
248
|
+
if (!rule.byWeekday.includes(v.dayOfWeek ?? 0)) return false;
|
|
249
|
+
}
|
|
250
|
+
if (rule.byMonthDay && rule.byMonthDay.length > 0) {
|
|
251
|
+
if (!rule.byMonthDay.includes(v.day ?? 0)) return false;
|
|
252
|
+
}
|
|
253
|
+
if (rule.byMonth && rule.byMonth.length > 0) {
|
|
254
|
+
if (!rule.byMonth.includes(v.month ?? 0)) return false;
|
|
255
|
+
}
|
|
256
|
+
if (rule.exDates && rule.exDates.some((d) => compare(d, value) === 0)) return false;
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
function advance(value, steps) {
|
|
260
|
+
const unit = rule.frequency === "secondly" ? "seconds" : rule.frequency === "minutely" ? "minutes" : rule.frequency === "hourly" ? "hours" : rule.frequency === "daily" ? "days" : rule.frequency === "weekly" ? "weeks" : rule.frequency === "monthly" ? "months" : "years";
|
|
261
|
+
return add(value, steps * rule.interval, unit);
|
|
262
|
+
}
|
|
263
|
+
function recordHistory(value) {
|
|
264
|
+
history.push(value);
|
|
265
|
+
if (history.length > MAX_HISTORY) history.shift();
|
|
266
|
+
}
|
|
267
|
+
function nextMatch(value) {
|
|
268
|
+
let candidate = value;
|
|
269
|
+
let safetyCounter = 0;
|
|
270
|
+
do {
|
|
271
|
+
candidate = advance(candidate, 1);
|
|
272
|
+
safetyCounter++;
|
|
273
|
+
if (safetyCounter > 1e3) {
|
|
274
|
+
atEnd = true;
|
|
275
|
+
return { value: candidate, found: false };
|
|
276
|
+
}
|
|
277
|
+
if (rule.until && compare(candidate, rule.until) > 0) {
|
|
278
|
+
atEnd = true;
|
|
279
|
+
return { value: candidate, found: false };
|
|
280
|
+
}
|
|
281
|
+
} while (!matches(candidate));
|
|
282
|
+
return { value: candidate, found: true };
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
next() {
|
|
286
|
+
if (atEnd) return { value: void 0, done: true };
|
|
287
|
+
if (atStart) {
|
|
288
|
+
atStart = false;
|
|
289
|
+
if (matches(current)) {
|
|
290
|
+
count++;
|
|
291
|
+
if (rule.count !== void 0 && count >= rule.count) atEnd = true;
|
|
292
|
+
if (rule.until && compare(current, rule.until) > 0) {
|
|
293
|
+
atEnd = true;
|
|
294
|
+
return { value: void 0, done: true };
|
|
295
|
+
}
|
|
296
|
+
recordHistory(current);
|
|
297
|
+
return { value: current, done: false };
|
|
298
|
+
}
|
|
299
|
+
const advanced2 = nextMatch(current);
|
|
300
|
+
if (!advanced2.found) return { value: void 0, done: true };
|
|
301
|
+
current = advanced2.value;
|
|
302
|
+
count++;
|
|
303
|
+
if (rule.count !== void 0 && count >= rule.count) atEnd = true;
|
|
304
|
+
recordHistory(current);
|
|
305
|
+
return { value: current, done: false };
|
|
306
|
+
}
|
|
307
|
+
const advanced = nextMatch(current);
|
|
308
|
+
if (!advanced.found) return { value: void 0, done: true };
|
|
309
|
+
current = advanced.value;
|
|
310
|
+
count++;
|
|
311
|
+
if (rule.count !== void 0 && count >= rule.count) atEnd = true;
|
|
312
|
+
recordHistory(current);
|
|
313
|
+
return { value: current, done: false };
|
|
314
|
+
},
|
|
315
|
+
previous() {
|
|
316
|
+
if (history.length === 0) return { value: void 0, done: true };
|
|
317
|
+
const v = history.pop();
|
|
318
|
+
return { value: v, done: false };
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function take(iter, n) {
|
|
323
|
+
const result = [];
|
|
324
|
+
for (let i = 0; i < n; i++) {
|
|
325
|
+
const r = iter.next();
|
|
326
|
+
if (r.done) break;
|
|
327
|
+
result.push(r.value);
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
var MAX_SKIP_COLLECTION = 1e5;
|
|
332
|
+
function skip(iter, n) {
|
|
333
|
+
for (let i = 0; i < n; i++) {
|
|
334
|
+
const r = iter.next();
|
|
335
|
+
if (r.done) break;
|
|
336
|
+
}
|
|
337
|
+
const result = [];
|
|
338
|
+
while (result.length < MAX_SKIP_COLLECTION) {
|
|
339
|
+
const r = iter.next();
|
|
340
|
+
if (r.done) return result;
|
|
341
|
+
result.push(r.value);
|
|
342
|
+
}
|
|
343
|
+
throw new RangeError(
|
|
344
|
+
`temporal-fmt: skip() collected ${MAX_SKIP_COLLECTION} occurrences and the rule is still producing \u2014 add a count or until to the rule, or use take(iter, n) for a bounded read.`
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
function between(start, rule, rangeStart, rangeEnd) {
|
|
348
|
+
const iter = recurrence(start, rule);
|
|
349
|
+
const result = [];
|
|
350
|
+
while (true) {
|
|
351
|
+
const r = iter.next();
|
|
352
|
+
if (r.done) break;
|
|
353
|
+
if (compare(r.value, rangeEnd) >= 0) break;
|
|
354
|
+
if (compare(r.value, rangeStart) >= 0) result.push(r.value);
|
|
355
|
+
}
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
358
|
+
function parseRRule(input) {
|
|
359
|
+
const parts = input.trim().toUpperCase().replace(/^RRULE:/, "").split(";");
|
|
360
|
+
const rule = { frequency: "daily", interval: 1 };
|
|
361
|
+
const frequencies = /* @__PURE__ */ new Set([
|
|
362
|
+
"SECONDLY",
|
|
363
|
+
"MINUTELY",
|
|
364
|
+
"HOURLY",
|
|
365
|
+
"DAILY",
|
|
366
|
+
"WEEKLY",
|
|
367
|
+
"MONTHLY",
|
|
368
|
+
"YEARLY"
|
|
369
|
+
]);
|
|
370
|
+
for (const part of parts) {
|
|
371
|
+
if (!part) continue;
|
|
372
|
+
const eq = part.indexOf("=");
|
|
373
|
+
if (eq < 0) continue;
|
|
374
|
+
const key = part.slice(0, eq);
|
|
375
|
+
const value = part.slice(eq + 1);
|
|
376
|
+
switch (key) {
|
|
377
|
+
case "FREQ":
|
|
378
|
+
if (!frequencies.has(value)) {
|
|
379
|
+
throw new RangeError(`temporal-fmt: unsupported RRULE frequency "${value}".`);
|
|
380
|
+
}
|
|
381
|
+
rule.frequency = value.toLowerCase();
|
|
382
|
+
break;
|
|
383
|
+
case "INTERVAL": {
|
|
384
|
+
const interval = Number(value);
|
|
385
|
+
if (!Number.isSafeInteger(interval) || interval < 1) {
|
|
386
|
+
throw new RangeError(`temporal-fmt: RRULE INTERVAL must be a positive safe integer (got "${value}").`);
|
|
387
|
+
}
|
|
388
|
+
rule.interval = interval;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
case "COUNT": {
|
|
392
|
+
const count = Number(value);
|
|
393
|
+
if (!Number.isSafeInteger(count) || count < 1) {
|
|
394
|
+
throw new RangeError(`temporal-fmt: RRULE COUNT must be a positive safe integer (got "${value}").`);
|
|
395
|
+
}
|
|
396
|
+
rule.count = count;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
case "UNTIL":
|
|
400
|
+
rule.until = value;
|
|
401
|
+
break;
|
|
402
|
+
case "BYDAY":
|
|
403
|
+
rule.byWeekday = value.split(",").map((d) => {
|
|
404
|
+
const m = d.match(/^([+-]?\d)?([A-Z]{2})$/);
|
|
405
|
+
if (!m) return 0;
|
|
406
|
+
const wd = m[2];
|
|
407
|
+
const map = { MO: 1, TU: 2, WE: 3, TH: 4, FR: 5, SA: 6, SU: 7 };
|
|
408
|
+
return map[wd] ?? 0;
|
|
409
|
+
});
|
|
410
|
+
break;
|
|
411
|
+
case "BYMONTHDAY": {
|
|
412
|
+
const values = value.split(",").map(Number);
|
|
413
|
+
if (values.some((day) => !Number.isInteger(day) || day === 0 || day < -31 || day > 31)) {
|
|
414
|
+
throw new RangeError(`temporal-fmt: RRULE BYMONTHDAY contains an out-of-range value.`);
|
|
415
|
+
}
|
|
416
|
+
rule.byMonthDay = values;
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
case "BYMONTH": {
|
|
420
|
+
const values = value.split(",").map(Number);
|
|
421
|
+
if (values.some((month) => !Number.isInteger(month) || month < 1 || month > 12)) {
|
|
422
|
+
throw new RangeError(`temporal-fmt: RRULE BYMONTH contains an out-of-range value.`);
|
|
423
|
+
}
|
|
424
|
+
rule.byMonth = values;
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return rule;
|
|
430
|
+
}
|
|
431
|
+
function formatRRule(rule) {
|
|
432
|
+
const parts = [`FREQ=${rule.frequency.toUpperCase()}`];
|
|
433
|
+
if (rule.interval !== 1) parts.push(`INTERVAL=${rule.interval}`);
|
|
434
|
+
if (rule.count !== void 0) parts.push(`COUNT=${rule.count}`);
|
|
435
|
+
if (rule.until !== void 0) parts.push(`UNTIL=${String(rule.until)}`);
|
|
436
|
+
if (rule.byWeekday && rule.byWeekday.length > 0) {
|
|
437
|
+
const map = { 1: "MO", 2: "TU", 3: "WE", 4: "TH", 5: "FR", 6: "SA", 7: "SU" };
|
|
438
|
+
parts.push(`BYDAY=${rule.byWeekday.map((d) => map[d]).join(",")}`);
|
|
439
|
+
}
|
|
440
|
+
if (rule.byMonthDay && rule.byMonthDay.length > 0) parts.push(`BYMONTHDAY=${rule.byMonthDay.join(",")}`);
|
|
441
|
+
if (rule.byMonth && rule.byMonth.length > 0) parts.push(`BYMONTH=${rule.byMonth.join(",")}`);
|
|
442
|
+
return parts.join(";");
|
|
443
|
+
}
|
|
444
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
445
|
+
0 && (module.exports = {
|
|
446
|
+
between,
|
|
447
|
+
formatRRule,
|
|
448
|
+
parseRRule,
|
|
449
|
+
recurrence,
|
|
450
|
+
skip,
|
|
451
|
+
take
|
|
452
|
+
});
|
|
21
453
|
//# sourceMappingURL=recurrence.cjs.map
|