Skip to content

Commit d2c09f1

Browse files
authored
ASSETS-25282: Fix UTC offset format acceptance in date parsers (#4660)
1 parent e50dc58 commit d2c09f1

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

packages/@internationalized/date/src/string.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import {Mutable} from './utils';
2020
const TIME_RE = /^(\d{2})(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?$/;
2121
const DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
2222
const DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?$/;
23-
const ZONED_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:([+-]\d{2})(?::(\d{2}))?)?\[(.*?)\]$/;
24-
const ABSOLUTE_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:(?:([+-]\d{2})(?::(\d{2}))?)|Z)$/;
23+
const ZONED_DATE_TIME_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:([+-]\d{2})(?::?(\d{2}))?)?\[(.*?)\]$/;
24+
const ABSOLUTE_RE = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}))?(?::(\d{2}))?(?::(\d{2}))?(\.\d+)?(?:(?:([+-]\d{2})(?::?(\d{2}))?)|Z)$/;
2525
const DATE_TIME_DURATION_RE =
2626
/^((?<negative>-)|\+)?P((?<years>\d*)Y)?((?<months>\d*)M)?((?<weeks>\d*)W)?((?<days>\d*)D)?((?<time>T)((?<hours>\d*[.,]?\d{1,9})H)?((?<minutes>\d*[.,]?\d{1,9})M)?((?<seconds>\d*[.,]?\d{1,9})S)?)?$/;
2727
const requiredDurationTimeGroups = ['hours', 'minutes', 'seconds'];
@@ -238,7 +238,7 @@ export function parseDuration(value: string): Required<DateTimeDuration> {
238238
}
239239

240240
const durationStringIncludesTime = match.groups?.time;
241-
241+
242242
if (durationStringIncludesTime) {
243243
const hasRequiredDurationTimeGroups = requiredDurationTimeGroups.some(group => match.groups?.[group]);
244244
if (!hasRequiredDurationTimeGroups) {

packages/@internationalized/date/tests/string.test.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,18 @@ describe('string conversion', function () {
224224
let date = parseZonedDateTime('2020-02-03T12:24:45-08:00[America/Los_Angeles]');
225225
let expected = new ZonedDateTime(2020, 2, 3, 'America/Los_Angeles', -28800000, 12, 24, 45);
226226
expect(date).toEqual(expected);
227+
228+
date = parseZonedDateTime('2020-02-03T12:24:45-0800[America/Los_Angeles]');
229+
expected = new ZonedDateTime(2020, 2, 3, 'America/Los_Angeles', -28800000, 12, 24, 45);
230+
expect(date).toEqual(expected);
231+
232+
date = parseZonedDateTime('2020-02-03T12:24:45-08[America/Los_Angeles]');
233+
expected = new ZonedDateTime(2020, 2, 3, 'America/Los_Angeles', -28800000, 12, 24, 45);
234+
expect(date).toEqual(expected);
235+
236+
date = parseZonedDateTime('2020-02-03T12:24:45+0000[UTC]');
237+
expected = new ZonedDateTime(2020, 2, 3, 'UTC', 0, 12, 24, 45);
238+
expect(date).toEqual(expected);
227239
});
228240

229241
it('should parse a date with a time with milliseconds and an offset', function () {
@@ -329,6 +341,18 @@ describe('string conversion', function () {
329341
date = parseAbsolute('2021-11-07T01:00-08:00', 'America/Los_Angeles');
330342
expected = new ZonedDateTime(2021, 11, 7, 'America/Los_Angeles', -28800000, 1, 0, 0);
331343
expect(date).toEqual(expected);
344+
345+
date = parseAbsolute('2021-11-07T01:00-0800', 'America/Los_Angeles');
346+
expected = new ZonedDateTime(2021, 11, 7, 'America/Los_Angeles', -28800000, 1, 0, 0);
347+
expect(date).toEqual(expected);
348+
349+
date = parseAbsolute('2021-11-07T01:00-08', 'America/Los_Angeles');
350+
expected = new ZonedDateTime(2021, 11, 7, 'America/Los_Angeles', -28800000, 1, 0, 0);
351+
expect(date).toEqual(expected);
352+
353+
date = parseAbsolute('2021-11-07T01:00+0000', 'America/Los_Angeles');
354+
expected = new ZonedDateTime(2021, 11, 6, 'America/Los_Angeles', -25200000, 18, 0, 0);
355+
expect(date).toEqual(expected);
332356
});
333357

334358
it('should error if missing offset or Z', function () {
@@ -366,7 +390,7 @@ describe('string conversion', function () {
366390
seconds: 5
367391
});
368392
});
369-
393+
370394
it('parses an ISO 8601 duration string that contains years, months, weeks, days, hours, minutes, and fractional values for seconds expressed with a period and returns a DateTimeDuration object', function () {
371395
const duration = parseDuration('P3Y6M6W4DT12H30M5.5S');
372396
expect(duration).toStrictEqual({
@@ -379,7 +403,7 @@ describe('string conversion', function () {
379403
seconds: 5.5
380404
});
381405
});
382-
406+
383407
it('parses an ISO 8601 duration string that contains years, months, weeks, days, hours, minutes, and fractional values for seconds expressed with a comma and returns a DateTimeDuration object', function () {
384408
const duration = parseDuration('P3Y6M6W4DT12H30M5,5S');
385409
expect(duration).toStrictEqual({
@@ -444,7 +468,7 @@ describe('string conversion', function () {
444468
seconds: 0
445469
});
446470
});
447-
471+
448472
it('parses a negative ISO 8601 duration string that contains years, months, weeks, days, hours, minutes, and seconds and returns a DateTimeDuration object', function () {
449473
const duration = parseDuration('-P3Y6M6W4DT12H30M5S');
450474
expect(duration).toStrictEqual({
@@ -457,7 +481,7 @@ describe('string conversion', function () {
457481
seconds: -5
458482
});
459483
});
460-
484+
461485
it('parses an ISO 8601 duration string that contains years, months, weeks, days, hours, minutes, and seconds with a preceding + sign and returns a DateTimeDuration object', function () {
462486
const duration = parseDuration('+P3Y6M6W4DT12H30M5S');
463487
expect(duration).toStrictEqual({
@@ -483,7 +507,7 @@ describe('string conversion', function () {
483507
seconds: 15
484508
});
485509
});
486-
510+
487511
it('parses an ISO 8601 duration string that contains years, months, weeks, and days and returns a DateTimeDuration object', function () {
488512
const duration = parseDuration('P7Y8M14W6D');
489513
expect(duration).toStrictEqual({
@@ -496,7 +520,7 @@ describe('string conversion', function () {
496520
seconds: 0
497521
});
498522
});
499-
523+
500524
it('parses an ISO 8601 duration string that contains years, months, hours, and seconds and returns a DateTimeDuration object', function () {
501525
const duration = parseDuration('P18Y7MT20H15S');
502526
expect(duration).toStrictEqual({
@@ -509,7 +533,7 @@ describe('string conversion', function () {
509533
seconds: 15
510534
});
511535
});
512-
536+
513537
it('throws an error when passed an improperly formatted ISO 8601 duration string', function () {
514538
expect(() => {
515539
parseDuration('+-P18Y7MT20H15S');

0 commit comments

Comments
 (0)