Skip to content

Commit

Permalink
Normative: Allow annotations after YYYY-MM and MM-DD
Browse files Browse the repository at this point in the history
In keeping with the IXDTF format which extends the grammar of RFC 3339
with any number of annotations, we should allow annotations after the
short YYYY-MM PlainYearMonth and MM-DD PlainMonthDay forms.

If we were to allow UTC offsets ±UU[:UU] alongside the time zone
annotation, that would be ambiguous in one case: YYYY-MM-UU would be
ambiguous with YYYY-MM-DD. This forced us to take another look at ISO 8601
and realize that YYYY-MM-DD-UU and YYYY-MM-DDZ are actually not defined by
ISO 8601. Although they are not forbidden either, but we don't have any
reason to introduce this notation given the set of Temporal types.
Therefore, UTC offsets are disallowed after any date-only notation (that
is, YYYY-MM-DD, YYYY-MM, and MM-DD.)

Closes: #2379
  • Loading branch information
ptomato committed Dec 1, 2022
1 parent 9cd448a commit 160e836
Showing 1 changed file with 29 additions and 28 deletions.
57 changes: 29 additions & 28 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,6 @@ <h1>ISO 8601 grammar</h1>
Time zone and <a href="https://tools.ietf.org/html/bcp47#section-2.1">BCP 47 calendar</a> suffixes are the only recognized ones.
Others are ignored, unless they are marked with a *!*, in which case they are rejected.
</li>
<li>A time zone suffix may be instead of or in addition to a UTC offset.</li>
<li>A space may be used to separate the date and time in a combined date / time representation, but not in a duration.</li>
<li>Alphabetic designators may be in lower or upper case.</li>
<li>Period or comma may be used as the decimal separator.</li>
Expand Down Expand Up @@ -1032,19 +1031,9 @@ <h1>ISO 8601 grammar</h1>
TimeZoneIANAName
TimeZoneUTCOffsetName

TimeZoneBracketedAnnotation :
TimeZoneAnnotation :
`[` AnnotationCriticalFlag? TimeZoneIdentifier `]`

TimeZoneOffsetRequired :
TimeZoneUTCOffset TimeZoneBracketedAnnotation?

TimeZoneNameRequired :
TimeZoneUTCOffset? TimeZoneBracketedAnnotation

TimeZone :
TimeZoneUTCOffset TimeZoneBracketedAnnotation?
TimeZoneBracketedAnnotation

AKeyLeadingChar :
LowercaseAlpha
`_`
Expand Down Expand Up @@ -1087,24 +1076,28 @@ <h1>ISO 8601 grammar</h1>
TimeHour `:` TimeMinute `:` TimeSecond TimeFraction?
TimeHour TimeMinute TimeSecond TimeFraction?

TimeSpecWithOptionalTimeZoneNotAmbiguous :
TimeSpec TimeZone? but not one of ValidMonthDay or DateSpecYearMonth

TimeSpecSeparator :
DateTimeSeparator TimeSpec
TimeSpecWithOptionalOffsetNotAmbiguous :
TimeSpec TimeZoneUTCOffset? but not one of ValidMonthDay or DateSpecYearMonth

DateTime :
Date TimeSpecSeparator? TimeZone?
Date
Date DateTimeSeparator TimeSpec TimeZoneUTCOffset?

AnnotatedTime :
TimeDesignator TimeSpec TimeZone? Annotations?
TimeSpecWithOptionalTimeZoneNotAmbiguous Annotations?
TimeDesignator TimeSpec TimeZoneUTCOffset? TimeZoneAnnotation? Annotations?
TimeSpecWithOptionalOffsetNotAmbiguous TimeZoneAnnotation? Annotations?

AnnotatedDateTime:
DateTime Annotations?
DateTime TimeZoneAnnotation? Annotations?

AnnotatedDateTimeTimeRequired :
Date TimeSpecSeparator TimeZone? Annotations?
Date DateTimeSeparator TimeSpec TimeZoneUTCOffset? TimeZoneAnnotation? Annotations?

AnnotatedYearMonth:
DateSpecYearMonth TimeZoneAnnotation? Annotations?

AnnotatedMonthDay:
DateSpecMonthDay TimeZoneAnnotation? Annotations?

