@@ -315,9 +315,9 @@ function FormatCalendarAnnotation(id: string, showCalendar: Temporal.ShowCalenda
315
315
return `[u-ca=${ id } ]` ;
316
316
}
317
317
318
- function ParseISODateTime ( isoString : string , { zoneRequired } : { zoneRequired : boolean } ) {
319
- const regex = zoneRequired ? PARSE . instant : PARSE . datetime ;
320
- const match = regex . exec ( isoString ) ;
318
+ function ParseISODateTime ( isoString : string ) {
319
+ // ZDT is the superset of fields for every other Temporal type
320
+ const match = PARSE . zoneddatetime . exec ( isoString ) ;
321
321
if ( ! match ) throw new RangeError ( `invalid ISO 8601 string: ${ isoString } ` ) ;
322
322
let yearString = match [ 1 ] ;
323
323
if ( yearString [ 0 ] === '\u2212' ) yearString = `-${ yearString . slice ( 1 ) } ` ;
@@ -380,19 +380,23 @@ function ParseISODateTime(isoString: string, { zoneRequired }: { zoneRequired: b
380
380
}
381
381
382
382
function ParseTemporalInstantString ( isoString : string ) {
383
- return ParseISODateTime ( isoString , { zoneRequired : true } ) ;
383
+ const result = ParseISODateTime ( isoString ) ;
384
+ if ( ! result . z && ! result . offset ) throw new RangeError ( 'Temporal.Instant requires a time zone offset' ) ;
385
+ return result ;
384
386
}
385
387
386
388
function ParseTemporalZonedDateTimeString ( isoString : string ) {
387
- return ParseISODateTime ( isoString , { zoneRequired : true } ) ;
389
+ const result = ParseISODateTime ( isoString ) ;
390
+ if ( ! result . ianaName ) throw new RangeError ( 'Temporal.ZonedDateTime requires a time zone ID in brackets' ) ;
391
+ return result ;
388
392
}
389
393
390
394
function ParseTemporalDateTimeString ( isoString : string ) {
391
- return ParseISODateTime ( isoString , { zoneRequired : false } ) ;
395
+ return ParseISODateTime ( isoString ) ;
392
396
}
393
397
394
398
function ParseTemporalDateString ( isoString : string ) {
395
- return ParseISODateTime ( isoString , { zoneRequired : false } ) ;
399
+ return ParseISODateTime ( isoString ) ;
396
400
}
397
401
398
402
function ParseTemporalTimeString ( isoString : string ) {
@@ -410,9 +414,7 @@ function ParseTemporalTimeString(isoString: string) {
410
414
calendar = match [ 15 ] ;
411
415
} else {
412
416
let z ;
413
- ( { hour, minute, second, millisecond, microsecond, nanosecond, calendar, z } = ParseISODateTime ( isoString , {
414
- zoneRequired : false
415
- } ) ) ;
417
+ ( { hour, minute, second, millisecond, microsecond, nanosecond, calendar, z } = ParseISODateTime ( isoString ) ) ;
416
418
if ( z ) throw new RangeError ( 'Z designator not supported for PlainTime' ) ;
417
419
}
418
420
return { hour, minute, second, millisecond, microsecond, nanosecond, calendar } ;
@@ -429,7 +431,7 @@ function ParseTemporalYearMonthString(isoString: string) {
429
431
calendar = match [ 3 ] ;
430
432
} else {
431
433
let z ;
432
- ( { year, month, calendar, day : referenceISODay , z } = ParseISODateTime ( isoString , { zoneRequired : false } ) ) ;
434
+ ( { year, month, calendar, day : referenceISODay , z } = ParseISODateTime ( isoString ) ) ;
433
435
if ( z ) throw new RangeError ( 'Z designator not supported for PlainYearMonth' ) ;
434
436
}
435
437
return { year, month, calendar, referenceISODay } ;
@@ -443,7 +445,7 @@ function ParseTemporalMonthDayString(isoString: string) {
443
445
day = ToInteger ( match [ 2 ] ) ;
444
446
} else {
445
447
let z ;
446
- ( { month, day, calendar, year : referenceISOYear , z } = ParseISODateTime ( isoString , { zoneRequired : false } ) ) ;
448
+ ( { month, day, calendar, year : referenceISOYear , z } = ParseISODateTime ( isoString ) ) ;
447
449
if ( z ) throw new RangeError ( 'Z designator not supported for PlainMonthDay' ) ;
448
450
}
449
451
return { month, day, calendar, referenceISOYear } ;
@@ -466,10 +468,14 @@ function ParseTemporalTimeZoneString(stringIdent: string): Partial<{
466
468
}
467
469
try {
468
470
// Try parsing ISO string instead
469
- return ParseISODateTime ( stringIdent , { zoneRequired : true } ) ;
471
+ const result = ParseISODateTime ( stringIdent ) ;
472
+ if ( result . z || result . offset || result . ianaName ) {
473
+ return result ;
474
+ }
470
475
} catch {
471
- throw new RangeError ( `Invalid time zone: ${ stringIdent } ` ) ;
476
+ // fall through
472
477
}
478
+ throw new RangeError ( `Invalid time zone: ${ stringIdent } ` ) ;
473
479
}
474
480
475
481
function ParseTemporalDurationString ( isoString : string ) {
@@ -514,7 +520,6 @@ function ParseTemporalInstant(isoString: string) {
514
520
515
521
const epochNs = GetEpochFromISOParts ( year , month , day , hour , minute , second , millisecond , microsecond , nanosecond ) ;
516
522
if ( epochNs === null ) throw new RangeError ( 'DateTime outside of supported range' ) ;
517
- if ( ! z && ! offset ) throw new RangeError ( 'Temporal.Instant requires a time zone offset' ) ;
518
523
const offsetNs = z ? 0 : ParseTimeZoneOffsetString ( offset ) ;
519
524
return JSBI . subtract ( epochNs , JSBI . BigInt ( offsetNs ) ) ;
520
525
}
@@ -982,7 +987,7 @@ export function ToRelativeTemporalObject(options: {
982
987
} else {
983
988
let ianaName , z ;
984
989
( { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, ianaName, offset, z } =
985
- ParseISODateTime ( ToString ( relativeTo ) , { zoneRequired : false } ) ) ;
990
+ ParseISODateTime ( ToString ( relativeTo ) ) ) ;
986
991
if ( ianaName ) timeZone = ianaName ;
987
992
if ( z ) {
988
993
offsetBehaviour = 'exact' ;
@@ -2083,7 +2088,7 @@ export function ToTemporalCalendar(calendarLikeParam: CalendarParams['from'][0])
2083
2088
if ( IsBuiltinCalendar ( identifier ) ) return new TemporalCalendar ( identifier ) ;
2084
2089
let calendar ;
2085
2090
try {
2086
- ( { calendar } = ParseISODateTime ( identifier , { zoneRequired : false } ) ) ;
2091
+ ( { calendar } = ParseISODateTime ( identifier ) ) ;
2087
2092
} catch {
2088
2093
throw new RangeError ( `Invalid calendar: ${ identifier } ` ) ;
2089
2094
}
0 commit comments