From faa111351f3585904ce173019a65f7e8891a7a79 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 25 Aug 2022 11:45:35 -0700 Subject: [PATCH] Normative: Add calendarName: "critical" option to toString() methods This adds a new recognized value "critical" to the calendarName option of the toString() methods of PlainDate, PlainDateTime, PlainYearMonth, PlainMonthDay, and ZonedDateTime. calendarName: "critical" behaves like calendarName: "always", but it also outputs a "!" flag in the calendar annotation. This flag is never used by Temporal, but could be consumed by other programs. See: #1450 --- docs/plaindate.md | 3 ++- docs/plaindatetime.md | 3 ++- docs/plainmonthday.md | 3 ++- docs/plainyearmonth.md | 3 ++- docs/zoneddatetime.md | 3 ++- polyfill/lib/ecmascript.mjs | 9 +++++---- spec/abstractops.html | 2 +- spec/calendar.html | 7 ++++--- spec/plainmonthday.html | 2 +- spec/plainyearmonth.html | 2 +- spec/zoneddatetime.html | 2 +- 11 files changed, 23 insertions(+), 16 deletions(-) diff --git a/docs/plaindate.md b/docs/plaindate.md index b66dbc45a0..8208b77a4a 100644 --- a/docs/plaindate.md +++ b/docs/plaindate.md @@ -621,7 +621,7 @@ date.equals(date); // => true - `options` (optional object): An object with properties influencing the formatting. The following options are recognized: - `calendarName` (string): Whether to show the calendar annotation in the return value. - Valid values are `'auto'`, `'always'`, and `'never'`. + Valid values are `'auto'`, `'always'`, `'never'`, and `'critical'`. The default is `'auto'`. **Returns:** a string in the ISO 8601 date format representing `date`. @@ -631,6 +631,7 @@ The string can be passed to `Temporal.PlainDate.from()` to create a new `Tempora Normally, a calendar annotation is shown when `date`'s calendar is not the ISO 8601 calendar. By setting the `calendarName` option to `'always'` or `'never'` this can be overridden to always or never show the annotation, respectively. +Normally not necessary, a value of `'critical'` is equivalent to `'always'` but the annotation will contain an additional `!` for certain interoperation use cases. For more information on the calendar annotation, see [the `Temporal` string formats documentation](./strings.md#calendar-systems). Example usage: diff --git a/docs/plaindatetime.md b/docs/plaindatetime.md index d5deea83ef..28855a34aa 100644 --- a/docs/plaindatetime.md +++ b/docs/plaindatetime.md @@ -850,7 +850,7 @@ dt1.equals(dt1); // => true - `options` (optional object): An object with properties representing options for the operation. The following options are recognized: - `calendarName` (string): Whether to show the calendar annotation in the return value. - Valid values are `'auto'`, `'always'`, and `'never'`. + Valid values are `'auto'`, `'always'`, `'never'`, and `'critical'`. The default is `'auto'`. - `fractionalSecondDigits` (number or string): How many digits to print after the decimal point in the output string. Valid values are `'auto'`, 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. @@ -875,6 +875,7 @@ Note that rounding may change the value of other units as well. Normally, a calendar annotation is shown when `datetime`'s calendar is not the ISO 8601 calendar. By setting the `calendarName` option to `'always'` or `'never'` this can be overridden to always or never show the annotation, respectively. +Normally not necessary, a value of `'critical'` is equivalent to `'always'` but the annotation will contain an additional `!` for certain interoperation use cases. For more information on the calendar annotation, see [the `Temporal` string formats documentation](./strings.md#calendar-systems). Example usage: diff --git a/docs/plainmonthday.md b/docs/plainmonthday.md index 238e8fff85..f5992b22fc 100644 --- a/docs/plainmonthday.md +++ b/docs/plainmonthday.md @@ -247,7 +247,7 @@ md2.equals({ monthCode: 'M02', day: 29 }); // => true - `options` (optional object): An object with properties influencing the formatting. The following options are recognized: - `calendarName` (string): Whether to show the calendar annotation in the return value. - Valid values are `'auto'`, `'always'`, and `'never'`. + Valid values are `'auto'`, `'always'`, `'never'`, and `'critical'`. The default is `'auto'`. **Returns:** a string in the ISO 8601 date format representing `monthDay`. @@ -257,6 +257,7 @@ The string can be passed to `Temporal.PlainMonthDay.from()` to create a new `Tem Normally, a calendar annotation is shown when `monthDay`'s calendar is not the ISO 8601 calendar. By setting the `calendarName` option to `'always'` or `'never'` this can be overridden to always or never show the annotation, respectively. +Normally not necessary, a value of `'critical'` is equivalent to `'always'` but the annotation will contain an additional `!` for certain interoperation use cases. For more information on the calendar annotation, see [the `Temporal` string formats documentation](./strings.md#calendar-systems). Example usage: diff --git a/docs/plainyearmonth.md b/docs/plainyearmonth.md index 29a5b7dd8f..10b34d11c1 100644 --- a/docs/plainyearmonth.md +++ b/docs/plainyearmonth.md @@ -509,7 +509,7 @@ ym.equals(ym); // => true - `options` (optional object): An object with properties influencing the formatting. The following options are recognized: - `calendarName` (string): Whether to show the calendar annotation in the return value. - Valid values are `'auto'`, `'always'`, and `'never'`. + Valid values are `'auto'`, `'always'`, `'never'`, and `'critical'`. The default is `'auto'`. **Returns:** a string in the ISO 8601 date format representing `yearMonth`. @@ -519,6 +519,7 @@ The string can be passed to `Temporal.PlainYearMonth.from()` to create a new `Te Normally, a calendar annotation is shown when `yearMonth`'s calendar is not the ISO 8601 calendar. By setting the `calendarName` option to `'always'` or `'never'` this can be overridden to always or never show the annotation, respectively. +Normally not necessary, a value of `'critical'` is equivalent to `'always'` but the annotation will contain an additional `!` for certain interoperation use cases. For more information on the calendar annotation, see [the `Temporal` string formats documentation](./strings.md#calendar-systems). Example usage: diff --git a/docs/zoneddatetime.md b/docs/zoneddatetime.md index d94f250549..5744c02499 100644 --- a/docs/zoneddatetime.md +++ b/docs/zoneddatetime.md @@ -1248,7 +1248,7 @@ zdt1.equals(zdt1); // => true Valid values are `'auto'` and `'never'`. The default is `'auto'`. - `calendarName` (string): Whether to show the calendar annotation in the return value. - Valid values are `'auto'`, `'always'`, and `'never'`. + Valid values are `'auto'`, `'always'`, `'never'`, and `'critical'`. The default is `'auto'`. - `fractionalSecondDigits` (number or string): How many digits to print after the decimal point in the output string. Valid values are `'auto'`, 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9. @@ -1279,6 +1279,7 @@ Note that rounding may change the value of other units as well. Normally, a calendar annotation is shown when `zonedDateTime`'s calendar is not the ISO 8601 calendar. By setting the `calendarName` option to `'always'` or `'never'` this can be overridden to always or never show the annotation, respectively. +Normally not necessary, a value of `'critical'` is equivalent to `'always'` but the annotation will contain an additional `!` for certain interoperation use cases. For more information on the calendar annotation, see [ISO string extensions](./strings.md#calendar-systems). Likewise, passing `'never'` to the `timeZoneName` or `offset` options controls whether the time zone offset (`+01:00`) or name annotation (`[Europe/Paris]`) are shown. diff --git a/polyfill/lib/ecmascript.mjs b/polyfill/lib/ecmascript.mjs index 248f841d7e..eba28fac11 100644 --- a/polyfill/lib/ecmascript.mjs +++ b/polyfill/lib/ecmascript.mjs @@ -286,7 +286,8 @@ export const ES = ObjectAssign({}, ES2020, { FormatCalendarAnnotation: (id, showCalendar) => { if (showCalendar === 'never') return ''; if (showCalendar === 'auto' && id === 'iso8601') return ''; - return `[u-ca=${id}]`; + const flag = showCalendar === 'critical' ? '!' : ''; + return `[${flag}u-ca=${id}]`; }, ParseISODateTime: (isoString) => { // ZDT is the superset of fields for every other Temporal type @@ -718,7 +719,7 @@ export const ES = ObjectAssign({}, ES2020, { return ES.GetOption(options, 'offset', ['prefer', 'use', 'ignore', 'reject'], fallback); }, ToShowCalendarOption: (options) => { - return ES.GetOption(options, 'calendarName', ['auto', 'always', 'never'], 'auto'); + return ES.GetOption(options, 'calendarName', ['auto', 'always', 'never', 'critical'], 'auto'); }, ToShowTimeZoneNameOption: (options) => { return ES.GetOption(options, 'timeZoneName', ['auto', 'never'], 'auto'); @@ -2085,7 +2086,7 @@ export const ES = ObjectAssign({}, ES2020, { let resultString = `${month}-${day}`; const calendar = GetSlot(monthDay, CALENDAR); const calendarID = ES.ToString(calendar); - if (showCalendar === 'always' || calendarID !== 'iso8601') { + if (showCalendar === 'always' || showCalendar === 'critical' || calendarID !== 'iso8601') { const year = ES.ISOYearString(GetSlot(monthDay, ISO_YEAR)); resultString = `${year}-${resultString}`; } @@ -2099,7 +2100,7 @@ export const ES = ObjectAssign({}, ES2020, { let resultString = `${year}-${month}`; const calendar = GetSlot(yearMonth, CALENDAR); const calendarID = ES.ToString(calendar); - if (showCalendar === 'always' || calendarID !== 'iso8601') { + if (showCalendar === 'always' || showCalendar === 'critical' || calendarID !== 'iso8601') { const day = ES.ISODateTimePartString(GetSlot(yearMonth, ISO_DAY)); resultString += `-${day}`; } diff --git a/spec/abstractops.html b/spec/abstractops.html index 3e8e5c771b..5d8fc37593 100644 --- a/spec/abstractops.html +++ b/spec/abstractops.html @@ -148,7 +148,7 @@

