From aea146dbd1f015bd7a0d03dc23accbef26529e59 Mon Sep 17 00:00:00 2001
From: Ujjwal Sharma
Date: Wed, 3 Feb 2021 20:24:28 +0530
Subject: [PATCH] WIP rebase ecma402
---
spec/biblio.json | 15 +++++
spec/intl.html | 167 ++++++++++++++++++++++++-----------------------
2 files changed, 99 insertions(+), 83 deletions(-)
diff --git a/spec/biblio.json b/spec/biblio.json
index df0e0fb7e9..0c5bef9af5 100644
--- a/spec/biblio.json
+++ b/spec/biblio.json
@@ -101,6 +101,21 @@
"type": "term",
"term": "%NumberFormat%",
"id": "sec-intl-numberformat-constructor"
+ },
+ {
+ "type": "clause",
+ "number": "Table 7",
+ "id": "table-datetimeformat-components"
+ },
+ {
+ "type": "clause",
+ "number": "Table 8",
+ "id": "table-datetimeformat-tolocaltime-record"
+ },
+ {
+ "type": "op",
+ "aoid": "DateTimeStyleFormat",
+ "id": "sec-date-time-style-format"
}
],
"https://tc39.es/proposal-intl-duration-format/": [
diff --git a/spec/intl.html b/spec/intl.html
index 7b77b2d489..78a4730c3b 100644
--- a/spec/intl.html
+++ b/spec/intl.html
@@ -9,6 +9,9 @@ Amendments to the ECMAScript® 2021 Internationalization API Specification
This section lists amendments which must be made to ECMA-402, the ECMAScript® 2021 Internationalization API Specification.
Text to be added is marked like this, and text to be deleted is marked like this.
+
+ This text is based on top of the ECMA-402 spec text from commit b5edf2cdcca8d69590796cd41abf8399d249b8a1.
+
@@ -83,64 +86,6 @@ DefaultTimeZone (
-
- Components of date and time formats
-
-
-
- Internal Slot |
- Property |
- Values |
-
-
-
- [[Weekday]] |
- *"weekday"* |
- *"narrow"*, *"short"*, *"long"* |
-
-
- [[Era]] |
- *"era"* |
- *"narrow"*, *"short"*, *"long"* |
-
-
- [[Year]] |
- *"year"* |
- *"2-digit"*, *"numeric"* |
-
-
- [[Month]] |
- *"month"* |
- *"2-digit"*, *"numeric"*, *"narrow"*, *"short"*, *"long"* |
-
-
- [[Day]] |
- *"day"* |
- *"2-digit"*, *"numeric"* |
-
-
- [[Hour]] |
- *"hour"* |
- *"2-digit"*, *"numeric"* |
-
-
- [[Minute]] |
- *"minute"* |
- *"2-digit"*, *"numeric"* |
-
-
- [[Second]] |
- *"second"* |
- *"2-digit"*, *"numeric"* |
-
-
- [[TimeZoneName]] |
- *"timeZoneName"* |
- *"short"*, *"long"* |
-
-
-
-
InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )
@@ -167,12 +112,12 @@ InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )
1. If _numberingSystem_ does not match the Unicode Locale Identifier `type` nonterminal, throw a *RangeError* exception.
1. Set _opt_.[[nu]] to _numberingSystem_.
1. Let _hour12_ be ? GetOption(_options_, *"hour12"*, *"boolean"*, *undefined*, *undefined*).
- 1. Let _hourCycle_ be ? GetOption(_options_, *"hourCycle"*, *"string"*, « *"h11"*, *"h12"*, *"h23"*, *"h24"* », *undefined*).
+ 1. Let _hourCycle_ be ? GetOption(_options_, *"hourCycle"*, *"string"*, « *"h11"*, *"h12"*, *"h23"*, *"h24"* », *undefined*).
1. If _hour12_ is not *undefined*, then
1. Let _hourCycle_ be *null*.
1. Set _opt_.[[hc]] to _hourCycle_.
1. Let _localeData_ be %DateTimeFormat%.[[LocaleData]].
- 1. Let _r_ be ResolveLocale( %DateTimeFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %DateTimeFormat%.[[RelevantExtensionKeys]], _localeData_).
+ 1. Let _r_ be ResolveLocale(%DateTimeFormat%.[[AvailableLocales]], _requestedLocales_, _opt_, %DateTimeFormat%.[[RelevantExtensionKeys]], _localeData_).
1. Set _dateTimeFormat_.[[Locale]] to _r_.[[locale]].
1. Let _calendar_ be _r_.[[ca]].
1. Set _dateTimeFormat_.[[Calendar]] to _calendar_.
@@ -209,15 +154,40 @@ InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )
1. Let _opt_ be a new Record.
1. For each row of , except the header row, in table order, do
1. Let _prop_ be the name given in the Property column of the row.
- 1. Let _value_ be ? GetOption(_options_, _prop_, *"string"*, « the strings given in the Values column of the row », *undefined*).
+ 1. If _prop_ is *"fractionalSecondDigits"*, then
+ 1. Let _value_ be ? GetNumberOption(options, *"fractionalSecondDigits"*, 1, 3, *undefined*).
+ 1. Else,
+ 1. Let _value_ be ? GetOption(_options_, _prop_, *"string"*, « the strings given in the Values column of the row », *undefined*).
1. Set _opt_.[[<_prop_>]] to _value_.
1. Let _dataLocaleData_ be _localeData_.[[<_dataLocale_>]].
- 1. Let _formats_ be _dataLocaleData_.[[formats]].[[<_calendar_>]].
1. Let _matcher_ be ? GetOption(_options_, *"formatMatcher"*, *"string"*, « *"basic"*, *"best fit"* », *"best fit"*).
- 1. If _matcher_ is *"basic"*, then
- 1. Let _bestFormat_ be BasicFormatMatcher(_opt_, _formats_).
- 1. Else,
- 1. Let _bestFormat_ be BestFitFormatMatcher(_opt_, _formats_).
+ 1. Let _dateStyle_ be ? GetOption(_options_, *"dateStyle"*, *"string"*, « *"full"*, *"long"*, *"medium"*, *"short"* », *undefined*).
+ 1. Set _dateTimeFormat_.[[DateStyle]] to _dateStyle_.
+ 1. Let _timeStyle_ be ? GetOption(_options_, *"timeStyle"*, *"string"*, « *"full"*, *"long"*, *"medium"*, *"short"* », *undefined*).
+ 1. Set _dateTimeFormat_.[[TimeStyle]] to _timeStyle_.
+ 1. If _dateStyle_ is not *undefined* or _timeStyle_ is not *undefined*, then
+ 1. For each row in , except the header row, do
+ 1. Let _prop_ be the name given in the Property column of the row.
+ 1. Let _p_ be _opt_.[[<_prop_>]].
+ 1. If _p_ is not *undefined*, then
+ 1. Throw a *TypeError* exception.
+ 1. Let _bestFormat_ be DateTimeStyleFormat(_dateStyle_, _timeStyle_, _dataLocaleData_).
+ 1. TODO: figure out how to deal with Temporal objects here.
+ 1. Else,
+ 1. Let _formats_ be _dataLocaleData_.[[formats]].[[<_calendar_>]].
+ 1. If _matcher_ is *"basic"*, then
+ 1. Let _bestFormat_ be BasicFormatMatcher(_opt_, _formats_).
+ 1. Else,
+ 1. Let _bestFormat_ be BestFitFormatMatcher(_opt_, _formats_).
+ 1. Let _expandedOptions_ be a copy of _opt_.
+ 1. Let _needDefaults_ be *true*.
+ 1. For each element _field_ of « *"weekday"*, *"year"*, *"month"*, *"day"*, *"hour"*, *"minute"*, *"second"* » in List order, do
+ 1. If _expandedOptions_.[[<_field_>]] is not *undefined*, then
+ 1. Set _needDefaults_ to *false*.
+ 1. If _needDefaults_ is *true*, then
+ 1. For each element _field_ of « *"year"*, *"month"*, *"day"*, *"hour"*, *"minute"*, *"second"* » in List order, do
+ 1. Set _expandedOptions_.[[<_field_>]] to *"numeric"*.
+ 1. Let _bestFormat_ be GetDateTimeFormatPattern(_matcher_, _expandedOptions_, _formats_, _hc_).
1. For each row in , except the header row, in table order, do
1. Let _prop_ be the name given in the Property column of the row.
1. Let _p_ be _bestFormat_.[[<_prop_>]].
@@ -248,18 +218,7 @@ InitializeDateTimeFormat ( _dateTimeFormat_, _locales_, _options_ )
1. Let _pattern_ be _bestFormat_.[[pattern12]].
1. Else,
1. Let _pattern_ be _bestFormat_.[[pattern]].
- 1. Else,
- 1. Set _dateTimeFormat_.[[HourCycle]] to *undefined*.
- 1. Let _pattern_ be _bestFormat_.[[pattern]].
- 1. Let _expandedOptions_ be a copy of _opt_.
- 1. Let _needDefaults_ be *true*.
- 1. For each element _field_ of « *"weekday"*, *"year"*, *"month"*, *"day"*, *"hour"*, *"minute"*, *"second"* » in List order, do
- 1. If _expandedOptions_.[[<_field_>]] is not *undefined*, then
- 1. Set _needDefaults_ to *false*.
- 1. If _needDefaults_ is *true*, then
- 1. For each element _field_ of « *"year"*, *"month"*, *"day"*, *"hour"*, *"minute"*, *"second"* » in List order, do
- 1. Set _expandedOptions_.[[<_field_>]] to *"numeric"*.
- 1. Set _dateTimeFormat_.[[Pattern]] to _pattern_GetDateTimeFormatPattern(_matcher_, _expandedOptions_, _formats_, _hc_).
+ 1. Set _dateTimeFormat_.[[Pattern]] to _pattern__bestFormat_.[[pattern]].
1. For each row in , except the header row, in table order, do
1. Let _limitedOptions_ be a new Record.
1. Let _needDefaults_ be *true*.
@@ -434,6 +393,12 @@ PartitionDateTimePattern ( _dateTimeFormat_, _x_ )
1. Perform ! CreateDataPropertyOrThrow(_nf2Options_, *"minimumIntegerDigits"*, 2).
1. Perform ! CreateDataPropertyOrThrow(_nf2Options_, *"useGrouping"*, *false*).
1. Let _nf2_ be ? Construct(%NumberFormat%, « _locale_, _nf2Options_ »).
+ 1. Let _fractionalSecondDigits_ be _dateTimeFormat_.[[FractionalSecondDigits]].
+ 1. If _fractionalSecondDigits_ is not *undefined*, then
+ 1. Let _nf3Options_ be ObjectCreate(*null*).
+ 1. Perform ! CreateDataPropertyOrThrow(_nf3Options_, *"minimumIntegerDigits"*, _fractionalSecondDigits_).
+ 1. Perform ! CreateDataPropertyOrThrow(_nf3Options_, *"useGrouping"*, *false*).
+ 1. Let _nf3_ be ? Construct(%NumberFormat%, « _locale_, _nf3Options_ »).
1. Let _tm_ be ToLocalTime(_x__epochNanoseconds_, _dateTimeFormat_.[[Calendar]], _dateTimeFormat_.[[TimeZone]]).
1. Let _result_ be a new empty List.
1. Let _patternParts_ be PartitionPattern(_dateTimeFormat_.[[Pattern]]_pattern_).
@@ -441,6 +406,11 @@ PartitionDateTimePattern ( _dateTimeFormat_, _x_ )
1. Let _p_ be _patternPart_.[[Type]].
1. If _p_ is *"literal"*, then
1. Append a new Record { [[Type]]: *"literal"*, [[Value]]: _patternPart_.[[Value]] } as the last element of the list _result_.
+ 1. Else if _p_ is equal to *"fractionalSecondDigits"*, then
+ 1. Let _v_ be _tm_.[[Millisecond]].
+ 1. Let _v_ be floor(_v_ × 10( _fractionalSecondDigits_ - 3 )).
+ 1. Let _fv_ be FormatNumeric(_nf3_, _v_).
+ 1. Append a new Record { [[Type]]: *"fractionalSecond"*, [[Value]]: _fv_ } as the last element of _result_.
1. Else if _p_ matches a Property column of the row in , then
1. Let _f_ be the value of _dateTimeFormat_'s internal slot whose name is the Internal Slot column of the matching row_pattern_.[[<_p_>]].
1. Let _v_ be the value of _tm_'s field whose name is the Internal Slot column of the matching row.
@@ -461,7 +431,7 @@ PartitionDateTimePattern ( _dateTimeFormat_, _x_ )
1. Else if _f_ is *"2-digit"*, then
1. Let _fv_ be FormatNumeric(_nf2_, _v_).
1. If the *"length"* property of _fv_ is greater than 2, let _fv_ be the substring of _fv_ containing the last two characters.
- 1. Else if _f_ is *"narrow"*, *"short"*, or *"long"*, then let _fv_ be a String value representing _f_ in the desired form; the String value depends upon the implementation and the effective locale and calendar of _dateTimeFormat_. If _p_ is *"month"*, then the String value may also depend on whether _dateTimeFormat_ has a [[Day]]_pattern_ has a [[day]] internal slot. If _p_ is *"timeZoneName"*, then the String value may also depend on the value of the [[InDST]] field of _tm_. If _p_ is *"era"*, then the String value may also depend on whether _dateTimeFormat_ has a [[Era]]_pattern_ has a [[era]] internal slot and if the implementation does not have a localized representation of _f_, then use _f_ itself.
+ 1. Else if _f_ is *"narrow"*, *"short"*, or *"long"*, then let _fv_ be a String value representing _v_ in the form given by _f_; the String value depends upon the implementation and the effective locale and calendar of _dateTimeFormat_. If _p_ is *"month"*, then the String value may also depend on whether _dateTimeFormat_ has a [[Day]]_pattern_ has a [[day]] internal slot. If _p_ is *"timeZoneName"*, then the String value may also depend on the value of the [[InDST]] field of _tm_. If _p_ is *"era"*, then the String value may also depend on whether _dateTimeFormat_ has a [[Era]]_pattern_ has a [[era]] internal slot and if the implementation does not have a localized representation of _f_, then use _f_ itself.
1. Append a new Record { [[Type]]: _p_, [[Value]]: _fv_ } as the last element of the list _result_.
1. Else if _p_ is equal to *"ampm"*, then
1. Let _v_ be _tm_.[[Hour]].
@@ -585,10 +555,9 @@ ToLocalTime ( _t_, _calendar_, _timeZone_ )
1. Let _timeZoneOffset_ be the value calculated according to LocalTZA(_t_, *true*) where the local time zone is replaced with timezone _timeZone_.
1. Let _timeZoneOffset_ be ! GetIANATimeZoneOffsetNanoseconds(_t_, _timeZone_).
1. Let _tz_ be the time value _t_ + _timeZoneOffset_.
- 1. Return a record with fields calculated from _tz_ according to .
+ 1. Return a record with fields calculated from _tz_ according to .
1. Else,
- 1. Return a record with the fields of Column 1 of calculated from _t_ for the given _calendar_ and _timeZone_. The calculations should use best available information about the specified _calendar_ and _timeZone_, including current and historical information about time zone offsets from UTC and daylight saving time rules.
- Given the same values of _t_, _calendar_, and _timeZone_, the result must be the same for the lifetime of the surrounding agent.
+ 1. Return a record with the fields of Column 1 of calculated from _t_ for the given _calendar_ and _timeZone_. The calculations should use best available information about the specified _calendar_ and _timeZone_, including current and historical information about time zone offsets from UTC and daylight saving time rules. Given the same values of _t_, _calendar_, and _timeZone_, the result must be the same for the lifetime of the surrounding agent.
@@ -664,6 +633,13 @@ ToLocalTime ( _t_, _calendar_, _timeZone_ )
! SecFromTime(_tz_ / 106)
+
+ [[Millisecond]] |
+
+ `msFromTime(tz)` specified in ES2021's Hours, Minutes, Second, and Milliseconds
+ ! msFromTime(_tz_ / 106)
+ |
+
[[Nanosecond]] |
_tz_ modulo 109 |
@@ -734,6 +710,9 @@ Intl.DateTimeFormat.prototype.resolvedOptions ( )
1. Else,
1. Assert: the Location value of the current row is ~pattern~.
1. Let _v_ be the value of _dtf_.[[Pattern]]'s internal slot whose name is the Internal Slot value of the current row.
+ 1. If the Internal Slot value of the current row is an Internal Slot value in , then
+ 1. If _dtf_.[[DateStyle]] is not *undefined* or _dtf_.[[TimeStyle]] is not *undefined*, then
+ 1. Let _v_ be *undefined*.
1. If _v_ is not *undefined*, then
1. Perform ! CreateDataPropertyOrThrow(_options_, _p_, _v_).
1. Return _options_.
@@ -804,6 +783,11 @@ Intl.DateTimeFormat.prototype.resolvedOptions ( )
*"day"* |
~pattern~ |
+
+ [[DayPeriod]][[dayPeriod]] |
+ *"dayPeriod"* |
+ ~pattern~ |
+
[[Hour]][[hour]] |
*"hour"* |
@@ -819,10 +803,25 @@ Intl.DateTimeFormat.prototype.resolvedOptions ( )
*"second"* |
~pattern~ |
+
+ [[FractionalSecondDigits]][[fractionalSecondDigits]] |
+ *"fractionalSecondDigits"* |
+ ~pattern~ |
+
[[TimeZoneName]][[timeZoneName]] |
*"timeZoneName"* |
~pattern~ |
+
+ [[DateStyle]] |
+ *"dateStyle"* |
+ ~object~ |
+
+
+ [[TimeStyle]] |
+ *"timeStyle"* |
+ ~object~ |
+
@@ -861,8 +860,10 @@