DurationWholeSeconds :
DecimalDigits[~Sep]
Expand Down Expand Up @@ -1177,7 +1170,7 @@ <h1>ISO 8601 grammar</h1>
Sign? DurationDesignator DurationTime

TemporalInstantString :
Date TimeSpecSeparator? TimeZoneOffsetRequired Annotations?
Date DateTimeSeparator TimeSpec TimeZoneUTCOffset TimeZoneAnnotation? Annotations?

TemporalDateTimeString :
AnnotatedDateTime
Expand All @@ -1186,19 +1179,19 @@ <h1>ISO 8601 grammar</h1>
Duration

TemporalMonthDayString :
DateSpecMonthDay
AnnotatedMonthDay
AnnotatedDateTime

TemporalTimeString :
AnnotatedTime
AnnotatedDateTimeTimeRequired

TemporalYearMonthString :
DateSpecYearMonth
AnnotatedYearMonth
AnnotatedDateTime

TemporalZonedDateTimeString :
Date TimeSpecSeparator? TimeZoneNameRequired Annotations?
DateTime TimeZoneAnnotation Annotations?
</emu-grammar>

<emu-clause id="sec-temporal-iso8601grammar-early-errors">
Expand Down Expand Up @@ -1228,8 +1221,16 @@ <h1>
<emu-note>The value of ! ToIntegerOrInfinity(*undefined*) is 0.</emu-note>
<emu-alg>
1. Let _parseResult_ be ~empty~.
1. For each nonterminal _goal_ of &laquo; |TemporalDateTimeString|, |TemporalInstantString|, |TemporalMonthDayString|, |TemporalTimeString|, |TemporalYearMonthString|, |TemporalZonedDateTimeString| &raquo;, do
1. For each nonterminal _goal_ of &laquo; |TemporalDateTimeString|, |TemporalInstantString|, |TemporalTimeString|, |TemporalZonedDateTimeString| &raquo;, do
1. If _parseResult_ is not a Parse Node, set _parseResult_ to ParseText(StringToCodePoints(_isoString_), _goal_).
1. For each nonterminal _goal_ of &laquo; |TemporalMonthDayString|, |TemporalYearMonthString| &raquo;, do
1. If _parseResult_ is not a Parse Node, then
1. Set _parseResult_ to ParseText(StringToCodePoints(_isoString_), _goal_).
1. If _parseResult_ is a Parse Node, then
1. For each |Annotation| Parse Node _annotation_ contained within _parseResult_, do
1. Let _key_ be the source text matched by the |AnnotationKey| Parse Node contained within _annotation_.
1. Let _value_ be the source text matched by the |AnnotationValue| Parse Node contained within _annotation_.
1. If CodePointsToString(_key_) is *"u-ca"* and the ASCII-lowercase of CodePointsToString(_value_) is not *"iso8601"*, throw a *RangeError* exception.
1. If _parseResult_ is not a Parse Node, throw a *RangeError* exception.
1. Let each of _year_, _month_, _day_, _hour_, _minute_, _second_, and _fSeconds_ be the source text matched by the respective |DateYear|, |DateMonth|, |DateDay|, |TimeHour|, |TimeMinute|, |TimeSecond|, and |TimeFraction| Parse Node contained within _parseResult_, or an empty sequence of code points if not present.
1. If the first code point of _year_ is U+2212 (MINUS SIGN), replace the first code point with U+002D (HYPHEN-MINUS).
Expand Down Expand Up @@ -1500,7 +1501,7 @@ <h1>
<emu-alg>
1. Let _parseResult_ be ParseText(StringToCodePoints(_isoString_), |TemporalDateTimeString|).
1. If _parseResult_ is a List of errors, throw a *RangeError* exception.
1. If _parseResult_ contains a |UTCDesignator| ParseNode but no |TimeZoneBracketedAnnotation| Parse Node, throw a *RangeError* exception.
1. If _parseResult_ contains a |UTCDesignator| ParseNode but no |TimeZoneAnnotation| Parse Node, throw a *RangeError* exception.
1. Return ? ParseISODateTime(_isoString_).
</emu-alg>
</emu-clause>
Expand Down

0 comments on commit 160e836

Please sign in to comment.