@optique/temporal 1.0.0-dev.1136 → 1.0.0-dev.1155

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/dist/index.cjs CHANGED
@@ -148,6 +148,64 @@ function zonedDateTime(options = {}) {
148
148
  };
149
149
  }
150
150
  /**
151
+ * Optional RFC 9557 calendar annotation suffix, e.g. `[u-ca=gregory]`.
152
+ * Accepts case-insensitive values and the optional critical flag (`!`).
153
+ * Used by all plain Temporal regexes to accept `toString()` output for
154
+ * non-ISO calendars.
155
+ */
156
+ const CALENDAR_ANNOTATION = String.raw`(\[!?u-ca=[a-zA-Z0-9\-]+\])?`;
157
+ /**
158
+ * Required RFC 9557 calendar annotation (non-optional variant used when the
159
+ * annotation must be present, e.g. for reference-day/year forms).
160
+ */
161
+ const CALENDAR_ANNOTATION_REQUIRED = String.raw`\[!?u-ca=[a-zA-Z0-9\-]+\]`;
162
+ /**
163
+ * Year portion: either 4 digits (`YYYY`) or a sign-prefixed 6-digit expanded
164
+ * year (`+YYYYYY` / `-YYYYYY`).
165
+ */
166
+ const YEAR = String.raw`([+-]\d{6}|\d{4})`;
167
+ /** ISO 8601 fractional seconds with `.` or `,` separator. */
168
+ const FRACTIONAL = String.raw`[.,]\d+`;
169
+ /** Extended date: `YYYY-MM-DD` or `±YYYYYY-MM-DD`. */
170
+ const DATE_EXTENDED = `${YEAR}-\\d{2}-\\d{2}`;
171
+ /** Basic date: `YYYYMMDD` or `±YYYYYYMMDD`. */
172
+ const DATE_BASIC = `${YEAR}\\d{4}`;
173
+ /** Extended time: `HH:MM[:SS[.frac]]`. */
174
+ const TIME_EXTENDED = `\\d{2}:\\d{2}(:\\d{2}(${FRACTIONAL})?)?`;
175
+ /** Basic time: `HH`, `HHMM`, or `HHMMSS[.frac]`. */
176
+ const TIME_BASIC = `\\d{2}(\\d{2}(\\d{2}(${FRACTIONAL})?)?)?`;
177
+ /**
178
+ * Matches YYYY-MM-DD (extended) or YYYYMMDD (basic) date forms only (no time
179
+ * component). Both forms accept expanded years and calendar annotations.
180
+ */
181
+ const PLAIN_DATE_RE = /* @__PURE__ */ new RegExp(`^(${DATE_EXTENDED}|${DATE_BASIC})${CALENDAR_ANNOTATION}$`);
182
+ /**
183
+ * Matches time forms only (no date prefix). Accepts extended
184
+ * (`HH:MM[:SS[.frac]]`), basic (`HH`, `HHMM`, `HHMMSS[.frac]`), and
185
+ * `T`-prefixed variants. Calendar annotations are accepted for consistency
186
+ * with `Temporal.PlainTime.from()` on polyfill runtimes.
187
+ */
188
+ const PLAIN_TIME_RE = /* @__PURE__ */ new RegExp(`^[Tt]?(${TIME_EXTENDED}|${TIME_BASIC})${CALENDAR_ANNOTATION}$`);
189
+ /**
190
+ * Matches date-time strings with both date and time parts. Accepts extended,
191
+ * basic, and mixed forms (e.g. `2020-01-23T170436`). The separator may be
192
+ * `T`, `t`, or a space. The time portion may be reduced-precision (hour
193
+ * only).
194
+ */
195
+ const PLAIN_DATETIME_RE = /* @__PURE__ */ new RegExp(`^(${DATE_EXTENDED}|${DATE_BASIC})[Tt ](${TIME_EXTENDED}|${TIME_BASIC})${CALENDAR_ANNOTATION}$`);
196
+ /**
197
+ * Matches YYYY-MM (extended) or YYYYMM (basic), or a full date
198
+ * (extended or basic) with a required calendar annotation (the reference day
199
+ * is emitted by `toString()` for non-ISO calendars).
200
+ */
201
+ const PLAIN_YEAR_MONTH_RE = /* @__PURE__ */ new RegExp(`^(${YEAR}-\\d{2}(${CALENDAR_ANNOTATION}|-\\d{2}${CALENDAR_ANNOTATION_REQUIRED})|${YEAR}\\d{2}(${CALENDAR_ANNOTATION}|\\d{2}${CALENDAR_ANNOTATION_REQUIRED}))$`);
202
+ /**
203
+ * Matches MM-DD, --MM-DD, MMDD, or --MMDD month-day forms, or a full date
204
+ * (extended or basic) with a required calendar annotation (the reference year
205
+ * is emitted by `toString()` for non-ISO calendars).
206
+ */
207
+ const PLAIN_MONTH_DAY_RE = /* @__PURE__ */ new RegExp(`^((--)?(\\d{2}-\\d{2}|\\d{4})${CALENDAR_ANNOTATION}|(${DATE_EXTENDED}|${DATE_BASIC})${CALENDAR_ANNOTATION_REQUIRED})$`);
208
+ /**
151
209
  * Creates a ValueParser for parsing Temporal.PlainDate from ISO 8601 date strings.
152
210
  *
153
211
  * Accepts strings like:
@@ -169,6 +227,7 @@ function plainDate(options = {}) {
169
227
  parse(input) {
170
228
  ensureTemporal();
171
229
  try {
230
+ if (!PLAIN_DATE_RE.test(input)) throw new RangeError();
172
231
  const value = Temporal.PlainDate.from(input);
173
232
  return {
174
233
  success: true,
@@ -208,6 +267,7 @@ function plainTime(options = {}) {
208
267
  parse(input) {
209
268
  ensureTemporal();
210
269
  try {
270
+ if (!PLAIN_TIME_RE.test(input)) throw new RangeError();
211
271
  const value = Temporal.PlainTime.from(input);
212
272
  return {
213
273
  success: true,
@@ -247,6 +307,7 @@ function plainDateTime(options = {}) {
247
307
  parse(input) {
248
308
  ensureTemporal();
249
309
  try {
310
+ if (!PLAIN_DATETIME_RE.test(input)) throw new RangeError();
250
311
  const value = Temporal.PlainDateTime.from(input);
251
312
  return {
252
313
  success: true,
@@ -286,6 +347,7 @@ function plainYearMonth(options = {}) {
286
347
  parse(input) {
287
348
  ensureTemporal();
288
349
  try {
350
+ if (!PLAIN_YEAR_MONTH_RE.test(input)) throw new RangeError();
289
351
  const value = Temporal.PlainYearMonth.from(input);
290
352
  return {
291
353
  success: true,
@@ -325,6 +387,7 @@ function plainMonthDay(options = {}) {
325
387
  parse(input) {
326
388
  ensureTemporal();
327
389
  try {
390
+ if (!PLAIN_MONTH_DAY_RE.test(input)) throw new RangeError();
328
391
  const value = Temporal.PlainMonthDay.from(input);
329
392
  return {
330
393
  success: true,
package/dist/index.js CHANGED
@@ -125,6 +125,64 @@ function zonedDateTime(options = {}) {
125
125
  };
126
126
  }
127
127
  /**
128
+ * Optional RFC 9557 calendar annotation suffix, e.g. `[u-ca=gregory]`.
129
+ * Accepts case-insensitive values and the optional critical flag (`!`).
130
+ * Used by all plain Temporal regexes to accept `toString()` output for
131
+ * non-ISO calendars.
132
+ */
133
+ const CALENDAR_ANNOTATION = String.raw`(\[!?u-ca=[a-zA-Z0-9\-]+\])?`;
134
+ /**
135
+ * Required RFC 9557 calendar annotation (non-optional variant used when the
136
+ * annotation must be present, e.g. for reference-day/year forms).
137
+ */
138
+ const CALENDAR_ANNOTATION_REQUIRED = String.raw`\[!?u-ca=[a-zA-Z0-9\-]+\]`;
139
+ /**
140
+ * Year portion: either 4 digits (`YYYY`) or a sign-prefixed 6-digit expanded
141
+ * year (`+YYYYYY` / `-YYYYYY`).
142
+ */
143
+ const YEAR = String.raw`([+-]\d{6}|\d{4})`;
144
+ /** ISO 8601 fractional seconds with `.` or `,` separator. */
145
+ const FRACTIONAL = String.raw`[.,]\d+`;
146
+ /** Extended date: `YYYY-MM-DD` or `±YYYYYY-MM-DD`. */
147
+ const DATE_EXTENDED = `${YEAR}-\\d{2}-\\d{2}`;
148
+ /** Basic date: `YYYYMMDD` or `±YYYYYYMMDD`. */
149
+ const DATE_BASIC = `${YEAR}\\d{4}`;
150
+ /** Extended time: `HH:MM[:SS[.frac]]`. */
151
+ const TIME_EXTENDED = `\\d{2}:\\d{2}(:\\d{2}(${FRACTIONAL})?)?`;
152
+ /** Basic time: `HH`, `HHMM`, or `HHMMSS[.frac]`. */
153
+ const TIME_BASIC = `\\d{2}(\\d{2}(\\d{2}(${FRACTIONAL})?)?)?`;
154
+ /**
155
+ * Matches YYYY-MM-DD (extended) or YYYYMMDD (basic) date forms only (no time
156
+ * component). Both forms accept expanded years and calendar annotations.
157
+ */
158
+ const PLAIN_DATE_RE = /* @__PURE__ */ new RegExp(`^(${DATE_EXTENDED}|${DATE_BASIC})${CALENDAR_ANNOTATION}$`);
159
+ /**
160
+ * Matches time forms only (no date prefix). Accepts extended
161
+ * (`HH:MM[:SS[.frac]]`), basic (`HH`, `HHMM`, `HHMMSS[.frac]`), and
162
+ * `T`-prefixed variants. Calendar annotations are accepted for consistency
163
+ * with `Temporal.PlainTime.from()` on polyfill runtimes.
164
+ */
165
+ const PLAIN_TIME_RE = /* @__PURE__ */ new RegExp(`^[Tt]?(${TIME_EXTENDED}|${TIME_BASIC})${CALENDAR_ANNOTATION}$`);
166
+ /**
167
+ * Matches date-time strings with both date and time parts. Accepts extended,
168
+ * basic, and mixed forms (e.g. `2020-01-23T170436`). The separator may be
169
+ * `T`, `t`, or a space. The time portion may be reduced-precision (hour
170
+ * only).
171
+ */
172
+ const PLAIN_DATETIME_RE = /* @__PURE__ */ new RegExp(`^(${DATE_EXTENDED}|${DATE_BASIC})[Tt ](${TIME_EXTENDED}|${TIME_BASIC})${CALENDAR_ANNOTATION}$`);
173
+ /**
174
+ * Matches YYYY-MM (extended) or YYYYMM (basic), or a full date
175
+ * (extended or basic) with a required calendar annotation (the reference day
176
+ * is emitted by `toString()` for non-ISO calendars).
177
+ */
178
+ const PLAIN_YEAR_MONTH_RE = /* @__PURE__ */ new RegExp(`^(${YEAR}-\\d{2}(${CALENDAR_ANNOTATION}|-\\d{2}${CALENDAR_ANNOTATION_REQUIRED})|${YEAR}\\d{2}(${CALENDAR_ANNOTATION}|\\d{2}${CALENDAR_ANNOTATION_REQUIRED}))$`);
179
+ /**
180
+ * Matches MM-DD, --MM-DD, MMDD, or --MMDD month-day forms, or a full date
181
+ * (extended or basic) with a required calendar annotation (the reference year
182
+ * is emitted by `toString()` for non-ISO calendars).
183
+ */
184
+ const PLAIN_MONTH_DAY_RE = /* @__PURE__ */ new RegExp(`^((--)?(\\d{2}-\\d{2}|\\d{4})${CALENDAR_ANNOTATION}|(${DATE_EXTENDED}|${DATE_BASIC})${CALENDAR_ANNOTATION_REQUIRED})$`);
185
+ /**
128
186
  * Creates a ValueParser for parsing Temporal.PlainDate from ISO 8601 date strings.
129
187
  *
130
188
  * Accepts strings like:
@@ -146,6 +204,7 @@ function plainDate(options = {}) {
146
204
  parse(input) {
147
205
  ensureTemporal();
148
206
  try {
207
+ if (!PLAIN_DATE_RE.test(input)) throw new RangeError();
149
208
  const value = Temporal.PlainDate.from(input);
150
209
  return {
151
210
  success: true,
@@ -185,6 +244,7 @@ function plainTime(options = {}) {
185
244
  parse(input) {
186
245
  ensureTemporal();
187
246
  try {
247
+ if (!PLAIN_TIME_RE.test(input)) throw new RangeError();
188
248
  const value = Temporal.PlainTime.from(input);
189
249
  return {
190
250
  success: true,
@@ -224,6 +284,7 @@ function plainDateTime(options = {}) {
224
284
  parse(input) {
225
285
  ensureTemporal();
226
286
  try {
287
+ if (!PLAIN_DATETIME_RE.test(input)) throw new RangeError();
227
288
  const value = Temporal.PlainDateTime.from(input);
228
289
  return {
229
290
  success: true,
@@ -263,6 +324,7 @@ function plainYearMonth(options = {}) {
263
324
  parse(input) {
264
325
  ensureTemporal();
265
326
  try {
327
+ if (!PLAIN_YEAR_MONTH_RE.test(input)) throw new RangeError();
266
328
  const value = Temporal.PlainYearMonth.from(input);
267
329
  return {
268
330
  success: true,
@@ -302,6 +364,7 @@ function plainMonthDay(options = {}) {
302
364
  parse(input) {
303
365
  ensureTemporal();
304
366
  try {
367
+ if (!PLAIN_MONTH_DAY_RE.test(input)) throw new RangeError();
305
368
  const value = Temporal.PlainMonthDay.from(input);
306
369
  return {
307
370
  success: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/temporal",
3
- "version": "1.0.0-dev.1136+00dc9aa5",
3
+ "version": "1.0.0-dev.1155+7532f28d",
4
4
  "description": "Temporal value parsers for Optique",
5
5
  "keywords": [
6
6
  "CLI",
@@ -56,7 +56,7 @@
56
56
  "sideEffects": false,
57
57
  "dependencies": {
58
58
  "@js-temporal/polyfill": "^0.5.1",
59
- "@optique/core": "1.0.0-dev.1136+00dc9aa5"
59
+ "@optique/core": "1.0.0-dev.1155+7532f28d"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/node": "^20.19.9",