@superdispatch/dates 0.21.8 → 0.21.13

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.
Files changed (62) hide show
  1. package/.babelrc.js +5 -0
  2. package/.turbo/turbo-version.log +26 -0
  3. package/package.json +58 -32
  4. package/pkg/README.md +10 -0
  5. package/{dist-types → pkg/dist-types}/index.d.ts +237 -237
  6. package/pkg/package.json +32 -0
  7. package/playroom.ts +10 -0
  8. package/src/__tests__/index.spec.ts +48 -0
  9. package/src/base-date-picker/BaseDatePicker.tsx +145 -0
  10. package/src/calendar/Calendar.playroom.tsx +28 -0
  11. package/src/calendar/Calendar.spec.tsx +531 -0
  12. package/src/calendar/Calendar.stories.tsx +50 -0
  13. package/src/calendar/Calendar.tsx +534 -0
  14. package/src/calendar/CalendarQuickSelection.tsx +34 -0
  15. package/src/calendar/InternalCalendarComponents.tsx +79 -0
  16. package/src/date-config/DateConfig.spec.tsx +23 -0
  17. package/src/date-config/DateConfig.tsx +60 -0
  18. package/src/date-field/DateField.playroom.tsx +21 -0
  19. package/src/date-field/DateField.spec.tsx +350 -0
  20. package/src/date-field/DateField.stories.tsx +47 -0
  21. package/src/date-field/DateField.tsx +155 -0
  22. package/src/date-range-field/DateRangeField.playroom.tsx +24 -0
  23. package/src/date-range-field/DateRangeField.spec.tsx +318 -0
  24. package/src/date-range-field/DateRangeField.stories.tsx +51 -0
  25. package/src/date-range-field/DateRangeField.tsx +277 -0
  26. package/src/date-time-utils/DateTimeUtils.spec.ts +652 -0
  27. package/src/date-time-utils/DateTimeUtils.ts +339 -0
  28. package/src/date-utils/DateUtils.spec.ts +234 -0
  29. package/src/date-utils/DateUtils.ts +333 -0
  30. package/src/formatted-date/FormattedDate.spec.tsx +103 -0
  31. package/src/formatted-date/FormattedDate.ts +42 -0
  32. package/src/formatted-relative-time/FormattedRelativeTime.spec.tsx +93 -0
  33. package/src/formatted-relative-time/FormattedRelativeTime.ts +60 -0
  34. package/src/index.ts +12 -0
  35. package/src/time-field/TimeField.playroom.tsx +21 -0
  36. package/src/time-field/TimeField.stories.tsx +35 -0
  37. package/src/time-field/TimeField.tsx +221 -0
  38. package/src/use-date-time/useDateTime.spec.ts +45 -0
  39. package/src/use-date-time/useDateTime.ts +31 -0
  40. package/src/use-date-time-range/useDateTimeRange.spec.ts +53 -0
  41. package/src/use-date-time-range/useDateTimeRange.ts +24 -0
  42. package/tsconfig.json +19 -0
  43. package/LICENSE +0 -21
  44. /package/{dist-node → pkg/dist-node}/index.js +0 -0
  45. /package/{dist-node → pkg/dist-node}/index.js.map +0 -0
  46. /package/{dist-src → pkg/dist-src}/base-date-picker/BaseDatePicker.js +0 -0
  47. /package/{dist-src → pkg/dist-src}/calendar/Calendar.js +0 -0
  48. /package/{dist-src → pkg/dist-src}/calendar/CalendarQuickSelection.js +0 -0
  49. /package/{dist-src → pkg/dist-src}/calendar/InternalCalendarComponents.js +0 -0
  50. /package/{dist-src → pkg/dist-src}/date-config/DateConfig.js +0 -0
  51. /package/{dist-src → pkg/dist-src}/date-field/DateField.js +0 -0
  52. /package/{dist-src → pkg/dist-src}/date-range-field/DateRangeField.js +0 -0
  53. /package/{dist-src → pkg/dist-src}/date-time-utils/DateTimeUtils.js +0 -0
  54. /package/{dist-src → pkg/dist-src}/date-utils/DateUtils.js +0 -0
  55. /package/{dist-src → pkg/dist-src}/formatted-date/FormattedDate.js +0 -0
  56. /package/{dist-src → pkg/dist-src}/formatted-relative-time/FormattedRelativeTime.js +0 -0
  57. /package/{dist-src → pkg/dist-src}/index.js +0 -0
  58. /package/{dist-src → pkg/dist-src}/time-field/TimeField.js +0 -0
  59. /package/{dist-src → pkg/dist-src}/use-date-time/useDateTime.js +0 -0
  60. /package/{dist-src → pkg/dist-src}/use-date-time-range/useDateTimeRange.js +0 -0
  61. /package/{dist-web → pkg/dist-web}/index.js +0 -0
  62. /package/{dist-web → pkg/dist-web}/index.js.map +0 -0