ToShowCalendarOption ( _normalizedOptions_ )

This property is used in `toString` methods in Temporal to control whether a calendar annotation should be output. - 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, *"string"*, « *"auto"*, *"always"*, *"never"* », *"auto"*). + 1. Return ? GetOption(_normalizedOptions_, *"calendarName"*, *"string"*, « *"auto"*, *"always"*, *"never"*, *"critical"* », *"auto"*). diff --git a/spec/calendar.html b/spec/calendar.html index b16c9fc8e7..dfb2df5f14 100644 --- a/spec/calendar.html +++ b/spec/calendar.html @@ -393,7 +393,7 @@

MaybeFormatCalendarAnnotation ( _calendarObject_: an Object or *undefined*, - _showCalendar_: one of *"auto"*, *"always"*, or *"never"*, + _showCalendar_: one of *"auto"*, *"always"*, *"never"*, or *"critical"*, ): either a normal completion containing a String, or an abrupt completion

@@ -419,7 +419,7 @@

FormatCalendarAnnotation ( _id_: a String, - _showCalendar_: one of *"auto"*, *"always"*, or *"never"*, + _showCalendar_: one of *"auto"*, *"always"*, *"never"*, or *"critical"*, ): a String

@@ -432,7 +432,8 @@

1. If _showCalendar_ is *"never"*, return the empty String. 1. If _showCalendar_ is *"auto"* and _id_ is *"iso8601"*, return the empty String. - 1. Return the string-concatenation of *"[u-ca="*, _id_, and *"]"*. + 1. If _showCalendar_ is *"critical"*, let _flag_ be *"!"*; else, let flag be the empty String. + 1. Return the string-concatenation of *"["*, _flag_, *"u-ca="*, _id_, and *"]"*. The exact form this annotation will take is undergoing a standardization process in the IETF; it is being discussed in the Internet Draft Date and Time on the Internet: Timestamps with additional information. diff --git a/spec/plainmonthday.html b/spec/plainmonthday.html index 72fa5ce3eb..d86a1f5ad8 100644 --- a/spec/plainmonthday.html +++ b/spec/plainmonthday.html @@ -408,7 +408,7 @@

