@fr0st/datetime 5.0.0

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.
@@ -0,0 +1,660 @@
1
+ import { formatDay, formatMonth, formatNumber, formatOffset } from './format.js';
2
+ import { parseDay, parseDayPeriod, parseEra, parseMonth, parseNumber } from './parse.js';
3
+ import { getType } from './utility.js';
4
+ import { getDayPeriods, getDays, getEras, getMonths, numberRegExp } from './values.js';
5
+
6
+ /**
7
+ * DateFormatter Format Data
8
+ */
9
+
10
+ export default {
11
+
12
+ /* ERA */
13
+
14
+ G: {
15
+ key: 'era',
16
+ maxLength: 5,
17
+ regex: (locale, length) => {
18
+ const type = getType(length);
19
+ return getEras(locale, type).join('|');
20
+ },
21
+ input: (locale, value, length) => {
22
+ const type = getType(length);
23
+ return parseEra(locale, value, type);
24
+ },
25
+ output: (datetime, length) => {
26
+ const type = getType(length);
27
+ return datetime.era(type);
28
+ },
29
+ },
30
+
31
+ /* YEAR */
32
+
33
+ // year
34
+ y: {
35
+ key: 'year',
36
+ regex: (locale) => numberRegExp(locale),
37
+ input: (locale, value, length) => {
38
+ value = parseNumber(locale, value);
39
+
40
+ if (length !== 2 || `${value}`.length !== 2) {
41
+ return value;
42
+ }
43
+
44
+ return value > 40 ?
45
+ 1900 + value :
46
+ 2000 + value;
47
+ },
48
+ output: (datetime, length) => {
49
+ let year = datetime.getYear();
50
+ if (length === 2) {
51
+ year = `${year}`.slice(-2);
52
+ }
53
+ return formatNumber(
54
+ datetime.getLocale(),
55
+ Math.abs(year),
56
+ length,
57
+ );
58
+ },
59
+ },
60
+
61
+ // week year
62
+ Y: {
63
+ key: 'weekYear',
64
+ regex: (locale) => numberRegExp(locale),
65
+ input: (locale, value, length) => {
66
+ value = parseNumber(locale, value);
67
+
68
+ if (length !== 2 || `${value}`.length !== 2) {
69
+ return value;
70
+ }
71
+
72
+ return value > 40 ?
73
+ 1900 + value :
74
+ 2000 + value;
75
+ },
76
+ output: (datetime, length) => {
77
+ let year = datetime.getWeekYear();
78
+ if (length === 2) {
79
+ year = `${year}`.slice(-2);
80
+ }
81
+ return formatNumber(
82
+ datetime.getLocale(),
83
+ Math.abs(year),
84
+ length,
85
+ );
86
+ },
87
+ },
88
+
89
+ /* QUARTER */
90
+
91
+ // quarter
92
+ Q: {
93
+ key: 'quarter',
94
+ regex: (locale) => numberRegExp(locale),
95
+ input: (locale, value) => parseNumber(locale, value),
96
+ output: (datetime, length) =>
97
+ formatNumber(
98
+ datetime.getLocale(),
99
+ datetime.getQuarter(),
100
+ length,
101
+ ),
102
+ },
103
+
104
+ // quarter (standalone)
105
+ q: {
106
+ key: 'quarter',
107
+ regex: (locale) => numberRegExp(locale),
108
+ input: (locale, value) => parseNumber(locale, value),
109
+ output: (datetime, length) =>
110
+ formatNumber(
111
+ datetime.getLocale(),
112
+ datetime.getQuarter(),
113
+ length,
114
+ ),
115
+ },
116
+
117
+ /* MONTH */
118
+
119
+ // month
120
+ M: {
121
+ key: 'month',
122
+ regex: (locale, length) => {
123
+ switch (length) {
124
+ case 5:
125
+ case 4:
126
+ case 3:
127
+ const type = getType(length);
128
+ return getMonths(locale, type, false).join('|');
129
+ default:
130
+ return numberRegExp(locale);
131
+ }
132
+ },
133
+ input: (locale, value, length) => {
134
+ switch (length) {
135
+ case 5:
136
+ return null;
137
+ case 4:
138
+ case 3:
139
+ const type = getType(length);
140
+ return parseMonth(locale, value, type, false);
141
+ default:
142
+ return parseNumber(locale, value);
143
+ }
144
+ },
145
+ output: (datetime, length) => {
146
+ const locale = datetime.getLocale();
147
+ const month = datetime.getMonth();
148
+ switch (length) {
149
+ case 5:
150
+ case 4:
151
+ case 3:
152
+ const type = getType(length);
153
+ return formatMonth(locale, month, type, false);
154
+ default:
155
+ return formatNumber(locale, month, length);
156
+ }
157
+ },
158
+ },
159
+
160
+ // month (standalone)
161
+ L: {
162
+ key: 'month',
163
+ regex: (locale, length) => {
164
+ switch (length) {
165
+ case 5:
166
+ case 4:
167
+ case 3:
168
+ const type = getType(length);
169
+ return getMonths(locale, type).join('|');
170
+ default:
171
+ return numberRegExp(locale);
172
+ }
173
+ },
174
+ input: (locale, value, length) => {
175
+ switch (length) {
176
+ case 5:
177
+ return null;
178
+ case 4:
179
+ case 3:
180
+ const type = getType(length);
181
+ return parseMonth(locale, value, type);
182
+ default:
183
+ return parseNumber(locale, value);
184
+ }
185
+ },
186
+ output: (datetime, length) => {
187
+ const locale = datetime.getLocale();
188
+ const month = datetime.getMonth();
189
+ switch (length) {
190
+ case 5:
191
+ case 4:
192
+ case 3:
193
+ const type = getType(length);
194
+ return formatMonth(locale, month, type);
195
+ default:
196
+ return formatNumber(locale, month, length);
197
+ }
198
+ },
199
+ },
200
+
201
+ /* WEEK */
202
+
203
+ // local week
204
+ w: {
205
+ key: 'week',
206
+ regex: (locale) => numberRegExp(locale),
207
+ input: (locale, value) => parseNumber(locale, value),
208
+ output: (datetime, length) =>
209
+ formatNumber(
210
+ datetime.getLocale(),
211
+ datetime.getWeek(),
212
+ length,
213
+ ),
214
+ },
215
+
216
+ // local week of month
217
+ W: {
218
+ key: 'weekOfMonth',
219
+ regex: (locale) => numberRegExp(locale),
220
+ input: (locale, value) => parseNumber(locale, value),
221
+ output: (datetime) =>
222
+ formatNumber(
223
+ datetime.getLocale(),
224
+ datetime.getWeekOfMonth(),
225
+ ),
226
+ },
227
+
228
+ /* DAY */
229
+
230
+ // day of month
231
+ d: {
232
+ key: 'date',
233
+ regex: (locale) => numberRegExp(locale),
234
+ input: (locale, value) => parseNumber(locale, value),
235
+ output: (datetime, length) =>
236
+ formatNumber(
237
+ datetime.getLocale(),
238
+ datetime.getDate(),
239
+ length,
240
+ ),
241
+ },
242
+
243
+ // day of year
244
+ D: {
245
+ key: 'dayOfYear',
246
+ regex: (locale) => numberRegExp(locale),
247
+ input: (locale, value) => parseNumber(locale, value),
248
+ output: (datetime, length) =>
249
+ formatNumber(
250
+ datetime.getLocale(),
251
+ datetime.getDayOfYear(),
252
+ length,
253
+ ),
254
+ },
255
+
256
+ // day of week in month
257
+ F: {
258
+ key: 'weekDayInMonth',
259
+ regex: (locale) => numberRegExp(locale),
260
+ input: (locale, value) => parseNumber(locale, value),
261
+ output: (datetime) =>
262
+ formatNumber(
263
+ datetime.getLocale(),
264
+ datetime.getWeekDayInMonth(),
265
+ ),
266
+ },
267
+
268
+ // week day name
269
+ E: {
270
+ key: 'weekDay',
271
+ regex: (locale, length) => {
272
+ const type = getType(length);
273
+ return getDays(locale, type, false).join('|');
274
+ },
275
+ input: (locale, value, length) => {
276
+ if (length === 5) {
277
+ return null;
278
+ }
279
+
280
+ const type = getType(length);
281
+ return parseDay(locale, value, type, false);
282
+ },
283
+ output: (datetime, length) => {
284
+ const type = getType(length);
285
+ const locale = datetime.getLocale();
286
+ const day = datetime.getDay();
287
+ return formatDay(locale, day, type, false);
288
+ },
289
+ },
290
+
291
+ // week day
292
+ e: {
293
+ key: 'weekDay',
294
+ maxLength: 5,
295
+ regex: (locale, length) => {
296
+ switch (length) {
297
+ case 5:
298
+ case 4:
299
+ case 3:
300
+ const type = getType(length);
301
+ return getDays(locale, type, false).join('|');
302
+ default:
303
+ return numberRegExp(locale);
304
+ }
305
+ },
306
+ input: (locale, value, length) => {
307
+ switch (length) {
308
+ case 5:
309
+ return null;
310
+ case 4:
311
+ case 3:
312
+ const type = getType(length);
313
+ return parseDay(locale, value, type, false);
314
+ default:
315
+ return parseNumber(locale, value);
316
+ }
317
+ },
318
+ output: (datetime, length) => {
319
+ const locale = datetime.getLocale();
320
+ switch (length) {
321
+ case 5:
322
+ case 4:
323
+ case 3:
324
+ const type = getType(length);
325
+ const day = datetime.getDay();
326
+ return formatDay(locale, day, type, false);
327
+ default:
328
+ const weekDay = datetime.getWeekDay();
329
+ return formatNumber(locale, weekDay, length);
330
+ }
331
+ },
332
+ },
333
+
334
+ // week day (standalone)
335
+ c: {
336
+ key: 'weekDay',
337
+ maxLength: 5,
338
+ regex: (locale, length) => {
339
+ switch (length) {
340
+ case 5:
341
+ case 4:
342
+ case 3:
343
+ const type = getType(length);
344
+ return getDays(locale, type).join('|');
345
+ default:
346
+ return numberRegExp(locale);
347
+ }
348
+ },
349
+ input: (locale, value, length) => {
350
+ switch (length) {
351
+ case 5:
352
+ return null;
353
+ case 4:
354
+ case 3:
355
+ const type = getType(length);
356
+ return parseDay(locale, value, type);
357
+ default:
358
+ return parseNumber(locale, value);
359
+ }
360
+ },
361
+ output: (datetime, length) => {
362
+ const locale = datetime.getLocale();
363
+ switch (length) {
364
+ case 5:
365
+ case 4:
366
+ case 3:
367
+ const type = getType(length);
368
+ const day = datetime.getDay();
369
+ return formatDay(locale, day, type);
370
+ default:
371
+ const weekDay = datetime.getWeekDay();
372
+ return formatNumber(locale, weekDay);
373
+ }
374
+ },
375
+ },
376
+
377
+ /* PERIOD */
378
+
379
+ a: {
380
+ key: 'dayPeriod',
381
+ regex: (locale, length) => {
382
+ const type = getType(length);
383
+ return getDayPeriods(locale, type).join('|');
384
+ },
385
+ input: (locale, value, length) => {
386
+ const type = getType(length);
387
+ return parseDayPeriod(locale, value, type);
388
+ },
389
+ output: (datetime, length) => {
390
+ const type = getType(length);
391
+ return datetime.dayPeriod(type);
392
+ },
393
+ },
394
+
395
+ /* HOUR */
396
+
397
+ h: {
398
+ key: 'hours12',
399
+ regex: (locale) => numberRegExp(locale),
400
+ input: (locale, value) => {
401
+ value = parseNumber(locale, value);
402
+ if (value === 12) {
403
+ value = 0;
404
+ }
405
+ return value;
406
+ },
407
+ output: (datetime, length) =>
408
+ formatNumber(
409
+ datetime.getLocale(),
410
+ datetime.getHours() % 12 || 12,
411
+ length,
412
+ ),
413
+ },
414
+
415
+ H: {
416
+ key: 'hours24',
417
+ regex: (locale) => numberRegExp(locale),
418
+ input: (locale, value) => parseNumber(locale, value),
419
+ output: (datetime, length) =>
420
+ formatNumber(
421
+ datetime.getLocale(),
422
+ datetime.getHours(),
423
+ length,
424
+ ),
425
+ },
426
+
427
+ K: {
428
+ key: 'hours12',
429
+ regex: (locale) => numberRegExp(locale),
430
+ input: (locale, value) => parseNumber(locale, value),
431
+ output: (datetime, length) =>
432
+ formatNumber(
433
+ datetime.getLocale(),
434
+ datetime.getHours() % 12,
435
+ length,
436
+ ),
437
+ },
438
+
439
+ k: {
440
+ key: 'hours24',
441
+ regex: (locale) => numberRegExp(locale),
442
+ input: (locale, value) => {
443
+ value = parseNumber(locale, value);
444
+ if (value === 24) {
445
+ value = 0;
446
+ }
447
+ return value;
448
+ },
449
+ output: (datetime, length) =>
450
+ formatNumber(
451
+ datetime.getLocale(),
452
+ datetime.getHours() || 24,
453
+ length,
454
+ ),
455
+ },
456
+
457
+ /* MINUTE */
458
+
459
+ m: {
460
+ key: 'minutes',
461
+ regex: (locale) => numberRegExp(locale),
462
+ input: (locale, value) => parseNumber(locale, value),
463
+ output: (datetime, length) =>
464
+ formatNumber(
465
+ datetime.getLocale(),
466
+ datetime.getMinutes(),
467
+ length,
468
+ ),
469
+ },
470
+
471
+ /* SECOND */
472
+
473
+ s: {
474
+ key: 'seconds',
475
+ regex: (locale) => numberRegExp(locale),
476
+ input: (locale, value) => parseNumber(locale, value),
477
+ output: (datetime, length) =>
478
+ formatNumber(
479
+ datetime.getLocale(),
480
+ datetime.getSeconds(),
481
+ length,
482
+ ),
483
+ },
484
+
485
+ /* FRACTIONAL */
486
+
487
+ S: {
488
+ key: 'milliseconds',
489
+ regex: (locale) => numberRegExp(locale),
490
+ input: (_) => 0,
491
+ output: (datetime, length) =>
492
+ formatNumber(
493
+ datetime.getLocale(),
494
+ `${Math.floor(
495
+ datetime.getMilliseconds() *
496
+ 1000,
497
+ )}`.padEnd(length, '0').slice(0, length),
498
+ ),
499
+ },
500
+
501
+ /* TIMEZONE/OFFSET */
502
+
503
+ z: {
504
+ output: (datetime, length) => {
505
+ if (length === 5) {
506
+ length = 1;
507
+ }
508
+ const type = getType(length);
509
+ return datetime.timeZoneName(type);
510
+ },
511
+ },
512
+
513
+ Z: {
514
+ key: 'timeZone',
515
+ regex: (_, length) => {
516
+ switch (length) {
517
+ case 5:
518
+ return `[\\+\\-]\\d{2}\\:\\d{2}|Z`;
519
+ case 4:
520
+ return `GMT[\\+\\-]\\d{2}\\:\\d{2}|GMT`;
521
+ default:
522
+ return `[\\+\\-]\\d{4}`;
523
+ }
524
+ },
525
+ input: (_, value) => value,
526
+ output: (datetime, length) => {
527
+ const offset = datetime.getTimeZoneOffset();
528
+
529
+ let useColon = true;
530
+ let prefix = '';
531
+ switch (length) {
532
+ case 5:
533
+ if (!offset) {
534
+ return 'Z';
535
+ }
536
+ break;
537
+ case 4:
538
+ prefix = 'GMT';
539
+
540
+ if (!offset) {
541
+ return prefix;
542
+ }
543
+
544
+ break;
545
+ default:
546
+ useColon = false;
547
+ break;
548
+ }
549
+
550
+ return prefix + formatOffset(offset, useColon);
551
+ },
552
+ },
553
+
554
+ O: {
555
+ key: 'timeZone',
556
+ regex: (_, length) => {
557
+ switch (length) {
558
+ case 4:
559
+ return `GMT[\\+\\-]\\d{2}\\:\\d{2}|GMT`;
560
+ default:
561
+ return `GMT[\\+\\-]\\d{2}|GMT`;
562
+ }
563
+ },
564
+ input: (_, value) => value,
565
+ output: (datetime, length) => {
566
+ const offset = datetime.getTimeZoneOffset();
567
+ const prefix = 'GMT';
568
+
569
+ if (!offset) {
570
+ return prefix;
571
+ }
572
+
573
+ let optionalMinutes = false;
574
+ switch (length) {
575
+ case 4:
576
+ break;
577
+ default:
578
+ optionalMinutes = true;
579
+ }
580
+
581
+ return prefix + formatOffset(offset, true, optionalMinutes);
582
+ },
583
+ },
584
+
585
+ V: {
586
+ key: 'timeZone',
587
+ regex: (_) => '([a-zA-Z_\/]+)',
588
+ input: (_, value) => value,
589
+ output: (datetime) => datetime.getTimeZone(),
590
+ },
591
+
592
+ X: {
593
+ key: 'timeZone',
594
+ regex: (_, length) => {
595
+ switch (length) {
596
+ case 5:
597
+ case 3:
598
+ return `[\\+\\-]\\d{2}\\:\\d{2}|Z`;
599
+ case 4:
600
+ case 2:
601
+ return `[\\+\\-]\\d{4}|Z`;
602
+ default:
603
+ return `[\\+\\-]\\d{2}(?:\\d{2})?|Z`;
604
+ }
605
+ },
606
+ input: (_, value) => value,
607
+ output: (datetime, length) => {
608
+ const offset = datetime.getTimeZoneOffset();
609
+
610
+ if (!offset) {
611
+ return 'Z';
612
+ }
613
+
614
+ let useColon;
615
+ switch (length) {
616
+ case 5:
617
+ case 3:
618
+ useColon = true;
619
+ break;
620
+ default:
621
+ useColon = false;
622
+ break;
623
+ }
624
+
625
+ return formatOffset(offset, useColon, length === 1);
626
+ },
627
+ },
628
+
629
+ x: {
630
+ key: 'timeZone',
631
+ regex: (_, length) => {
632
+ switch (length) {
633
+ case 5:
634
+ case 3:
635
+ return `[\\+\\-]\\d{2}\\:\\d{2}`;
636
+ case 4:
637
+ case 2:
638
+ return `[\\+\\-]\\d{4}`;
639
+ default:
640
+ return `[\\+\\-]\\d{2}(?:\\d{2})?`;
641
+ }
642
+ },
643
+ input: (_, value) => value,
644
+ output: (datetime, length) => {
645
+ let useColon;
646
+ switch (length) {
647
+ case 5:
648
+ case 3:
649
+ useColon = true;
650
+ break;
651
+ default:
652
+ useColon = false;
653
+ break;
654
+ }
655
+
656
+ return formatOffset(datetime.getTimeZoneOffset(), useColon, length === 1);
657
+ },
658
+ },
659
+
660
+ };