@bbn/bbn 2.0.23 → 2.0.25
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/bbn.js +1 -1
- package/dist/bbn.js.map +1 -1
- package/dist/dt/functions/buildLocaleFromIntl.d.ts +1 -0
- package/dist/dt/functions/buildLocaleFromIntl.js +37 -0
- package/dist/dt/functions/parse.d.ts +7 -0
- package/dist/dt/functions/parse.js +527 -0
- package/dist/dt.d.ts +14 -0
- package/dist/dt.js +201 -0
- package/dist/index.js +2 -0
- package/package.json +4 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function buildLocaleFromIntl(): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import extend from "../../fn/object/extend.js";
|
|
2
|
+
import numProperties from "../../fn/object/numProperties.js";
|
|
3
|
+
export default function buildLocaleFromIntl() {
|
|
4
|
+
if (numProperties(bbn.dt.locales)) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
const langs = [bbn.env.lang, ...navigator.languages];
|
|
8
|
+
const fmtMonthLong = new Intl.DateTimeFormat(langs, { month: 'long' });
|
|
9
|
+
const fmtMonthShort = new Intl.DateTimeFormat(langs, { month: 'short' });
|
|
10
|
+
const fmtWeekLong = new Intl.DateTimeFormat(langs, { weekday: 'long' });
|
|
11
|
+
const fmtWeekShort = new Intl.DateTimeFormat(langs, { weekday: 'short' });
|
|
12
|
+
// Create 12 dates for months (2020 chosen arbitrarily)
|
|
13
|
+
const monthsLong = [];
|
|
14
|
+
const monthsShort = [];
|
|
15
|
+
for (let m = 0; m < 12; m++) {
|
|
16
|
+
const d = new Date(2020, m, 1);
|
|
17
|
+
monthsLong.push(fmtMonthLong.format(d));
|
|
18
|
+
monthsShort.push(fmtMonthShort.format(d));
|
|
19
|
+
}
|
|
20
|
+
// Create 7 dates for weekdays (starting from Sunday 2020-02-02 which *is* Sunday)
|
|
21
|
+
// 2020-02-02 is Sunday → guarantees stable weekday list
|
|
22
|
+
const baseSunday = new Date(2020, 1, 2); // YYYY, MM (0-based), DD
|
|
23
|
+
const weekdaysLong = [];
|
|
24
|
+
const weekdaysShort = [];
|
|
25
|
+
for (let i = 0; i < 7; i++) {
|
|
26
|
+
const d = new Date(baseSunday.getTime() + i * 86400000);
|
|
27
|
+
weekdaysLong.push(fmtWeekLong.format(d));
|
|
28
|
+
weekdaysShort.push(fmtWeekShort.format(d));
|
|
29
|
+
}
|
|
30
|
+
extend(bbn.dt.locales, {
|
|
31
|
+
monthsLong,
|
|
32
|
+
monthsShort,
|
|
33
|
+
weekdaysLong,
|
|
34
|
+
weekdaysShort,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Temporal } from 'temporal-polyfill';
|
|
2
|
+
export default function parse(input: string, format: string | string[], locale?: {
|
|
3
|
+
monthsLong?: string[];
|
|
4
|
+
monthsShort?: string[];
|
|
5
|
+
weekdaysLong?: string[];
|
|
6
|
+
weekdaysShort?: string[];
|
|
7
|
+
}): Temporal.Instant | Temporal.PlainDateTime | Temporal.PlainDate | Temporal.PlainTime | Temporal.PlainYearMonth | Temporal.PlainMonthDay;
|
|
@@ -0,0 +1,527 @@
|
|
|
1
|
+
import buildLocaleFromIntl from './buildLocaleFromIntl.js';
|
|
2
|
+
export default function parse(input, format, locale) {
|
|
3
|
+
var _a, _b, _c, _d;
|
|
4
|
+
buildLocaleFromIntl();
|
|
5
|
+
const TemporalAny = globalThis.Temporal;
|
|
6
|
+
if (!TemporalAny) {
|
|
7
|
+
throw new Error('Temporal API is required (load @js-temporal/polyfill)');
|
|
8
|
+
}
|
|
9
|
+
const T = TemporalAny;
|
|
10
|
+
const loc = {
|
|
11
|
+
monthsLong: (_a = locale === null || locale === void 0 ? void 0 : locale.monthsLong) !== null && _a !== void 0 ? _a : bbn.dt.locales.monthsLong,
|
|
12
|
+
monthsShort: (_b = locale === null || locale === void 0 ? void 0 : locale.monthsShort) !== null && _b !== void 0 ? _b : bbn.dt.locales.monthsShort,
|
|
13
|
+
weekdaysLong: (_c = locale === null || locale === void 0 ? void 0 : locale.weekdaysLong) !== null && _c !== void 0 ? _c : bbn.dt.locales.weekdaysLong,
|
|
14
|
+
weekdaysShort: (_d = locale === null || locale === void 0 ? void 0 : locale.weekdaysShort) !== null && _d !== void 0 ? _d : bbn.dt.locales.weekdaysShort
|
|
15
|
+
};
|
|
16
|
+
const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
+
const makeTokenSpecs = () => [
|
|
18
|
+
// Years
|
|
19
|
+
{
|
|
20
|
+
token: 'YYYY',
|
|
21
|
+
regex: '\\d{4}',
|
|
22
|
+
apply: (v, ctx) => {
|
|
23
|
+
ctx.year = parseInt(v, 10);
|
|
24
|
+
ctx.hasYear = true;
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
token: 'YY',
|
|
29
|
+
regex: '\\d{2}',
|
|
30
|
+
apply: (v, ctx) => {
|
|
31
|
+
const n = parseInt(v, 10);
|
|
32
|
+
ctx.year = n >= 70 ? 1900 + n : 2000 + n;
|
|
33
|
+
ctx.hasYear = true;
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
token: 'Y',
|
|
38
|
+
regex: '[+-]?\\d{1,6}',
|
|
39
|
+
apply: (v, ctx) => {
|
|
40
|
+
ctx.year = parseInt(v, 10);
|
|
41
|
+
ctx.hasYear = true;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
// Months
|
|
45
|
+
{
|
|
46
|
+
token: 'MMMM',
|
|
47
|
+
regex: '[^\\d\\s]+',
|
|
48
|
+
apply: (v, ctx) => {
|
|
49
|
+
const idx = loc.monthsLong
|
|
50
|
+
.findIndex((m) => m.toLowerCase() === v.toLowerCase());
|
|
51
|
+
if (idx === -1) {
|
|
52
|
+
throw new Error('Invalid month name: ' + v);
|
|
53
|
+
}
|
|
54
|
+
ctx.month = idx + 1;
|
|
55
|
+
ctx.hasMonth = true;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
token: 'MMM',
|
|
60
|
+
regex: '[^\\d\\s]+',
|
|
61
|
+
apply: (v, ctx) => {
|
|
62
|
+
const idx = loc.monthsShort
|
|
63
|
+
.findIndex((m) => m.toLowerCase() === v.toLowerCase());
|
|
64
|
+
if (idx === -1) {
|
|
65
|
+
throw new Error('Invalid short month name: ' + v);
|
|
66
|
+
}
|
|
67
|
+
ctx.month = idx + 1;
|
|
68
|
+
ctx.hasMonth = true;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
token: 'MM',
|
|
73
|
+
regex: '\\d{2}',
|
|
74
|
+
apply: (v, ctx) => {
|
|
75
|
+
const n = parseInt(v, 10);
|
|
76
|
+
if (n < 1 || n > 12) {
|
|
77
|
+
throw new Error('Invalid month: ' + n);
|
|
78
|
+
}
|
|
79
|
+
ctx.month = n;
|
|
80
|
+
ctx.hasMonth = true;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
token: 'mm',
|
|
85
|
+
regex: '\\d{2}',
|
|
86
|
+
apply: (v, ctx) => {
|
|
87
|
+
const n = parseInt(v, 10);
|
|
88
|
+
if (n < 0 || n > 59) {
|
|
89
|
+
throw new Error('Invalid minute: ' + n);
|
|
90
|
+
}
|
|
91
|
+
// NOTE: in your original code this wrote to month, but name suggests minutes.
|
|
92
|
+
// I'm keeping original behavior, but you might want to correct this.
|
|
93
|
+
ctx.month = n;
|
|
94
|
+
ctx.hasMonth = true;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
token: 'M',
|
|
99
|
+
regex: '\\d{1,2}',
|
|
100
|
+
apply: (v, ctx) => {
|
|
101
|
+
const n = parseInt(v, 10);
|
|
102
|
+
if (n < 1 || n > 12) {
|
|
103
|
+
throw new Error('Invalid month: ' + n);
|
|
104
|
+
}
|
|
105
|
+
ctx.month = n;
|
|
106
|
+
ctx.hasMonth = true;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
token: 'm', // PHP-like month
|
|
111
|
+
regex: '\\d{2}',
|
|
112
|
+
apply: (v, ctx) => {
|
|
113
|
+
const n = parseInt(v, 10);
|
|
114
|
+
if (n < 1 || n > 12) {
|
|
115
|
+
throw new Error('Invalid month: ' + n);
|
|
116
|
+
}
|
|
117
|
+
ctx.month = n;
|
|
118
|
+
ctx.hasMonth = true;
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
// Day of month
|
|
122
|
+
{
|
|
123
|
+
token: 'DD',
|
|
124
|
+
regex: '\\d{2}',
|
|
125
|
+
apply: (v, ctx) => {
|
|
126
|
+
const n = parseInt(v, 10);
|
|
127
|
+
if (n < 1 || n > 31) {
|
|
128
|
+
throw new Error('Invalid day of month: ' + n);
|
|
129
|
+
}
|
|
130
|
+
ctx.day = n;
|
|
131
|
+
ctx.hasDay = true;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
token: 'D',
|
|
136
|
+
regex: '\\d{1,2}',
|
|
137
|
+
apply: (v, ctx) => {
|
|
138
|
+
const n = parseInt(v, 10);
|
|
139
|
+
if (n < 1 || n > 31) {
|
|
140
|
+
throw new Error('Invalid day of month: ' + n);
|
|
141
|
+
}
|
|
142
|
+
ctx.day = n;
|
|
143
|
+
ctx.hasDay = true;
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
token: 'd', // PHP-like day-of-month
|
|
148
|
+
regex: '\\d{2}',
|
|
149
|
+
apply: (v, ctx) => {
|
|
150
|
+
const n = parseInt(v, 10);
|
|
151
|
+
if (n < 1 || n > 31) {
|
|
152
|
+
throw new Error('Invalid day of month: ' + n);
|
|
153
|
+
}
|
|
154
|
+
ctx.day = n;
|
|
155
|
+
ctx.hasDay = true;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
// Weekday (validated only, not used for construction)
|
|
159
|
+
{
|
|
160
|
+
token: 'dddd',
|
|
161
|
+
regex: '[^\\d\\s]+',
|
|
162
|
+
apply: (v, ctx) => {
|
|
163
|
+
const idx = loc.weekdaysLong
|
|
164
|
+
.findIndex((w) => w.toLowerCase() === v.toLowerCase());
|
|
165
|
+
if (idx === -1) {
|
|
166
|
+
throw new Error('Invalid weekday name: ' + v);
|
|
167
|
+
}
|
|
168
|
+
ctx.weekday = idx; // 0-6
|
|
169
|
+
}
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
token: 'ddd',
|
|
173
|
+
regex: '[^\\d\\s]+',
|
|
174
|
+
apply: (v, ctx) => {
|
|
175
|
+
const idx = loc.weekdaysShort
|
|
176
|
+
.findIndex((w) => w.toLowerCase() === v.toLowerCase());
|
|
177
|
+
if (idx === -1) {
|
|
178
|
+
throw new Error('Invalid short weekday name: ' + v);
|
|
179
|
+
}
|
|
180
|
+
ctx.weekday = idx;
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
token: 'EE',
|
|
185
|
+
regex: '\\d{1}',
|
|
186
|
+
apply: (v, ctx) => {
|
|
187
|
+
const n = parseInt(v, 10);
|
|
188
|
+
if (n < 0 || n > 7) {
|
|
189
|
+
throw new Error('Invalid weekday number: ' + n);
|
|
190
|
+
}
|
|
191
|
+
ctx.weekday = n;
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
// Hours
|
|
195
|
+
{
|
|
196
|
+
token: 'HH',
|
|
197
|
+
regex: '\\d{2}',
|
|
198
|
+
apply: (v, ctx) => {
|
|
199
|
+
const n = parseInt(v, 10);
|
|
200
|
+
if (n < 0 || n > 23) {
|
|
201
|
+
throw new Error('Invalid hour: ' + n);
|
|
202
|
+
}
|
|
203
|
+
ctx.hour = n;
|
|
204
|
+
ctx.hasHour = true;
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
token: 'H',
|
|
209
|
+
regex: '\\d{1,2}',
|
|
210
|
+
apply: (v, ctx) => {
|
|
211
|
+
const n = parseInt(v, 10);
|
|
212
|
+
if (n < 0 || n > 23) {
|
|
213
|
+
throw new Error('Invalid hour: ' + n);
|
|
214
|
+
}
|
|
215
|
+
ctx.hour = n;
|
|
216
|
+
ctx.hasHour = true;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
token: 'h', // PHP-like 24h alias here
|
|
221
|
+
regex: '\\d{2}',
|
|
222
|
+
apply: (v, ctx) => {
|
|
223
|
+
const n = parseInt(v, 10);
|
|
224
|
+
if (n < 0 || n > 23) {
|
|
225
|
+
throw new Error('Invalid hour: ' + n);
|
|
226
|
+
}
|
|
227
|
+
ctx.hour = n;
|
|
228
|
+
ctx.hasHour = true;
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
// Minutes
|
|
232
|
+
{
|
|
233
|
+
token: 'II',
|
|
234
|
+
regex: '\\d{2}',
|
|
235
|
+
apply: (v, ctx) => {
|
|
236
|
+
const n = parseInt(v, 10);
|
|
237
|
+
if (n < 0 || n > 59) {
|
|
238
|
+
throw new Error('Invalid minute: ' + n);
|
|
239
|
+
}
|
|
240
|
+
ctx.minute = n;
|
|
241
|
+
ctx.hasMinute = true;
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
token: 'I',
|
|
246
|
+
regex: '\\d{1,2}',
|
|
247
|
+
apply: (v, ctx) => {
|
|
248
|
+
const n = parseInt(v, 10);
|
|
249
|
+
if (n < 0 || n > 59) {
|
|
250
|
+
throw new Error('Invalid minute: ' + n);
|
|
251
|
+
}
|
|
252
|
+
ctx.minute = n;
|
|
253
|
+
ctx.hasMinute = true;
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
token: 'i', // PHP-like minutes
|
|
258
|
+
regex: '\\d{2}',
|
|
259
|
+
apply: (v, ctx) => {
|
|
260
|
+
const n = parseInt(v, 10);
|
|
261
|
+
if (n < 0 || n > 59) {
|
|
262
|
+
throw new Error('Invalid minute: ' + n);
|
|
263
|
+
}
|
|
264
|
+
ctx.minute = n;
|
|
265
|
+
ctx.hasMinute = true;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
// Seconds
|
|
269
|
+
{
|
|
270
|
+
token: 'SS',
|
|
271
|
+
regex: '\\d{2}',
|
|
272
|
+
apply: (v, ctx) => {
|
|
273
|
+
const n = parseInt(v, 10);
|
|
274
|
+
if (n < 0 || n > 59) {
|
|
275
|
+
throw new Error('Invalid second: ' + n);
|
|
276
|
+
}
|
|
277
|
+
ctx.second = n;
|
|
278
|
+
ctx.hasSecond = true;
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
token: 'S',
|
|
283
|
+
regex: '\\d{1,2}',
|
|
284
|
+
apply: (v, ctx) => {
|
|
285
|
+
const n = parseInt(v, 10);
|
|
286
|
+
if (n < 0 || n > 59) {
|
|
287
|
+
throw new Error('Invalid second: ' + n);
|
|
288
|
+
}
|
|
289
|
+
ctx.second = n;
|
|
290
|
+
ctx.hasSecond = true;
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
token: 's', // PHP-like seconds
|
|
295
|
+
regex: '\\d{2}',
|
|
296
|
+
apply: (v, ctx) => {
|
|
297
|
+
const n = parseInt(v, 10);
|
|
298
|
+
if (n < 0 || n > 59) {
|
|
299
|
+
throw new Error('Invalid second: ' + n);
|
|
300
|
+
}
|
|
301
|
+
ctx.second = n;
|
|
302
|
+
ctx.hasSecond = true;
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
// Milliseconds
|
|
306
|
+
{
|
|
307
|
+
token: 'ms',
|
|
308
|
+
regex: '\\d{1,3}',
|
|
309
|
+
apply: (v, ctx) => {
|
|
310
|
+
const n = parseInt(v, 10);
|
|
311
|
+
if (n < 0 || n > 999) {
|
|
312
|
+
throw new Error('Invalid millisecond: ' + n);
|
|
313
|
+
}
|
|
314
|
+
ctx.ms = n;
|
|
315
|
+
ctx.hasMs = true;
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
// Week (parsed, not used yet)
|
|
319
|
+
{
|
|
320
|
+
token: 'WWWW',
|
|
321
|
+
regex: '\\d{1,2}',
|
|
322
|
+
apply: (v, ctx) => {
|
|
323
|
+
const n = parseInt(v, 10);
|
|
324
|
+
if (n < 1 || n > 53) {
|
|
325
|
+
throw new Error('Invalid week number: ' + n);
|
|
326
|
+
}
|
|
327
|
+
ctx.week = n;
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
token: 'WWW',
|
|
332
|
+
regex: '\\d{1,2}',
|
|
333
|
+
apply: (v, ctx) => {
|
|
334
|
+
const n = parseInt(v, 10);
|
|
335
|
+
if (n < 1 || n > 53) {
|
|
336
|
+
throw new Error('Invalid week number: ' + n);
|
|
337
|
+
}
|
|
338
|
+
ctx.week = n;
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
token: 'WW',
|
|
343
|
+
regex: '\\d{1,2}',
|
|
344
|
+
apply: (v, ctx) => {
|
|
345
|
+
const n = parseInt(v, 10);
|
|
346
|
+
if (n < 1 || n > 53) {
|
|
347
|
+
throw new Error('Invalid week number: ' + n);
|
|
348
|
+
}
|
|
349
|
+
ctx.week = n;
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
token: 'W',
|
|
354
|
+
regex: '\\d{1,2}',
|
|
355
|
+
apply: (v, ctx) => {
|
|
356
|
+
const n = parseInt(v, 10);
|
|
357
|
+
if (n < 1 || n > 53) {
|
|
358
|
+
throw new Error('Invalid week number: ' + n);
|
|
359
|
+
}
|
|
360
|
+
ctx.week = n;
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
// Timezone offset (Z)
|
|
364
|
+
{
|
|
365
|
+
token: 'Z',
|
|
366
|
+
regex: '(?:Z|[+-]\\d{2}:?\\d{2})',
|
|
367
|
+
apply: (v, ctx) => {
|
|
368
|
+
if (v === 'Z' || v === 'z') {
|
|
369
|
+
ctx.offsetMinutes = 0;
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const sign = v[0] === '-' ? -1 : 1;
|
|
373
|
+
const rest = v.slice(1); // "02:00" or "0500"
|
|
374
|
+
let hh;
|
|
375
|
+
let mm;
|
|
376
|
+
if (rest.includes(':')) {
|
|
377
|
+
const [h, m] = rest.split(':');
|
|
378
|
+
hh = parseInt(h, 10);
|
|
379
|
+
mm = parseInt(m, 10);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
hh = parseInt(rest.slice(0, 2), 10);
|
|
383
|
+
mm = parseInt(rest.slice(2, 4), 10);
|
|
384
|
+
}
|
|
385
|
+
if (hh < 0 || hh > 23 || mm < 0 || mm > 59) {
|
|
386
|
+
throw new Error('Invalid timezone offset: ' + v);
|
|
387
|
+
}
|
|
388
|
+
ctx.offsetMinutes = sign * (hh * 60 + mm);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
// Timezone name (z) – IANA like "Europe/Rome"
|
|
392
|
+
{
|
|
393
|
+
token: 'z',
|
|
394
|
+
regex: '[A-Za-z_\\/]+',
|
|
395
|
+
apply: (v, ctx) => {
|
|
396
|
+
ctx.timeZone = v;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
];
|
|
400
|
+
function parseWithFormat(fmt) {
|
|
401
|
+
var _a;
|
|
402
|
+
const ctx = {
|
|
403
|
+
year: 1970,
|
|
404
|
+
month: 1,
|
|
405
|
+
day: 1,
|
|
406
|
+
hour: 0,
|
|
407
|
+
minute: 0,
|
|
408
|
+
second: 0,
|
|
409
|
+
ms: 0,
|
|
410
|
+
hasYear: false,
|
|
411
|
+
hasMonth: false,
|
|
412
|
+
hasDay: false,
|
|
413
|
+
hasHour: false,
|
|
414
|
+
hasMinute: false,
|
|
415
|
+
hasSecond: false,
|
|
416
|
+
hasMs: false
|
|
417
|
+
};
|
|
418
|
+
const tokenSpecs = makeTokenSpecs();
|
|
419
|
+
const tokensByLength = [...tokenSpecs].sort((a, b) => b.token.length - a.token.length);
|
|
420
|
+
let pattern = '';
|
|
421
|
+
const applyFns = [];
|
|
422
|
+
let i = 0;
|
|
423
|
+
while (i < fmt.length) {
|
|
424
|
+
let matchedToken = null;
|
|
425
|
+
for (const spec of tokensByLength) {
|
|
426
|
+
if (fmt.startsWith(spec.token, i)) {
|
|
427
|
+
matchedToken = spec;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (matchedToken) {
|
|
432
|
+
pattern += `(${matchedToken.regex})`;
|
|
433
|
+
if (matchedToken.apply) {
|
|
434
|
+
applyFns.push(value => matchedToken.apply(value, ctx));
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
applyFns.push(() => { });
|
|
438
|
+
}
|
|
439
|
+
i += matchedToken.token.length;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
pattern += escapeRegex(fmt[i]);
|
|
443
|
+
i += 1;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const fullRegex = new RegExp('^' + pattern + '$');
|
|
447
|
+
const match = fullRegex.exec(input);
|
|
448
|
+
if (!match) {
|
|
449
|
+
throw new Error(`Date string "${input}" does not match format "${fmt}"`);
|
|
450
|
+
}
|
|
451
|
+
for (let idx = 1; idx < match.length; idx++) {
|
|
452
|
+
const value = match[idx];
|
|
453
|
+
const apply = applyFns[idx - 1];
|
|
454
|
+
if (value != null && apply) {
|
|
455
|
+
apply(value);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const hasDate = ctx.hasYear || ctx.hasMonth || ctx.hasDay;
|
|
459
|
+
const hasFullDate = ctx.hasYear && ctx.hasMonth && ctx.hasDay;
|
|
460
|
+
const hasYearMonthOnly = ctx.hasYear && ctx.hasMonth && !ctx.hasDay;
|
|
461
|
+
const hasMonthDayOnly = !ctx.hasYear && ctx.hasMonth && ctx.hasDay;
|
|
462
|
+
const hasTime = ctx.hasHour || ctx.hasMinute || ctx.hasSecond || ctx.hasMs;
|
|
463
|
+
const hasZone = ctx.timeZone != null || ctx.offsetMinutes != null;
|
|
464
|
+
// ---------- 1) If timezone (Z or z) → Instant ----------
|
|
465
|
+
if (hasZone) {
|
|
466
|
+
// Fill date/time with whatever we have + defaults (1970-01-01 etc.)
|
|
467
|
+
let pdt;
|
|
468
|
+
try {
|
|
469
|
+
pdt = new T.PlainDateTime(ctx.year, ctx.month, ctx.day, ctx.hour, ctx.minute, ctx.second, ctx.ms * 1000000);
|
|
470
|
+
}
|
|
471
|
+
catch (_b) {
|
|
472
|
+
throw new Error('Invalid date/time components');
|
|
473
|
+
}
|
|
474
|
+
if (ctx.timeZone) {
|
|
475
|
+
const tz = T.TimeZone.from(ctx.timeZone);
|
|
476
|
+
const zdt = pdt.toZonedDateTime(tz);
|
|
477
|
+
return zdt.toInstant();
|
|
478
|
+
}
|
|
479
|
+
// offsetMinutes only
|
|
480
|
+
const utcMs = Date.UTC(ctx.year, ctx.month - 1, ctx.day, ctx.hour, ctx.minute, ctx.second, ctx.ms);
|
|
481
|
+
const epochMs = utcMs - ((_a = ctx.offsetMinutes) !== null && _a !== void 0 ? _a : 0) * 60000;
|
|
482
|
+
return T.Instant.fromEpochMilliseconds(epochMs);
|
|
483
|
+
}
|
|
484
|
+
// ---------- 2) No timezone: decide which Plain* type ----------
|
|
485
|
+
if (hasDate && hasTime) {
|
|
486
|
+
// Full DateTime (even if some date fields defaulted; we require full date)
|
|
487
|
+
if (!hasFullDate) {
|
|
488
|
+
throw new Error('PlainDateTime requires year, month and day');
|
|
489
|
+
}
|
|
490
|
+
return new T.PlainDateTime(ctx.year, ctx.month, ctx.day, ctx.hour, ctx.minute, ctx.second, ctx.ms * 1000000);
|
|
491
|
+
}
|
|
492
|
+
if (hasDate && !hasTime) {
|
|
493
|
+
if (hasFullDate) {
|
|
494
|
+
return new T.PlainDate(ctx.year, ctx.month, ctx.day);
|
|
495
|
+
}
|
|
496
|
+
if (hasYearMonthOnly) {
|
|
497
|
+
return new T.PlainYearMonth(ctx.year, ctx.month);
|
|
498
|
+
}
|
|
499
|
+
if (hasMonthDayOnly) {
|
|
500
|
+
// Reference year: 1972 is often used (leap year)
|
|
501
|
+
return new T.PlainMonthDay(ctx.month, ctx.day, 1972);
|
|
502
|
+
}
|
|
503
|
+
// e.g. only year → ambiguous, you can decide another behavior if you want
|
|
504
|
+
throw new Error('Not enough date components for a known Temporal type');
|
|
505
|
+
}
|
|
506
|
+
if (!hasDate && hasTime) {
|
|
507
|
+
// PlainTime
|
|
508
|
+
return new T.PlainTime(ctx.hour, ctx.minute, ctx.second, ctx.ms * 1000000);
|
|
509
|
+
}
|
|
510
|
+
throw new Error('No date or time information found in input');
|
|
511
|
+
}
|
|
512
|
+
// ---------- Handle single format or array of formats ----------
|
|
513
|
+
if (Array.isArray(format)) {
|
|
514
|
+
let lastError = null;
|
|
515
|
+
for (const fmt of format) {
|
|
516
|
+
try {
|
|
517
|
+
return parseWithFormat(fmt);
|
|
518
|
+
}
|
|
519
|
+
catch (e) {
|
|
520
|
+
lastError = e;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
throw lastError !== null && lastError !== void 0 ? lastError : new Error('No format matched');
|
|
524
|
+
}
|
|
525
|
+
return parseWithFormat(format);
|
|
526
|
+
}
|
|
527
|
+
;
|
package/dist/dt.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import parse from './dt/functions/parse.js';
|
|
2
|
+
declare const dt: {
|
|
3
|
+
(value: any, inputFormat?: null | String): void;
|
|
4
|
+
locales: any;
|
|
5
|
+
parse: typeof parse;
|
|
6
|
+
time(): void;
|
|
7
|
+
date(): void;
|
|
8
|
+
dateTime(): void;
|
|
9
|
+
duration(): void;
|
|
10
|
+
zoned(): void;
|
|
11
|
+
monthDay(): void;
|
|
12
|
+
yearMonth(): void;
|
|
13
|
+
};
|
|
14
|
+
export default dt;
|