TemporalMonthDayToString ( _monthDay_, _showCalendar_ )

1. Let _day_ be ToZeroPaddedDecimalString(_monthDay_.[[ISODay]], 2). 1. Let _result_ be the string-concatenation of _month_, the code unit 0x002D (HYPHEN-MINUS), and _day_. 1. Let _calendarID_ be ? ToString(_monthDay_.[[Calendar]]). - 1. If _showCalendar_ is *"always"* or if _calendarID_ is not *"iso8601"*, then + 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarID_ is not *"iso8601"*, then 1. Let _year_ be ! PadISOYear(_monthDay_.[[ISOYear]]). 1. Set _result_ to the string-concatenation of _year_, the code unit 0x002D (HYPHEN-MINUS), and _result_. 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarID_, _showCalendar_). diff --git a/spec/plainyearmonth.html b/spec/plainyearmonth.html index d438371f95..c684693e45 100644 --- a/spec/plainyearmonth.html +++ b/spec/plainyearmonth.html @@ -587,7 +587,7 @@

TemporalYearMonthToString ( _yearMonth_, _showCalendar_ )

1. Let _month_ be ToZeroPaddedDecimalString(_yearMonth_.[[ISOMonth]], 2). 1. Let _result_ be the string-concatenation of _year_, the code unit 0x002D (HYPHEN-MINUS), and _month_. 1. Let _calendarID_ be ? ToString(_yearMonth_.[[Calendar]]). - 1. If _showCalendar_ is *"always"* or if _calendarID_ is not *"iso8601"*, then + 1. If _showCalendar_ is one of *"always"* or *"critical"*, or if _calendarID_ is not *"iso8601"*, then 1. Let _day_ be ToZeroPaddedDecimalString(_yearMonth_.[[ISODay]], 2). 1. Set _result_ to the string-concatenation of _result_, the code unit 0x002D (HYPHEN-MINUS), and _day_. 1. Let _calendarString_ be FormatCalendarAnnotation(_calendarID_, _showCalendar_). diff --git a/spec/zoneddatetime.html b/spec/zoneddatetime.html index 40dec73716..b3fa2fd0e3 100644 --- a/spec/zoneddatetime.html +++ b/spec/zoneddatetime.html @@ -1162,7 +1162,7 @@

TemporalZonedDateTimeToString ( _zonedDateTime_: a Temporal.ZonedDateTime, _precision_: one of *"auto"*, *"minute"*, or an integer between 0 and 9 inclusive, - _showCalendar_: one of *"auto"*, *"always"*, or *"never"*, + _showCalendar_: one of *"auto"*, *"always"*, *"never"*, or *"critical"*, _showTimeZone_: one of *"auto"* or *"never"*, _showOffset_: one of *"auto"* or *"never"*, optional _increment_: an integer,