@@ -315,9 +315,9 @@ function FormatCalendarAnnotation(id: string, showCalendar: Temporal.ShowCalenda
315315 return `[u-ca=${ id } ]` ;
316316}
317317
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 ) ;
321321 if ( ! match ) throw new RangeError ( `invalid ISO 8601 string: ${ isoString } ` ) ;
322322 let yearString = match [ 1 ] ;
323323 if ( yearString [ 0 ] === '\u2212' ) yearString = `-${ yearString . slice ( 1 ) } ` ;
@@ -380,19 +380,23 @@ function ParseISODateTime(isoString: string, { zoneRequired }: { zoneRequired: b
380380}
381381
382382function 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 ;
384386}
385387
386388function 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 ;
388392}
389393
390394function ParseTemporalDateTimeString ( isoString : string ) {
391- return ParseISODateTime ( isoString , { zoneRequired : false } ) ;
395+ return ParseISODateTime ( isoString ) ;
392396}
393397
394398function ParseTemporalDateString ( isoString : string ) {
395- return ParseISODateTime ( isoString , { zoneRequired : false } ) ;
399+ return ParseISODateTime ( isoString ) ;
396400}
397401
398402function ParseTemporalTimeString ( isoString : string ) {
@@ -410,9 +414,7 @@ function ParseTemporalTimeString(isoString: string) {
410414 calendar = match [ 15 ] ;
411415 } else {
412416 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 ) ) ;
416418 if ( z ) throw new RangeError ( 'Z designator not supported for PlainTime' ) ;
417419 }
418420 return { hour, minute, second, millisecond, microsecond, nanosecond, calendar } ;
@@ -429,7 +431,7 @@ function ParseTemporalYearMonthString(isoString: string) {
429431 calendar = match [ 3 ] ;
430432 } else {
431433 let z ;
432- ( { year, month, calendar, day : referenceISODay , z } = ParseISODateTime ( isoString , { zoneRequired : false } ) ) ;
434+ ( { year, month, calendar, day : referenceISODay , z } = ParseISODateTime ( isoString ) ) ;
433435 if ( z ) throw new RangeError ( 'Z designator not supported for PlainYearMonth' ) ;
434436 }
435437 return { year, month, calendar, referenceISODay } ;
@@ -443,7 +445,7 @@ function ParseTemporalMonthDayString(isoString: string) {
443445 day = ToInteger ( match [ 2 ] ) ;
444446 } else {
445447 let z ;
446- ( { month, day, calendar, year : referenceISOYear , z } = ParseISODateTime ( isoString , { zoneRequired : false } ) ) ;
448+ ( { month, day, calendar, year : referenceISOYear , z } = ParseISODateTime ( isoString ) ) ;
447449 if ( z ) throw new RangeError ( 'Z designator not supported for PlainMonthDay' ) ;
448450 }
449451 return { month, day, calendar, referenceISOYear } ;
@@ -466,10 +468,14 @@ function ParseTemporalTimeZoneString(stringIdent: string): Partial<{
466468 }
467469 try {
468470 // 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+ }
470475 } catch {
471- throw new RangeError ( `Invalid time zone: ${ stringIdent } ` ) ;
476+ // fall through
472477 }
478+ throw new RangeError ( `Invalid time zone: ${ stringIdent } ` ) ;
473479}
474480
475481function ParseTemporalDurationString ( isoString : string ) {
@@ -514,7 +520,6 @@ function ParseTemporalInstant(isoString: string) {
514520
515521 const epochNs = GetEpochFromISOParts ( year , month , day , hour , minute , second , millisecond , microsecond , nanosecond ) ;
516522 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' ) ;
518523 const offsetNs = z ? 0 : ParseTimeZoneOffsetString ( offset ) ;
519524 return JSBI . subtract ( epochNs , JSBI . BigInt ( offsetNs ) ) ;
520525}
@@ -982,7 +987,7 @@ export function ToRelativeTemporalObject(options: {
982987 } else {
983988 let ianaName , z ;
984989 ( { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond, calendar, ianaName, offset, z } =
985- ParseISODateTime ( ToString ( relativeTo ) , { zoneRequired : false } ) ) ;
990+ ParseISODateTime ( ToString ( relativeTo ) ) ) ;
986991 if ( ianaName ) timeZone = ianaName ;
987992 if ( z ) {
988993 offsetBehaviour = 'exact' ;
@@ -2083,7 +2088,7 @@ export function ToTemporalCalendar(calendarLikeParam: CalendarParams['from'][0])
20832088 if ( IsBuiltinCalendar ( identifier ) ) return new TemporalCalendar ( identifier ) ;
20842089 let calendar ;
20852090 try {
2086- ( { calendar } = ParseISODateTime ( identifier , { zoneRequired : false } ) ) ;
2091+ ( { calendar } = ParseISODateTime ( identifier ) ) ;
20872092 } catch {
20882093 throw new RangeError ( `Invalid calendar: ${ identifier } ` ) ;
20892094 }
0 commit comments