@@ -0,0 +1,652 @@
1
+ import { mockDate } from '@superdispatch/ui-testutils';
2
+ import { DateTime, FixedOffsetZone } from 'luxon';
3
+ import { DateFormat, setDefaultTimeZone } from '../date-config/DateConfig';
4
+ import {
5
+ DateDisplayVariant,
6
+ DateString,
7
+ DateStringRange,
8
+ DateTimeRange,
9
+ formatDate,
10
+ formatDateRange,
11
+ formatRelativeTime,
12
+ NullableDateInput,
13
+ NullableDateRangeInput,
14
+ NullableDateString,
15
+ parseDate,
16
+ parseDateRange,
17
+ PrimitiveDateInput,
18
+ stringifyDate,
19
+ stringifyDateRange,
20
+ toPrimitiveDateInput,
21
+ } from './DateTimeUtils';
22
+
23
+ const STUB_UTC = Date.UTC(2019, 4, 24, 1, 2, 3, 4);
24
+
25
+ beforeEach(() => {
26
+ mockDate();
27
+ setDefaultTimeZone('local');
28
+ });
29
+
30
+ test.each<[NullableDateInput, PrimitiveDateInput]>([
31
+ [NaN, NaN],
32
+ [null, NaN],
33
+ [undefined, NaN],
34
+ ['', ''],
35
+ ['invalid', 'invalid'],
36
+ ['2019-05-24T05:06:07.008Z', '2019-05-24T05:06:07.008Z'],
37
+ [STUB_UTC, STUB_UTC],
38
+ [new Date(STUB_UTC), STUB_UTC],
39
+ [DateTime.fromMillis(STUB_UTC), STUB_UTC],
40
+ ])('toPrimitiveDateInput', (input, expected) => {
41
+ expect(toPrimitiveDateInput(input)).toBe(expected);
42
+ });
43
+
44
+ test.each<[input: NullableDateInput, result: null | string]>([
45
+ [null, null],
46
+ [undefined, null],
47
+ [STUB_UTC, '2019-05-23T20:02:03.004-05:00'],
48
+ [new Date(STUB_UTC), '2019-05-23T20:02:03.004-05:00'],
49
+ [DateTime.fromMillis(STUB_UTC), '2019-05-23T20:02:03.004-05:00'],
50
+ [
51
+ DateTime.fromMillis(STUB_UTC).setZone(FixedOffsetZone.instance(0)),
52
+ '2019-05-23T20:02:03.004-05:00',
53
+ ],
54
+ ])('parseDate(%p): %p', (input, result) => {
55
+ expect(parseDate(input).toISO()).toBe(result);
56
+ });
57
+
58
+ test.each<[NullableDateInput, Record<DateFormat, null | string>]>([
59
+ [null, { JodaISO: null, DateISO: null, DateTimeISO: null }],
60
+ [undefined, { JodaISO: null, DateISO: null, DateTimeISO: null }],
61
+ ['0000-00-00', { JodaISO: null, DateISO: null, DateTimeISO: null }],
62
+
63
+ [
64
+ '2019-05-24',
65
+ {
66
+ JodaISO: null,
67
+ DateISO: '2019-05-24T00:00:00.000+02:00',
68
+ DateTimeISO: '2019-05-24T00:00:00.000+02:00',
69
+ },
70
+ ],
71
+
72
+ [
73
+ '2019-05-24T01:02:03.045Z',
74
+ {
75
+ JodaISO: null,
76
+ DateISO: '2019-05-24T03:02:03.045+02:00',
77
+ DateTimeISO: '2019-05-24T03:02:03.045+02:00',
78
+ },
79
+ ],
80
+
81
+ [
82
+ '2019-05-24T01:02:03.045+0000',
83
+ {
84
+ JodaISO: '2019-05-24T03:02:03.045+02:00',
85
+ DateISO: '2019-05-24T03:02:03.045+02:00',
86
+ DateTimeISO: '2019-05-24T03:02:03.045+02:00',
87
+ },
88
+ ],
89
+
90
+ [
91
+ '2019-05-24T01:02:03.045+0500',
92
+ {
93
+ JodaISO: '2019-05-23T22:02:03.045+02:00',
94
+ DateISO: '2019-05-23T22:02:03.045+02:00',
95
+ DateTimeISO: '2019-05-23T22:02:03.045+02:00',
96
+ },
97
+ ],
98
+
99
+ [
100
+ '2019-05-24T01:02:03.045-0500',
101
+ {
102
+ JodaISO: '2019-05-24T08:02:03.045+02:00',
103
+ DateISO: '2019-05-24T08:02:03.045+02:00',
104
+ DateTimeISO: '2019-05-24T08:02:03.045+02:00',
105
+ },
106
+ ],
107
+
108
+ [
109
+ '2019-05-24T01:02:03.045678+0000',
110
+ {
111
+ JodaISO: null,
112
+ DateISO: '2019-05-24T03:02:03.045+02:00',
113
+ DateTimeISO: '2019-05-24T03:02:03.045+02:00',
114
+ },
115
+ ],
116
+
117
+ [
118
+ '2019-05-24T01:02:03.045678+0500',
119
+ {
120
+ JodaISO: null,
121
+ DateISO: '2019-05-23T22:02:03.045+02:00',
122
+ DateTimeISO: '2019-05-23T22:02:03.045+02:00',
123
+ },
124
+ ],
125
+
126
+ [
127
+ '2019-05-24T01:02:03.045678-0500',
128
+ {
129
+ JodaISO: null,
130
+ DateISO: '2019-05-24T08:02:03.045+02:00',
131
+ DateTimeISO: '2019-05-24T08:02:03.045+02:00',
132
+ },
133
+ ],
134
+ ])('parseDate(%p)', (input, expectations) => {
135
+ const results: Record<string, any> = {};
136
+
137
+ setDefaultTimeZone(120);
138
+
139
+ for (const format of Object.keys(expectations) as DateFormat[]) {
140
+ results[format] = parseDate(input, { format }).toJSON();
141
+ }
142
+
143
+ expect(results).toEqual(expectations);
144
+ });
145
+
146
+ test.each<
147
+ [
148
+ input: null | undefined | string,
149
+ ...cases: Array<
150
+ [offset: number, results: Record<DateFormat, null | string>]
151
+ >
152
+ ]
153
+ >([
154
+ [null, [0, { JodaISO: null, DateISO: null, DateTimeISO: null }]],
155
+ [null, [0, { JodaISO: null, DateISO: null, DateTimeISO: null }]],
156
+ ['0000-00-00', [0, { JodaISO: null, DateISO: null, DateTimeISO: null }]],
157
+
158
+ [
159
+ '2019-05-24T00:00:00.000Z',
160
+ [
161
+ 0,
162
+ {
163
+ JodaISO: '2019-05-24T00:00:00.000+0000',
164
+ DateISO: '2019-05-24',
165
+ DateTimeISO: '2019-05-24T00:00:00.000Z',
166
+ },
167
+ ],
168
+
169
+ [
170
+ 3,
171
+ {
172
+ JodaISO: '2019-05-24T03:00:00.000+0300',
173
+ DateISO: '2019-05-24',
174
+ DateTimeISO: '2019-05-24T03:00:00.000+03:00',
175
+ },
176
+ ],
177
+
178
+ [
179
+ -3,
180
+ {
181
+ JodaISO: '2019-05-23T21:00:00.000-0300',
182
+ DateISO: '2019-05-23',
183
+ DateTimeISO: '2019-05-23T21:00:00.000-03:00',
184
+ },
185
+ ],
186
+ ],
187
+
188
+ [
189
+ '2019-05-24T12:13:14.156Z',
190
+ [
191
+ 0,
192
+ {
193
+ JodaISO: '2019-05-24T12:13:14.156+0000',
194
+ DateISO: '2019-05-24',
195
+ DateTimeISO: '2019-05-24T12:13:14.156Z',
196
+ },
197
+ ],
198
+
199
+ [
200
+ 3,
201
+ {
202
+ JodaISO: '2019-05-24T15:13:14.156+0300',
203
+ DateISO: '2019-05-24',
204
+ DateTimeISO: '2019-05-24T15:13:14.156+03:00',
205
+ },
206
+ ],
207
+
208
+ [
209
+ -3,
210
+ {
211
+ JodaISO: '2019-05-24T09:13:14.156-0300',
212
+ DateISO: '2019-05-24',
213
+ DateTimeISO: '2019-05-24T09:13:14.156-03:00',
214
+ },
215
+ ],
216
+ ],
217
+
218
+ [
219
+ '2019-05-24T12:13:14.156+0500',
220
+ [
221
+ 0,
222
+ {
223
+ JodaISO: '2019-05-24T07:13:14.156+0000',
224
+ DateISO: '2019-05-24',
225
+ DateTimeISO: '2019-05-24T07:13:14.156Z',
226
+ },
227
+ ],
228
+
229
+ [
230
+ 3,
231
+ {
232
+ JodaISO: '2019-05-24T10:13:14.156+0300',
233
+ DateISO: '2019-05-24',
234
+ DateTimeISO: '2019-05-24T10:13:14.156+03:00',
235
+ },
236
+ ],
237
+
238
+ [
239
+ -3,
240
+ {
241
+ JodaISO: '2019-05-24T04:13:14.156-0300',
242
+ DateISO: '2019-05-24',
243
+ DateTimeISO: '2019-05-24T04:13:14.156-03:00',
244
+ },
245
+ ],
246
+ ],
247
+
248
+ [
249
+ '2019-05-24T12:13:14.156-0500',
250
+ [
251
+ 0,
252
+ {
253
+ JodaISO: '2019-05-24T17:13:14.156+0000',
254
+ DateISO: '2019-05-24',
255
+ DateTimeISO: '2019-05-24T17:13:14.156Z',
256
+ },
257
+ ],
258
+
259
+ [
260
+ 3,
261
+ {
262
+ JodaISO: '2019-05-24T20:13:14.156+0300',
263
+ DateISO: '2019-05-24',
264
+ DateTimeISO: '2019-05-24T20:13:14.156+03:00',
265
+ },
266
+ ],
267
+
268
+ [
269
+ -3,
270
+ {
271
+ JodaISO: '2019-05-24T14:13:14.156-0300',
272
+ DateISO: '2019-05-24',
273
+ DateTimeISO: '2019-05-24T14:13:14.156-03:00',
274
+ },
275
+ ],
276
+ ],
277
+ ])('stringifyDate(%p)', (input, ...cases) => {
278
+ for (const [offset, expectations] of cases) {
279
+ const results: Record<string, any> = {};
280
+
281
+ for (const format of Object.keys(expectations) as DateFormat[]) {
282
+ setDefaultTimeZone(offset * 60);
283
+
284
+ if (input == null) {
285
+ results[format] = stringifyDate(input, { format });
286
+ } else {
287
+ results[format] = stringifyDate(DateTime.fromISO(input), { format });
288
+ }
289
+ }
290
+
291
+ expect(results).toEqual(expectations);
292
+ }
293
+ });
294
+
295
+ test('stringifyDate(…)', () => {
296
+ expect(stringifyDate(DateTime.local())).toBe('2019-05-24T07:13:14.015-05:00');
297
+ });
298
+
299
+ test.each<
300
+ [
301
+ offset: number,
302
+ input: DateString,
303
+ fallback: string | undefined,
304
+ results: Record<DateDisplayVariant, string>,
305
+ ]
306
+ >([
307
+ [
308
+ 0,
309
+ '0000-00-00',
310
+ undefined,
311
+ {
312
+ ShortDate: 'Invalid Date',
313
+ Date: 'Invalid Date',
314
+ Time: 'Invalid Date',
315
+ DateTime: 'Invalid Date',
316
+ },
317
+ ],
318
+
319
+ [
320
+ 0,
321
+ '0000-00-00',
322
+ 'Custom Empty Text',
323
+ {
324
+ ShortDate: 'Custom Empty Text',
325
+ Date: 'Custom Empty Text',
326
+ Time: 'Custom Empty Text',
327
+ DateTime: 'Custom Empty Text',
328
+ },
329
+ ],
330
+
331
+ [
332
+ 0,
333
+ '2019-05-24T12:13:14.156Z',
334
+ undefined,
335
+ {
336
+ ShortDate: 'May 24',
337
+ Date: 'May 24, 2019',
338
+ Time: '12:13 PM',
339
+ DateTime: 'May 24, 2019, 12:13 PM',
340
+ },
341
+ ],
342
+
343
+ [
344
+ 3,
345
+ '2019-05-24T05:06:07.008Z',
346
+ undefined,
347
+ {
348
+ ShortDate: 'May 24',
349
+ Date: 'May 24, 2019',
350
+ Time: '8:06 AM',
351
+ DateTime: 'May 24, 2019, 8:06 AM',
352
+ },
353
+ ],
354
+
355
+ [
356
+ -3,
357
+ '2019-05-24T05:06:07.008Z',
358
+ undefined,
359
+ {
360
+ ShortDate: 'May 24',
361
+ Date: 'May 24, 2019',
362
+ Time: '2:06 AM',
363
+ DateTime: 'May 24, 2019, 2:06 AM',
364
+ },
365
+ ],
366
+
367
+ [
368
+ 7,
369
+ '2019-05-24T05:06:07.008Z',
370
+ undefined,
371
+ {
372
+ ShortDate: 'May 24',
373
+ Date: 'May 24, 2019',
374
+ Time: '12:06 PM',
375
+ DateTime: 'May 24, 2019, 12:06 PM',
376
+ },
377
+ ],
378
+
379
+ [
380
+ -7,
381
+ '2019-05-24T05:06:07.008Z',
382
+ undefined,
383
+ {
384
+ ShortDate: 'May 23',
385
+ Date: 'May 23, 2019',
386
+ Time: '10:06 PM',
387
+ DateTime: 'May 23, 2019, 10:06 PM',
388
+ },
389
+ ],
390
+ ])(
391
+ '(tz: %p) formatDate(%p, { fallback: %p })',
392
+ (offset, input, fallback, expectations) => {
393
+ const dateResults: Record<string, any> = {};
394
+ const stringResults: Record<string, any> = {};
395
+
396
+ for (const variant of Object.keys(expectations) as DateDisplayVariant[]) {
397
+ setDefaultTimeZone(offset * 60);
398
+
399
+ dateResults[variant] = formatDate(DateTime.fromISO(input), {
400
+ variant,
401
+ fallback,
402
+ });
403
+
404
+ stringResults[variant] = formatDate(input, {
405
+ variant,
406
+ fallback,
407
+ });
408
+ }
409
+
410
+ expect(dateResults).toEqual(expectations);
411
+ expect(stringResults).toEqual(expectations);
412
+ },
413
+ );
414
+
415
+ test('formatRelative(…)', () => {
416
+ expect(formatRelativeTime('2019-05-24')).toBe('7h ago');
417
+ expect(formatRelativeTime('2019-05-24T05:00:00Z')).toBe('7h ago');
418
+ expect(formatRelativeTime('2019-05-24T05:00:00-0000')).toBe('7h ago');
419
+ expect(formatRelativeTime('2019-05-24T00:00:00-0500')).toBe('7h ago');
420
+ expect(formatRelativeTime('2019-05-24T10:00:00+0500')).toBe('7h ago');
421
+ });
422
+
423
+ test.each<[NullableDateRangeInput, Record<DateFormat, DateTimeRange>]>([
424
+ [
425
+ null,
426
+ {
427
+ JodaISO: [null, null],
428
+ DateISO: [null, null],
429
+ DateTimeISO: [null, null],
430
+ },
431
+ ],
432
+ [
433
+ undefined,
434
+ {
435
+ JodaISO: [null, null],
436
+ DateISO: [null, null],
437
+ DateTimeISO: [null, null],
438
+ },
439
+ ],
440
+ [
441
+ [null, undefined],
442
+ {
443
+ JodaISO: [null, null],
444
+ DateISO: [null, null],
445
+ DateTimeISO: [null, null],
446
+ },
447
+ ],
448
+
449
+ [
450
+ [NaN, '0000-00-00'],
451
+ {
452
+ JodaISO: [null, null],
453
+ DateISO: [null, null],
454
+ DateTimeISO: [null, null],
455
+ },
456
+ ],
457
+
458
+ [
459
+ [null, STUB_UTC],
460
+
461
+ {
462
+ JodaISO: [DateTime.fromMillis(STUB_UTC), null],
463
+ DateISO: [DateTime.fromMillis(STUB_UTC), null],
464
+ DateTimeISO: [DateTime.fromMillis(STUB_UTC), null],
465
+ },
466
+ ],
467
+
468
+ [
469
+ [null, new Date(STUB_UTC)],
470
+
471
+ {
472
+ JodaISO: [DateTime.fromMillis(STUB_UTC), null],
473
+ DateISO: [DateTime.fromMillis(STUB_UTC), null],
474
+ DateTimeISO: [DateTime.fromMillis(STUB_UTC), null],
475
+ },
476
+ ],
477
+
478
+ [
479
+ [null, DateTime.fromMillis(STUB_UTC)],
480
+
481
+ {
482
+ JodaISO: [DateTime.fromMillis(STUB_UTC), null],
483
+ DateISO: [DateTime.fromMillis(STUB_UTC), null],
484
+ DateTimeISO: [DateTime.fromMillis(STUB_UTC), null],
485
+ },
486
+ ],
487
+
488
+ [
489
+ [null, '2019-05-24'],
490
+ {
491
+ JodaISO: [null, null],
492
+ DateISO: [DateTime.fromISO('2019-05-24'), null],
493
+ DateTimeISO: [DateTime.fromISO('2019-05-24'), null],
494
+ },
495
+ ],
496
+
497
+ [
498
+ [null, '2019-05-24T01:02:03.004Z'],
499
+
500
+ {
501
+ JodaISO: [null, null],
502
+ DateISO: [DateTime.fromMillis(STUB_UTC), null],
503
+ DateTimeISO: [DateTime.fromMillis(STUB_UTC), null],
504
+ },
505
+ ],
506
+
507
+ [
508
+ ['2019-05-24T03:02:03.004-02:00', '2000-01-02T03:04:05.678+02:00'],
509
+ {
510
+ JodaISO: [null, null],
511
+ DateISO: [
512
+ DateTime.fromISO('2000-01-02T03:04:05.678+02:00'),
513
+ DateTime.fromISO('2019-05-24T03:02:03.004-02:00'),
514
+ ],
515
+ DateTimeISO: [
516
+ DateTime.fromISO('2000-01-02T03:04:05.678+02:00'),
517
+ DateTime.fromISO('2019-05-24T03:02:03.004-02:00'),
518
+ ],
519
+ },
520
+ ],
521
+
522
+ [
523
+ ['2019-05-24T03:02:03.004-0200', '2000-01-02T03:04:05.678+0200'],
524
+ {
525
+ JodaISO: [
526
+ DateTime.fromISO('2000-01-02T03:04:05.678+02:00'),
527
+ DateTime.fromISO('2019-05-24T03:02:03.004-02:00'),
528
+ ],
529
+ DateISO: [
530
+ DateTime.fromISO('2000-01-02T03:04:05.678+02:00'),
531
+ DateTime.fromISO('2019-05-24T03:02:03.004-02:00'),
532
+ ],
533
+ DateTimeISO: [
534
+ DateTime.fromISO('2000-01-02T03:04:05.678+02:00'),
535
+ DateTime.fromISO('2019-05-24T03:02:03.004-02:00'),
536
+ ],
537
+ },
538
+ ],
539
+ ])('parseDateRange(%p)', (input, expectations) => {
540
+ const results: Record<string, any> = {};
541
+
542
+ for (const format of Object.keys(expectations)) {
543
+ results[format] = parseDateRange(input, { format: format as DateFormat });
544
+ }
545
+
546
+ expect(results).toEqual(expectations);
547
+ });
548
+
549
+ test.each<
550
+ [
551
+ [NullableDateString, NullableDateString],
552
+ Record<DateFormat, DateStringRange>,
553
+ ]
554
+ >([
555
+ [
556
+ [undefined, undefined],
557
+ {
558
+ JodaISO: [null, null],
559
+ DateISO: [null, null],
560
+ DateTimeISO: [null, null],
561
+ },
562
+ ],
563
+
564
+ [
565
+ [undefined, '0000-00-00'],
566
+ {
567
+ JodaISO: [null, null],
568
+ DateISO: [null, null],
569
+ DateTimeISO: [null, null],
570
+ },
571
+ ],
572
+
573
+ [
574
+ [undefined, '2019-05-24T00:00:00.000Z'],
575
+ {
576
+ JodaISO: ['2019-05-23T19:00:00.000-0500', null],
577
+ DateISO: ['2019-05-23', null],
578
+ DateTimeISO: ['2019-05-23T19:00:00.000-05:00', null],
579
+ },
580
+ ],
581
+
582
+ [
583
+ ['2019-05-24T12:13:14.156Z', '2019-05-24T00:00:00.000Z'],
584
+ {
585
+ DateISO: ['2019-05-23', '2019-05-24'],
586
+ DateTimeISO: [
587
+ '2019-05-23T19:00:00.000-05:00',
588
+ '2019-05-24T07:13:14.156-05:00',
589
+ ],
590
+ JodaISO: ['2019-05-23T19:00:00.000-0500', '2019-05-24T07:13:14.156-0500'],
591
+ },
592
+ ],
593
+
594
+ [
595
+ ['2019-05-24T01:11:11.111-0500', '2019-05-24T01:22:22.222+0500'],
596
+ {
597
+ DateISO: ['2019-05-23', '2019-05-24'],
598
+ DateTimeISO: [
599
+ '2019-05-23T15:22:22.222-05:00',
600
+ '2019-05-24T01:11:11.111-05:00',
601
+ ],
602
+ JodaISO: ['2019-05-23T15:22:22.222-0500', '2019-05-24T01:11:11.111-0500'],
603
+ },
604
+ ],
605
+ ])('stringifyDateRange(%p)', ([start, finish], expectations) => {
606
+ const results: Record<string, any> = {};
607
+
608
+ for (const format of Object.keys(expectations)) {
609
+ results[format] = stringifyDateRange(
610
+ [
611
+ !start ? undefined : DateTime.fromISO(start),
612
+ !finish ? undefined : DateTime.fromISO(finish),
613
+ ],
614
+ { format: format as DateFormat },
615
+ );
616
+ }
617
+
618
+ expect(results).toEqual(expectations);
619
+ });
620
+
621
+ test.each<
622
+ [[NullableDateString, NullableDateString], string | undefined, string]
623
+ >([
624
+ [[undefined, undefined], '', ''],
625
+ [[undefined, undefined], undefined, 'Invalid Date Range'],
626
+ [[undefined, '0000-00-00'], 'Custom Empty Text', 'Custom Empty Text'],
627
+
628
+ [[undefined, '2019-05-24T00:00:00.000Z'], undefined, 'May 23, 2019 - …'],
629
+
630
+ [
631
+ ['2019-05-24T12:13:14.156Z', '2019-05-24T00:00:00.000Z'],
632
+ undefined,
633
+ 'May 23 - May 24, 2019',
634
+ ],
635
+
636
+ [
637
+ ['2019-05-24T12:13:14.156Z', '2020-05-24T00:00:00.000Z'],
638
+ undefined,
639
+ 'May 24, 2019 - May 23, 2020',
640
+ ],
641
+ ])('formatDateRange(%p, %p): %p', ([start, finish], fallback, expected) => {
642
+ expect(formatDateRange([start, finish], { fallback })).toEqual(expected);
643
+ expect(
644
+ formatDateRange(
645
+ [
646
+ !start ? undefined : DateTime.fromISO(start),
647
+ !finish ? undefined : DateTime.fromISO(finish),
648
+ ],
649
+ { fallback },
650
+ ),
651
+ ).toEqual(expected);
652
+ });