diff --git a/spec/annexes.html b/spec/annexes.html index 95079e09..aca91b12 100644 --- a/spec/annexes.html +++ b/spec/annexes.html @@ -181,6 +181,12 @@

Implementation Dependent Behaviour

+
  • + In Temporal: + +
  • diff --git a/spec/datetimeformat.html b/spec/datetimeformat.html index ce9f82ca..37791a19 100644 --- a/spec/datetimeformat.html +++ b/spec/datetimeformat.html @@ -53,14 +53,17 @@

    _options_: an ECMAScript language value, _required_: ~date~, ~time~, or ~any~, _defaults_: ~date~, ~time~, or ~all~, + optional _toLocaleStringTimeZone_: a primary time zone identifier, ): either a normal completion containing a DateTimeFormat object or a throw completion

    +
    description
    +
    _toLocaleStringTimeZone_ supports the behaviour of %Temporal.ZonedDateTime.prototype.toLocaleString%.
    - 1. Let _dateTimeFormat_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Intl.DateTimeFormat.prototype%"*, « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[HourCycle]], [[DateStyle]], [[TimeStyle]], [[DateTimeFormat]], [[BoundFormat]] »). + 1. Let _dateTimeFormat_ be ? OrdinaryCreateFromConstructor(_newTarget_, *"%Intl.DateTimeFormat.prototype%"*, « [[InitializedDateTimeFormat]], [[Locale]], [[Calendar]], [[NumberingSystem]], [[TimeZone]], [[HourCycle]], [[DateStyle]], [[TimeStyle]], [[DateTimeFormat]], [[TemporalPlainDateFormat]], [[TemporalPlainYearMonthFormat]], [[TemporalPlainMonthDayFormat]], [[TemporalPlainTimeFormat]], [[TemporalPlainDateTimeFormat]], [[TemporalInstantFormat]], [[BoundFormat]] »). 1. Let _hour12_ be *undefined*. 1. Let _modifyResolutionOptions_ be a new Abstract Closure with parameters (_options_) that captures _hour12_ and performs the following steps when called: 1. Set _hour12_ to _options_.[[hour12]]. @@ -71,6 +74,9 @@

    1. Let _r_ be _optionsResolution_.[[ResolvedLocale]]. 1. Set _dateTimeFormat_.[[Locale]] to _r_.[[Locale]]. 1. Let _resolvedCalendar_ be _r_.[[ca]]. + 1. [id="step-calendar-fallback"] If _resolvedCalendar_ is *"islamic"*, then + 1. Set _resolvedCalendar_ to *"islamic-tbla"*. + 1. If the ECMAScript implementation has a mechanism for reporting diagnostic warning messages, a warning should be issued. 1. Set _dateTimeFormat_.[[Calendar]] to _resolvedCalendar_. 1. Set _dateTimeFormat_.[[NumberingSystem]] to _r_.[[nu]]. 1. Let _resolvedLocaleData_ be _r_.[[LocaleData]]. @@ -82,23 +88,23 @@

    1. Assert: _hour12_ is *undefined*. 1. Let _hc_ be _r_.[[hc]]. 1. If _hc_ is *null*, set _hc_ to _resolvedLocaleData_.[[hourCycle]]. + 1. Set _dateTimeFormat_.[[HourCycle]] to _hc_. 1. Let _timeZone_ be ? Get(_options_, *"timeZone"*). - 1. If _timeZone_ is *undefined*, then - 1. Set _timeZone_ to SystemTimeZoneIdentifier(). + 1. If _toLocaleStringTimeZone_ is present, then + 1. If _timeZone_ is not *undefined*, throw a *TypeError* exception. + 1. Set _timeZone_ to _toLocaleStringTimeZone_. 1. Else, - 1. Set _timeZone_ to ? ToString(_timeZone_). - 1. If IsTimeZoneOffsetString(_timeZone_) is *true*, then - 1. Let _parseResult_ be ParseText(StringToCodePoints(_timeZone_), |UTCOffset|). + 1. If _timeZone_ is *undefined*, set _timeZone_ to SystemTimeZoneIdentifier(); else, set _timeZone_ to ? ToString(_timeZone_). + 1. If IsOffsetTimeZoneIdentifier(_timeZone_) is *true*, then + 1. Let _parseResult_ be ParseText(StringToCodePoints(_timeZone_), |UTCOffset[~SubMinutePrecision]|). 1. Assert: _parseResult_ is a Parse Node. - 1. If _parseResult_ contains more than one |MinuteSecond| Parse Node, throw a *RangeError* exception. - 1. Let _offsetNanoseconds_ be ParseTimeZoneOffsetString(_timeZone_). + 1. Let _offsetNanoseconds_ be ? ParseDateTimeUTCOffset(_timeZone_). 1. Let _offsetMinutes_ be _offsetNanoseconds_ / (6 × 1010). - 1. Assert: _offsetMinutes_ is an integer. 1. Set _timeZone_ to FormatOffsetTimeZoneIdentifier(_offsetMinutes_). 1. Else, 1. Let _timeZoneIdentifierRecord_ be GetAvailableNamedTimeZoneIdentifier(_timeZone_). 1. If _timeZoneIdentifierRecord_ is ~empty~, throw a *RangeError* exception. - 1. Set _timeZone_ to _timeZoneIdentifierRecord_.[[PrimaryIdentifier]]. + 1. Set _timeZone_ to _timeZoneIdentifierRecord_.[[Identifier]]. 1. Set _dateTimeFormat_.[[TimeZone]] to _timeZone_. 1. Let _formatOptions_ be a new Record. 1. Set _formatOptions_.[[hourCycle]] to _hc_. @@ -118,6 +124,7 @@

    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. Let _formats_ be _resolvedLocaleData_.[[formats]].[[<_resolvedCalendar_>]]. 1. If _dateStyle_ is not *undefined* or _timeStyle_ is not *undefined*, then 1. If _hasExplicitFormatComponents_ is *true*, then 1. Throw a *TypeError* exception. @@ -127,54 +134,35 @@

    1. Throw a *TypeError* exception. 1. Let _styles_ be _resolvedLocaleData_.[[styles]].[[<_resolvedCalendar_>]]. 1. Let _bestFormat_ be DateTimeStyleFormat(_dateStyle_, _timeStyle_, _styles_). + 1. If _dateStyle_ is not *undefined*, then + 1. Set _dateTimeFormat_.[[TemporalPlainDateFormat]] to AdjustDateTimeStyleFormat(_formats_, _bestFormat_, _formatMatcher_, « *"weekday"*, *"era"*, *"year"*, *"month"*, *"day"* »). + 1. Set _dateTimeFormat_.[[TemporalPlainYearMonthFormat]] to AdjustDateTimeStyleFormat(_formats_, _bestFormat_, _formatMatcher_, « *"era"*, *"year"*, *"month"* »). + 1. Set _dateTimeFormat_.[[TemporalPlainMonthDayFormat]] to AdjustDateTimeStyleFormat(_formats_, _bestFormat_, _formatMatcher_, « *"month"*, *"day"* »). + 1. Else, + 1. Set _dateTimeFormat_.[[TemporalPlainDateFormat]] to *null*. + 1. Set _dateTimeFormat_.[[TemporalPlainYearMonthFormat]] to *null*. + 1. Set _dateTimeFormat_.[[TemporalPlainMonthDayFormat]] to *null*. + 1. If _timeStyle_ is not *undefined*, then + 1. Set _dateTimeFormat_.[[TemporalPlainTimeFormat]] to AdjustDateTimeStyleFormat(_formats_, _bestFormat_, _formatMatcher_, « *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* »). + 1. Else, + 1. Set _dateTimeFormat_.[[TemporalPlainTimeFormat]] to *null*. + 1. Set _dateTimeFormat_.[[TemporalPlainDateTimeFormat]] to AdjustDateTimeStyleFormat(_formats_, _bestFormat_, _formatMatcher_, « *"weekday"*, *"era"*, *"year"*, *"month"*, *"day"*, *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* »). + 1. Set _dateTimeFormat_.[[TemporalInstantFormat]] to _bestFormat_. 1. Else, - 1. Let _needDefaults_ be *true*. - 1. If _required_ is ~date~ or ~any~, then - 1. For each property name _prop_ of « *"weekday"*, *"year"*, *"month"*, *"day"* », do - 1. Let _value_ be _formatOptions_.[[<_prop_>]]. - 1. If _value_ is not *undefined*, set _needDefaults_ to *false*. - 1. If _required_ is ~time~ or ~any~, then - 1. For each property name _prop_ of « *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* », do - 1. Let _value_ be _formatOptions_.[[<_prop_>]]. - 1. If _value_ is not *undefined*, set _needDefaults_ to *false*. - 1. If _needDefaults_ is *true* and _defaults_ is either ~date~ or ~all~, then - 1. For each property name _prop_ of « *"year"*, *"month"*, *"day"* », do - 1. Set _formatOptions_.[[<_prop_>]] to *"numeric"*. - 1. If _needDefaults_ is *true* and _defaults_ is either ~time~ or ~all~, then - 1. For each property name _prop_ of « *"hour"*, *"minute"*, *"second"* », do - 1. Set _formatOptions_.[[<_prop_>]] to *"numeric"*. - 1. Let _formats_ be _resolvedLocaleData_.[[formats]].[[<_resolvedCalendar_>]]. - 1. If _formatMatcher_ is *"basic"*, then - 1. Let _bestFormat_ be BasicFormatMatcher(_formatOptions_, _formats_). + 1. Let _bestFormat_ be GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, _required_, _defaults_, ~all~). + 1. Set _dateTimeFormat_.[[TemporalPlainDateFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~date~, ~date~, ~relevant~). + 1. Set _dateTimeFormat_.[[TemporalPlainYearMonthFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~year-month~, ~year-month~, ~relevant~). + 1. Set _dateTimeFormat_.[[TemporalPlainMonthDayFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~month-day~, ~month-day~, ~relevant~). + 1. Set _dateTimeFormat_.[[TemporalPlainTimeFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~time~, ~time~, ~relevant~). + 1. Set _dateTimeFormat_.[[TemporalPlainDateTimeFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~any~, ~all~, ~relevant~). + 1. If _toLocaleStringTimeZone_ is present, then + 1. Set _dateTimeFormat_.[[TemporalInstantFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~any~, ~zoned-date-time~, ~all~). 1. Else, - 1. Let _bestFormat_ be BestFitFormatMatcher(_formatOptions_, _formats_). + 1. Set _dateTimeFormat_.[[TemporalInstantFormat]] to GetDateTimeFormat(_formats_, _formatMatcher_, _formatOptions_, ~any~, ~all~, ~all~). 1. Set _dateTimeFormat_.[[DateTimeFormat]] to _bestFormat_. - 1. If _bestFormat_ has a field [[hour]], then - 1. Set _dateTimeFormat_.[[HourCycle]] to _hc_. 1. Return _dateTimeFormat_. - - -

    - FormatOffsetTimeZoneIdentifier ( - _offsetMinutes_: an integer, - ): a String -

    -
    -
    description
    -
    - It formats a UTC offset, in minutes, into a UTC offset string formatted like ±HH:MM. -
    -
    - - 1. If _offsetMinutes_ ≥ 0, let _sign_ be the code unit 0x002B (PLUS SIGN); otherwise, let _sign_ be the code unit 0x002D (HYPHEN-MINUS). - 1. Let _absoluteMinutes_ be abs(_offsetMinutes_). - 1. Let _hours_ be floor(_absoluteMinutes_ / 60). - 1. Let _minutes_ be _absoluteMinutes_ modulo 60. - 1. Return the string-concatenation of _sign_, ToZeroPaddedDecimalString(_hours_, 2), the code unit 0x003A (COLON), and ToZeroPaddedDecimalString(_minutes_, 2). - -
    @@ -221,6 +209,10 @@

    Internal slots

    The value of the [[LocaleData]] internal slot is implementation-defined within the constraints described in and the following additional constraints, for all locale values _locale_:

      +
    • + [[LocaleData]].[[<_locale_>]].[[ca]] must be a List consisting of calendar types. + It may include calendar types not listed in , for the purposes of implementing a diagnostic warning message in cases where the locale data references unsupported calendars, as in Step of CreateDateTimeFormat. +
    • [[LocaleData]].[[<_locale_>]].[[nu]] must be a List that does not include the values *"native"*, *"traditio"*, or *"finance"*.
    • @@ -1056,8 +1048,8 @@

      Intl.DateTimeFormat.prototype.formatRange ( _startDate_, _endDate_ )

      1. Let _dtf_ be *this* value. 1. Perform ? RequireInternalSlot(_dtf_, [[InitializedDateTimeFormat]]). 1. If _startDate_ is *undefined* or _endDate_ is *undefined*, throw a *TypeError* exception. - 1. Let _x_ be ? ToNumber(_startDate_). - 1. Let _y_ be ? ToNumber(_endDate_). + 1. Let _x_ be ? ToDateTimeFormattable(_startDate_). + 1. Let _y_ be ? ToDateTimeFormattable(_endDate_). 1. Return ? FormatDateTimeRange(_dtf_, _x_, _y_). @@ -1071,8 +1063,8 @@

      Intl.DateTimeFormat.prototype.formatRangeToParts ( _startDate_, _endDate_ )< 1. Let _dtf_ be *this* value. 1. Perform ? RequireInternalSlot(_dtf_, [[InitializedDateTimeFormat]]). 1. If _startDate_ is *undefined* or _endDate_ is *undefined*, throw a *TypeError* exception. - 1. Let _x_ be ? ToNumber(_startDate_). - 1. Let _y_ be ? ToNumber(_endDate_). + 1. Let _x_ be ? ToDateTimeFormattable(_startDate_). + 1. Let _y_ be ? ToDateTimeFormattable(_endDate_). 1. Return ? FormatDateTimeRangeToParts(_dtf_, _x_, _y_). @@ -1088,7 +1080,7 @@

      Intl.DateTimeFormat.prototype.formatToParts ( _date_ )

      1. If _date_ is *undefined*, then 1. Let _x_ be ! Call(%Date.now%, *undefined*). 1. Else, - 1. Let _x_ be ? ToNumber(_date_). + 1. Let _x_ be ? ToDateTimeFormattable(_date_). 1. Return ? FormatDateTimeToParts(_dtf_, _x_). @@ -1115,10 +1107,16 @@

      Properties of Intl.DateTimeFormat Instances

    • [[Locale]] is a String value with the language tag of the locale whose localization is used for formatting.
    • [[Calendar]] is a String value representing the Unicode Calendar Identifier used for formatting.
    • [[NumberingSystem]] is a String value representing the Unicode Number System Identifier used for formatting.
    • -
    • [[TimeZone]] is a String value used for formatting that is either an available named time zone identifier or an offset time zone identifier.
    • -
    • [[HourCycle]] is a String value indicating whether the 12-hour format (*"h11"*, *"h12"*) or the 24-hour format (*"h23"*, *"h24"*) should be used. *"h11"* and *"h23"* start with hour 0 and go up to 11 and 23 respectively. *"h12"* and *"h24"* start with hour 1 and go up to 12 and 24. [[HourCycle]] is only used when [[DateTimeFormat]] has an [[hour]] field.
    • +
    • [[TimeZone]] is an available time zone identifier used for formatting.
    • +
    • [[HourCycle]] is a String value indicating whether the 12-hour format (*"h11"*, *"h12"*) or the 24-hour format (*"h23"*, *"h24"*) should be used. *"h11"* and *"h23"* start with hour 0 and go up to 11 and 23 respectively. *"h12"* and *"h24"* start with hour 1 and go up to 12 and 24.
    • [[DateStyle]], [[TimeStyle]] are each either *undefined*, or a String value with values *"full"*, *"long"*, *"medium"*, or *"short"*.
    • [[DateTimeFormat]] is a DateTime Format Record.
    • +
    • [[TemporalPlainDateFormat]] is either a DateTime Format Record or *null*.
    • +
    • [[TemporalPlainYearMonthFormat]] is either a DateTime Format Record or *null*.
    • +
    • [[TemporalPlainMonthDayFormat]] is either a DateTime Format Record or *null*.
    • +
    • [[TemporalPlainTimeFormat]] is either a DateTime Format Record or *null*.
    • +
    • [[TemporalPlainDateTimeFormat]] is a DateTime Format Record.
    • +
    • [[TemporalInstantFormat]] is a DateTime Format Record.

    Finally, Intl.DateTimeFormat instances have a [[BoundFormat]] internal slot that caches the function returned by the format accessor ().

    @@ -1197,6 +1195,73 @@

    Abstract Operations for DateTimeFormat Objects

    + +

    + GetDateTimeFormat ( + _formats_: a List of DateTime Format Records, + _matcher_: either *"basic"* or *"best fit"*, + _options_: a Record, + _required_: one of ~date~, ~time~, ~year-month~, ~month-day~, or ~any~, + _defaults_: one of ~date~, ~time~, ~year-month~, ~month-day~, ~zoned-date-time~, or ~all~, + _inherit_: either ~all~ or ~relevant~, + ): either a DateTime Format Record or *null* +

    +
    +
    + + 1. If _required_ is ~date~, then + 1. Let _requiredOptions_ be « *"weekday"*, *"year"*, *"month"*, *"day"* ». + 1. Else if _required_ is ~time~, then + 1. Let _requiredOptions_ be « *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* ». + 1. Else if _required_ is ~year-month~, then + 1. Let _requiredOptions_ be « *"year"*, *"month"* ». + 1. Else if _required_ is ~month-day~, then + 1. Let _requiredOptions_ be « *"month"*, *"day"* ». + 1. Else, + 1. Assert: _required_ is ~any~. + 1. Let _requiredOptions_ be « *"weekday"*, *"year"*, *"month"*, *"day"*, *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* ». + 1. If _defaults_ is ~date~, then + 1. Let _defaultOptions_ be « *"year"*, *"month"*, *"day"* ». + 1. Else if _defaults_ is ~time~, then + 1. Let _defaultOptions_ be « *"hour"*, *"minute"*, *"second"* ». + 1. Else if _defaults_ is ~year-month~, then + 1. Let _defaultOptions_ be « *"year"*, *"month"* ». + 1. Else if _defaults_ is ~month-day~, then + 1. Let _defaultOptions_ be « *"month"*, *"day"* ». + 1. Else, + 1. Assert: _defaults_ is ~zoned-date-time~ or ~all~. + 1. Let _defaultOptions_ be « *"year"*, *"month"*, *"day"*, *"hour"*, *"minute"*, *"second"* ». + 1. If _inherit_ is ~all~, then + 1. Let _formatOptions_ be a copy of _options_. + 1. Else, + 1. Let _formatOptions_ be a new Record. + 1. If _required_ is one of ~date~, ~year-month~, or ~any~, then + 1. Set _formatOptions_.[[era]] to _options_.[[era]]. + 1. If _required_ is either ~time~ or ~any~, then + 1. Set _formatOptions_.[[hourCycle]] to _options_.[[hourCycle]]. + 1. Let _anyPresent_ be *false*. + 1. For each property name _prop_ of « *"weekday"*, *"year"*, *"month"*, *"day"*, *"dayPeriod"*, *"hour"*, *"minute"*, *"second"*, *"fractionalSecondDigits"* », do + 1. If _options_.[[<_prop_>]] is not *undefined*, set _anyPresent_ to *true*. + 1. Let _needDefaults_ be *true*. + 1. For each property name _prop_ of _requiredOptions_, do + 1. Let _value_ be _options_.[[<_prop_>]]. + 1. If _value_ is not *undefined*, then + 1. Set _formatOptions_.[[<_prop_>]] to _value_. + 1. Set _needDefaults_ to *false*. + 1. If _needDefaults_ is *true*, then + 1. If _anyPresent_ is *true* and _inherit_ is ~relevant~, return *null*. + 1. For each property name _prop_ of _defaultOptions_, do + 1. Set _formatOptions_.[[<_prop_>]] to *"numeric"*. + 1. If _defaults_ is ~zoned-date-time~ and _formatOptions_.[[timeZoneName]] is *undefined*, then + 1. Set _formatOptions_.[[timeZoneName]] to *"short"*. + 1. If _matcher_ is *"basic"*, then + 1. Let _bestFormat_ be BasicFormatMatcher(_formatOptions_, _formats_). + 1. Else, + 1. Let _bestFormat_ be BestFitFormatMatcher(_formatOptions_, _formats_). + 1. Return _bestFormat_. + +
    +

    DateTimeStyleFormat ( @@ -1239,6 +1304,41 @@

    + +

    + AdjustDateTimeStyleFormat ( + _formats_: a List of DateTime Format Records, + _baseFormat_: a DateTime Format Record, + _matcher_: either *"basic"* or *"best fit"*, + _allowedOptions_: a List of property names from the “Property” column of , + ): a DateTime Format Record +

    +
    +
    description
    +
    + It inspects _baseFormat_ and determines the closest format to it that only includes fields from _allowedOptions_. + This is used for determining the best format for Temporal objects with the `"dateStyle"` or `"timeStyle"` options. + For example, a locale's best format for `"dateStyle": "full"` might include the weekday, which is not applicable when formatting a `Temporal.PlainYearMonth` object. +
    +
    + + 1. Let _anyConflictingFields_ be *false*. + 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 current row. + 1. If _baseFormat_ has a [[<_prop_>]] field and _allowedOptions_ does not contain _prop_, set _anyConflictingFields_ to true. + 1. If _anyConflictingFields_ is *false*, return _baseFormat_. + 1. NOTE: The above steps prevent the operation from returning an altered format when _baseFormat_ would be sufficient. This should be unnecessary, but exists because the ECMA-402 specification does not guarantee that a format returned from DateTimeStyleFormat can also be returned from BasicFormatMatcher or BestFitFormatMatcher. + 1. Let _formatOptions_ be a new Record. + 1. For each property name _prop_ of _allowedOptions_, do + 1. If _baseFormat_ has a [[<_prop_>]] field, set _formatOptions_.[[<_prop_>]] to _baseFormat_.[[<_prop_>]]. + 1. If _matcher_ is *"basic"*, then + 1. Let _bestFormat_ be BasicFormatMatcher(_formatOptions_, _formats_). + 1. Else, + 1. Let _bestFormat_ be BestFitFormatMatcher(_formatOptions_, _formats_). + 1. Return _bestFormat_. + +
    +

    BasicFormatMatcher ( @@ -1331,7 +1431,7 @@

    DateTime Format Functions

    1. If _date_ is not provided or is *undefined*, then 1. Let _x_ be ! Call(%Date.now%, *undefined*). 1. Else, - 1. Let _x_ be ? ToNumber(_date_). + 1. Let _x_ be ? ToDateTimeFormattable(_date_). 1. Return ? FormatDateTime(_dtf_, _x_). @@ -1344,12 +1444,13 @@

    _dateTimeFormat_: an Intl.DateTimeFormat, _format_: a DateTime Format Record or a DateTime Range Pattern Format Record, _pattern_: a Pattern String, - _epochNanoseconds_: a BigInt, + _epochNanoseconds_: an epoch nanoseconds value, + _isPlain_: a Boolean, ): a List of Records with fields [[Type]] (a String) and [[Value]] (a String)

    description
    -
    It creates the corresponding parts for the epoch time _epochNanoseconds_ according to _pattern_ and to the effective locale and the formatting options of _dateTimeFormat_ and _format_.
    +
    It creates the corresponding parts for the epoch time _epochNanoseconds_ according to _pattern_ and to the effective locale and the formatting options of _dateTimeFormat_ and _format_, with _isPlain_ signifying whether _epochNanoseconds_ is an epoch-time representation of a wall-clock time.
    1. Let _locale_ be _dateTimeFormat_.[[Locale]]. @@ -1369,7 +1470,8 @@

    1. Perform ! CreateDataPropertyOrThrow(_nf3Options_, *"numberingSystem"*, _dateTimeFormat_.[[NumberingSystem]]). 1. Perform ! CreateDataPropertyOrThrow(_nf3Options_, *"useGrouping"*, *false*). 1. Let _nf3_ be ! Construct(%Intl.NumberFormat%, « _locale_, _nf3Options_ »). - 1. Let _tm_ be ToLocalTime(_epochNanoseconds_, _dateTimeFormat_.[[Calendar]], _dateTimeFormat_.[[TimeZone]]). + 1. If _isPlain_ is *true*, let _timeZone_ be *"+00:00"*; else let _timeZone_ be _dateTimeFormat_.[[TimeZone]]. + 1. Let _tm_ be ToLocalTime(_epochNanoseconds_, _dateTimeFormat_.[[Calendar]], _timeZone_). 1. Let _patternParts_ be PartitionPattern(_pattern_). 1. Let _result_ be a new empty List. 1. For each Record { [[Type]], [[Value]] } _patternPart_ of _patternParts_, do @@ -1447,23 +1549,22 @@

    PartitionDateTimePattern ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, + _x_: either a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing a List of Records with fields [[Type]] (a String) and [[Value]] (a String), or a throw completion

    description
    -
    It interprets _x_ as a time value as specified in ECMA-262, , and creates the corresponding parts according to the effective locale and the formatting options of _dateTimeFormat_.
    +
    It derives an epoch nanoseconds value from _x_ (interpreting _x_ as milliseconds since the epoch if it is a Number), and creates the corresponding parts according to the type of _x_, effective locale, and the formatting options of _dateTimeFormat_.
    - 1. Let _x_ be TimeClip(_x_). - 1. If _x_ is *NaN*, throw a *RangeError* exception. - 1. Let _epochNanoseconds_ be ℤ(ℝ(_x_) × 106). - 1. Let _format_ be _dateTimeFormat_.[[DateTimeFormat]]. - 1. If _dateTimeFormat_.[[HourCycle]] is *"h11"* or *"h12"*, then + 1. Let _formatRecord_ be ? ValueFormatRecord(_dateTimeFormat_, _x_). + 1. Let _epochNanoseconds_ be _formatRecord_.[[EpochNanoseconds]]. + 1. Let _format_ be _formatRecord_.[[Format]]. + 1. If _format_ has a field [[hour]] and _dateTimeFormat_.[[HourCycle]] is *"h11"* or *"h12"*, then 1. Let _pattern_ be _format_.[[pattern12]]. 1. Else, 1. Let _pattern_ be _format_.[[pattern]]. - 1. Let _result_ be FormatDateTimePattern(_dateTimeFormat_, _format_, _pattern_, _epochNanoseconds_). + 1. Let _result_ be FormatDateTimePattern(_dateTimeFormat_, _format_, _pattern_, _epochNanoseconds_, _formatRecord_.[[IsPlain]]). 1. Return _result_.
    @@ -1472,7 +1573,7 @@

    FormatDateTime ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, + _x_: either a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing a String or a throw completion

    @@ -1490,7 +1591,7 @@

    FormatDateTimeToParts ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, + _x_: a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing an Array or a throw completion

    @@ -1513,25 +1614,27 @@

    PartitionDateTimeRangePattern ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, - _y_: a Number, + _x_: either a Number or an Object for which IsTemporalObject returns *true*, + _y_: either a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing a List of Records with fields [[Type]] (a String), [[Value]] (a String), and [[Source]] (a String), or a throw completion

    description
    -
    It interprets _x_ and _y_ as time values as specified in ECMA-262, , and creates the corresponding parts according to the effective locale and the formatting options of _dateTimeFormat_.
    +
    It derives an epoch nanoseconds value from each of _x_ and _y_ (interpreting each Number as milliseconds since the epoch), and creates the corresponding parts according to the types of _x_ and _y_, effective locale, and the formatting options of _dateTimeFormat_.
    - 1. Set _x_ to TimeClip(_x_). - 1. If _x_ is *NaN*, throw a *RangeError* exception. - 1. Set _y_ to TimeClip(_y_). - 1. If _y_ is *NaN*, throw a *RangeError* exception. - 1. Let _xEpochNanoseconds_ be ℤ(ℝ(_x_) × 106). - 1. Let _yEpochNanoseconds_ be ℤ(ℝ(_y_) × 106). + 1. If IsTemporalObject(_x_) is *true* or IsTemporalObject(_y_) is *true*, then + 1. If SameTemporalType(_x_, _y_) is *false*, throw a *TypeError* exception. + 1. Let _xFormatRecord_ be ? ValueFormatRecord(_dateTimeFormat_, _x_). + 1. Let _yFormatRecord_ be ? ValueFormatRecord(_dateTimeFormat_, _y_). + 1. Let _xEpochNanoseconds_ be _xFormatRecord_.[[EpochNanoseconds]]. + 1. Let _yEpochNanoseconds_ be _yFormatRecord_.[[EpochNanoseconds]]. 1. Let _tm1_ be ToLocalTime(_xEpochNanoseconds_, _dateTimeFormat_.[[Calendar]], _dateTimeFormat_.[[TimeZone]]). 1. Let _tm2_ be ToLocalTime(_yEpochNanoseconds_, _dateTimeFormat_.[[Calendar]], _dateTimeFormat_.[[TimeZone]]). - 1. Let _format_ be _dateTimeFormat_.[[DateTimeFormat]]. - 1. If _dateTimeFormat_.[[HourCycle]] is *"h11"* or *"h12"*, then + 1. Let _format_ be _xFormatRecord_.[[Format]]. + 1. Assert: _format_ is equal to _yFormatRecord_.[[Format]]. + 1. Assert: _xFormatRecord_.[[IsPlain]] = _yFormatRecord_.[[IsPlain]]. + 1. If _format_ has a field [[hour]] and _dateTimeFormat_.[[HourCycle]] is *"h11"* or *"h12"*, then 1. Let _pattern_ be _format_.[[pattern12]]. 1. Let _rangePatterns_ be _format_.[[rangePatterns12]]. 1. Else, @@ -1569,7 +1672,7 @@

    1. Set _relevantFieldsEqual_ to *false*. 1. If _relevantFieldsEqual_ is *true*, then 1. Let _collapsedResult_ be a new empty List. - 1. Let _resultParts_ be FormatDateTimePattern(_dateTimeFormat_, _format_, _pattern_, _xEpochNanoseconds_). + 1. Let _resultParts_ be FormatDateTimePattern(_dateTimeFormat_, _format_, _pattern_, _xEpochNanoseconds_, _xFormatRecord_.[[IsPlain]]). 1. For each Record { [[Type]], [[Value]] } _r_ of _resultParts_, do 1. Append the Record { [[Type]]: _r_.[[Type]], [[Value]]: _r_.[[Value]], [[Source]]: *"shared"* } to _collapsedResult_. 1. Return _collapsedResult_. @@ -1583,7 +1686,7 @@

    1. Let _z_ be _xEpochNanoseconds_. 1. Else, 1. Let _z_ be _yEpochNanoseconds_. - 1. Let _resultParts_ be FormatDateTimePattern(_dateTimeFormat_, _selectedRangePattern_, _pattern_, _z_). + 1. Let _resultParts_ be FormatDateTimePattern(_dateTimeFormat_, _selectedRangePattern_, _pattern_, _z_, _xFormatRecord_.[[IsPlain]]). 1. For each Record { [[Type]], [[Value]] } _r_ of _resultParts_, do 1. Append the Record { [[Type]]: _r_.[[Type]], [[Value]]: _r_.[[Value]], [[Source]]: _source_ } to _rangeResult_. 1. Return _rangeResult_. @@ -1594,8 +1697,8 @@

    FormatDateTimeRange ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, - _y_: a Number, + _x_: either a Number or an Object for which IsTemporalObject returns *true*, + _y_: either a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing a String or a throw completion

    @@ -1613,8 +1716,8 @@

    FormatDateTimeRangeToParts ( _dateTimeFormat_: an Intl.DateTimeFormat, - _x_: a Number, - _y_: a Number, + _x_: either a Number or an Object for which IsTemporalObject returns *true*, + _y_: either a Number or an Object for which IsTemporalObject returns *true*, ): either a normal completion containing an Array or a throw completion

    @@ -1634,10 +1737,154 @@

    + +

    + ToDateTimeFormattable ( + _value_: an ECMAScript language value, but not *undefined*, + ): either a normal completion containing either a Number or an Object for which IsTemporalObject returns *true*, or a throw completion +

    +
    +
    description
    +
    It converts _value_ to a value that can be formatted by an %Intl.DateTimeFormat% object.
    +
    + + 1. If IsTemporalObject(_value_) is *true*, return _value_. + 1. Return ? ToNumber(_value_). + +
    + + +

    + IsTemporalObject ( + _value_: an ECMAScript language value, + ): a Boolean +

    +
    +
    + + 1. If _value_ is not an Object, return *false*. + 1. If _value_ does not have an [[InitializedTemporalDate]], [[InitializedTemporalTime]], [[InitializedTemporalDateTime]], [[InitializedTemporalZonedDateTime]], [[InitializedTemporalYearMonth]], [[InitializedTemporalMonthDay]], or [[InitializedTemporalInstant]] internal slot, return *false*. + 1. Return *true*. + +
    + + +

    + SameTemporalType ( + _x_: an ECMAScript language value, + _y_: an ECMAScript language value, + ): a Boolean +

    +
    +
    description
    +
    It determines whether _x_ and _y_ are both instances of the same Temporal type.
    +
    + + 1. If either of IsTemporalObject(_x_) or IsTemporalObject(_y_) is *false*, return *false*. + 1. If _x_ has an [[InitializedTemporalDate]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalTime]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalDateTime]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalZonedDateTime]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalYearMonth]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalMonthDay]] internal slot and _y_ does not, return *false*. + 1. If _x_ has an [[InitializedTemporalInstant]] internal slot and _y_ does not, return *false*. + 1. Return *true*. + +
    + + +

    Value Format Records

    + +

    Each Value Format Record has the fields defined in .

    + + + Value Format Record Fields + + + + + + + + + + + + + + + + + + + +
    Field NameValue Type
    [[Format]]a DateTime Format Record
    [[EpochNanoseconds]]an epoch nanoseconds value
    [[IsPlain]]a Boolean
    +
    +
    + + +

    + ValueFormatRecord ( + _dateTimeFormat_: an Intl.DateTimeFormat, + _x_: either a Number, or an Object for which IsTemporalObject returns *true*, + ): either a normal completion containing a Value Format Record or a throw completion +

    +
    +
    + + 1. Let _dtfCalendar_ be _dateTimeFormat_.[[Calendar]]. + 1. If _x_ is a Number, then + 1. Let _v_ be TimeClip(_x_). + 1. If _v_ is *NaN*, throw a *RangeError* exception. + 1. Let _epochNanoseconds_ be ℝ(_v_) × 106. + 1. Return the Value Format Record { + [[Format]]: _dateTimeFormat_.[[DateTimeFormat]], + [[EpochNanoseconds]]: _epochNanoseconds_, + [[IsPlain]]: *false* + }. + 1. If _x_ has an [[InitializedTemporalInstant]] internal slot, then + 1. Return the Value Format Record { + [[Format]]: _dateTimeFormat_.[[TemporalInstantFormat]], + [[EpochNanoseconds]]: _x_.[[EpochNanoseconds]], + [[IsPlain]]: *false* + }. + 1. If _x_ has an [[InitializedTemporalDateTime]] internal slot, then + 1. If _x_.[[Calendar]] is not either _dtfCalendar_ or *"iso8601"*, throw a *RangeError* exception. + 1. Let _format_ be _dateTimeFormat_.[[TemporalPlainDateTimeFormat]]. + 1. Let _isoDateTime_ be _x_.[[ISODateTime]]. + 1. Else if _x_ has an [[InitializedTemporalDate]] internal slot, then + 1. If _x_.[[Calendar]] is not either _dtfCalendar_ or *"iso8601"*, throw a *RangeError* exception. + 1. Let _format_ be _dateTimeFormat_.[[TemporalPlainDateFormat]]. + 1. Let _isoDateTime_ be CombineISODateAndTimeRecord(_x_.[[ISODate]], NoonTimeRecord()). + 1. Else if _x_ has an [[InitializedTemporalYearMonth]] internal slot, then + 1. If _x_.[[Calendar]] is not equal to _dtfCalendar_, throw a *RangeError* exception. + 1. Let _format_ be _dateTimeFormat_.[[TemporalPlainYearMonthFormat]]. + 1. Let _isoDateTime_ be CombineISODateAndTimeRecord(_x_.[[ISODate]], NoonTimeRecord()). + 1. Else if _x_ has an [[InitializedTemporalMonthDay]] internal slot, then + 1. If _x_.[[Calendar]] is not equal to _dtfCalendar_, throw a *RangeError* exception. + 1. Let _format_ be _dateTimeFormat_.[[TemporalPlainMonthDayFormat]]. + 1. Let _isoDateTime_ be CombineISODateAndTimeRecord(_x_.[[ISODate]], NoonTimeRecord()). + 1. Else if _x_ has an [[InitializedTemporalTime]] internal slot, then + 1. Let _format_ be _dateTimeFormat_.[[TemporalPlainTimeFormat]]. + 1. Let _isoDate_ be CreateISODateRecord(1970, 1, 1). + 1. Let _isoDateTime_ be CombineISODateAndTimeRecord(_isoDate_, _x_.[[Time]]). + 1. Else, + 1. Assert: _x_ has an [[InitializedTemporalZonedDateTime]] internal slot. + 1. Throw a *TypeError* exception. + 1. If _format_ is *null*, throw a *TypeError* exception. + 1. Let _epochNs_ be GetUTCEpochNanoseconds(_isoDateTime_). + 1. Return the Value Format Record { + [[Format]]: _format_, + [[EpochNanoseconds]]: _epochNs_, + [[IsPlain]]: *true* + }. + +
    +

    ToLocalTime ( - _epochNs_: a BigInt, + _epochNs_: an epoch nanoseconds value, _calendar_: a String, _timeZoneIdentifier_: a String, ): a ToLocalTime Record @@ -1649,17 +1896,23 @@

    - 1. If IsTimeZoneOffsetString(_timeZoneIdentifier_) is *true*, then - 1. Let _offsetNs_ be ParseTimeZoneOffsetString(_timeZoneIdentifier_). + 1. If IsOffsetTimeZoneIdentifier(_timeZoneIdentifier_) is *true*, then + 1. Let _offsetNs_ be ! ParseDateTimeUTCOffset(_timeZoneIdentifier_). 1. Else, 1. Assert: GetAvailableNamedTimeZoneIdentifier(_timeZoneIdentifier_) is not ~empty~. 1. Let _offsetNs_ be GetNamedTimeZoneOffsetNanoseconds(_timeZoneIdentifier_, _epochNs_). - 1. Let _tz_ be ℝ(_epochNs_) + _offsetNs_. + 1. Let _tz_ be _epochNs_ + _offsetNs_. 1. If _calendar_ is *"gregory"*, then 1. Return a ToLocalTime Record with fields calculated from _tz_ according to . 1. Else, - 1. Return a ToLocalTime Record with the fields calculated from _tz_ for the given _calendar_. The calculations should use best available information about the specified _calendar_. + 1. Return a ToLocalTime Record with the fields calculated from _tz_ for the given _calendar_. The calculations should use best available information about the specified _calendar_. Given the same values of _epochNs_, _calendar_, and _timeZoneIdentifier_, the result must be the same for the lifetime of the surrounding agent. + + + Time zone information is subject to change, and host environments may update their time zone database at any time. + At a minimum, implementations must ensure that the time zone information for each particular value of _timeZone_ individually remains constant starting from the time it is first accessed, for the lifetime of the surrounding agent. + Furthermore, it is recommended that the time zone information for all values of _timeZone_ as a whole (i.e. the time zone database) remains the same for the lifetime of the surrounding agent. + diff --git a/spec/durationformat.html b/spec/durationformat.html index 0edb055f..f68dc0e5 100644 --- a/spec/durationformat.html +++ b/spec/durationformat.html @@ -308,15 +308,15 @@

    Intl.DurationFormat.prototype.resolvedOptions ( )

    -

    Intl.DurationFormat.prototype.format ( _duration_ )

    +

    Intl.DurationFormat.prototype.format ( _durationLike_ )

    -

    When the `format` method is called with an argument _duration_, the following steps are taken:

    +

    When the `format` method is called with an argument _durationLike_, the following steps are taken:

    1. Let _df_ be the *this* value. 1. Perform ? RequireInternalSlot(_df_, [[InitializedDurationFormat]]). - 1. Let _record_ be ? ToDurationRecord(_duration_). - 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _record_). + 1. Let _duration_ be ? ToTemporalDuration(_durationLike_). + 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _duration_). 1. Let _result_ be the empty String. 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do 1. Set _result_ to the string-concatenation of _result_ and _part_.[[Value]]. @@ -325,15 +325,15 @@

    Intl.DurationFormat.prototype.format ( _duration_ )

    -

    Intl.DurationFormat.prototype.formatToParts ( _duration_ )

    +

    Intl.DurationFormat.prototype.formatToParts ( _durationLike_ )

    -

    When the `formatToParts` method is called with an argument _duration_, the following steps are taken:

    +

    When the `formatToParts` method is called with an argument _durationLike_, the following steps are taken:

    1. Let _df_ be the *this* value. 1. Perform ? RequireInternalSlot(_df_, [[InitializedDurationFormat]]). - 1. Let _record_ be ? ToDurationRecord(_duration_). - 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _record_). + 1. Let _duration_ be ? ToTemporalDuration(_durationLike_). + 1. Let _parts_ be PartitionDurationFormatPattern(_df_, _duration_). 1. Let _result_ be ! ArrayCreate(0). 1. Let _n_ be 0. 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do @@ -385,197 +385,6 @@

    Properties of Intl.DurationFormat Instances

    Abstract Operations for DurationFormat Objects

    - -

    Duration Records

    -

    A Duration Record is a Record value used to represent a Duration.

    -

    Duration Records have the fields listed in

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FieldMeaning
    [[Years]] - The number of years in the duration. -
    [[Months]] - The number of months in the duration. -
    [[Weeks]] - The number of weeks in the duration. -
    [[Days]] - The number of days in the duration. -
    [[Hours]] - The number of hours in the duration. -
    [[Minutes]] - The number of minutes in the duration. -
    [[Seconds]] - The number of seconds in the duration. -
    [[Milliseconds]] - The number of milliseconds in the duration. -
    [[Microseconds]] - The number of microseconds in the duration. -
    [[Nanoseconds]] - The number of nanoseconds in the duration. -
    -
    -
    - - -

    - ToIntegerIfIntegral ( - _argument_: an ECMAScript language value, - ): either a normal completion containing an integer, or a throw completion -

    -
    -
    description
    -
    It converts _argument_ to an integer representing its Number value, or throws a *RangeError* when that value is not integral.
    -
    - - 1. Let _number_ be ? ToNumber(_argument_). - 1. If _number_ is not an integral Number, throw a *RangeError* exception. - 1. Return ℝ(_number_). - -
    - - -

    - ToDurationRecord ( - _input_: an ECMAScript language value, - ): either a normal completion containing a Duration Record, or a throw completion -

    -
    -
    description
    -
    It converts a given object that represents a Duration into a Duration Record.
    -
    - - - 1. If _input_ is not an Object, then - 1. If _input_ is a String, throw a *RangeError* exception. - 1. Throw a *TypeError* exception. - 1. Let _result_ be a new Duration Record with each field set to 0. - 1. Let _days_ be ? Get(_input_, *"days"*). - 1. If _days_ is not *undefined*, set _result_.[[Days]] to ? ToIntegerIfIntegral(_days_). - 1. Let _hours_ be ? Get(_input_, *"hours"*). - 1. If _hours_ is not *undefined*, set _result_.[[Hours]] to ? ToIntegerIfIntegral(_hours_). - 1. Let _microseconds_ be ? Get(_input_, *"microseconds"*). - 1. If _microseconds_ is not *undefined*, set _result_.[[Microseconds]] to ? ToIntegerIfIntegral(_microseconds_). - 1. Let _milliseconds_ be ? Get(_input_, *"milliseconds"*). - 1. If _milliseconds_ is not *undefined*, set _result_.[[Milliseconds]] to ? ToIntegerIfIntegral(_milliseconds_). - 1. Let _minutes_ be ? Get(_input_, *"minutes"*). - 1. If _minutes_ is not *undefined*, set _result_.[[Minutes]] to ? ToIntegerIfIntegral(_minutes_). - 1. Let _months_ be ? Get(_input_, *"months"*). - 1. If _months_ is not *undefined*, set _result_.[[Months]] to ? ToIntegerIfIntegral(_months_). - 1. Let _nanoseconds_ be ? Get(_input_, *"nanoseconds"*). - 1. If _nanoseconds_ is not *undefined*, set _result_.[[Nanoseconds]] to ? ToIntegerIfIntegral(_nanoseconds_). - 1. Let _seconds_ be ? Get(_input_, *"seconds"*). - 1. If _seconds_ is not *undefined*, set _result_.[[Seconds]] to ? ToIntegerIfIntegral(_seconds_). - 1. Let _weeks_ be ? Get(_input_, *"weeks"*). - 1. If _weeks_ is not *undefined*, set _result_.[[Weeks]] to ? ToIntegerIfIntegral(_weeks_). - 1. Let _years_ be ? Get(_input_, *"years"*). - 1. If _years_ is not *undefined*, set _result_.[[Years]] to ? ToIntegerIfIntegral(_years_). - 1. If _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, and _nanoseconds_ are all *undefined*, throw a *TypeError* exception. - 1. If IsValidDuration( _result_.[[Years]], _result_.[[Months]], _result_.[[Weeks]], _result_.[[Days]], _result_.[[Hours]], _result_.[[Minutes]], _result_.[[Seconds]], _result_.[[Milliseconds]], _result_.[[Microseconds]], _result_.[[Nanoseconds]]) is *false*, then - 1. Throw a *RangeError* exception. - 1. Return _result_. - -
    - - -

    - DurationSign ( - _duration_: a Duration Record, - ): -1, 0, or 1 -

    -
    -
    description
    -
    It returns 1 if the most significant non-zero field in the _duration_ argument is positive, and -1 if the most significant non-zero field is negative. If all of _duration_'s fields are zero, it returns 0.
    -
    - - 1. For each value _v_ of « _duration_.[[Years]], _duration_.[[Months]], _duration_.[[Weeks]], _duration_.[[Days]], _duration_.[[Hours]], _duration_.[[Minutes]], _duration_.[[Seconds]], _duration_.[[Milliseconds]], _duration_.[[Microseconds]], _duration_.[[Nanoseconds]] », do - 1. If _v_ < 0, return -1. - 1. If _v_ > 0, return 1. - 1. Return 0. - -
    - - -

    - IsValidDuration ( - _years_: an integer, - _months_: an integer, - _weeks_: an integer, - _days_: an integer, - _hours_: an integer, - _minutes_: an integer, - _seconds_: an integer, - _milliseconds_: an integer, - _microseconds_: an integer, - _nanoseconds_: an integer, - ): a Boolean -

    -
    -
    description
    -
    It returns *true* if its arguments form valid input from which to construct a Duration Record, and *false* otherwise.
    -
    - - 1. Let _sign_ be 0. - 1. For each value _v_ of « _years_, _months_, _weeks_, _days_, _hours_, _minutes_, _seconds_, _milliseconds_, _microseconds_, _nanoseconds_ », do - 1. If 𝔽(_v_) is not finite, return *false*. - 1. If _v_ < 0, then - 1. If _sign_ > 0, return *false*. - 1. Set _sign_ to -1. - 1. Else if _v_ > 0, then - 1. If _sign_ < 0, return *false*. - 1. Set _sign_ to 1. - 1. If abs(_years_) ≥ 232, return *false*. - 1. If abs(_months_) ≥ 232, return *false*. - 1. If abs(_weeks_) ≥ 232, return *false*. - 1. Let _normalizedSeconds_ be _days_ × 86,400 + _hours_ × 3600 + _minutes_ × 60 + _seconds_ + ℝ(𝔽(_milliseconds_)) × 10-3 + ℝ(𝔽(_microseconds_)) × 10-6 + ℝ(𝔽(_nanoseconds_)) × 10-9. - 1. NOTE: The above step cannot be implemented directly using floating-point arithmetic. Multiplying by 10-3, 10-6, and 10-9 respectively may be imprecise when _milliseconds_, _microseconds_, or _nanoseconds_ is an unsafe integer. This multiplication can be implemented in C++ with an implementation of `std::remquo()` with sufficient bits in the quotient. String manipulation will also give an exact result, since the multiplication is by a power of 10. - 1. If abs(_normalizedSeconds_) ≥ 253, return *false*. - 1. Return *true*. - -
    -

    GetDurationUnitOptions ( @@ -667,7 +476,7 @@

    ComputeFractionalDigits ( _durationFormat_: a DurationFormat Object, - _duration_: a Duration Record, + _duration_: a Temporal.Duration, ): a mathematical value

    @@ -679,11 +488,11 @@

    1. Let _result_ be 0. 1. Let _exponent_ be 3. 1. For each row of , except the header row, in table order, do - 1. Let _unitOptions_ be the value of _durationFormat_'s internal slot whose name is the Internal Slot value of the current row. + 1. Let _unitOptions_ be the value of _durationFormat_'s internal slot whose name is the “Formatter Internal Slot” value of the current row. 1. If _unitOptions_.[[Style]] is *"fractional"*, then 1. Let _unit_ be the Unit value of the current row. 1. Assert: IsFractionalSecondUnitName(_unit_) is *true*. - 1. Let _value_ be the value of _duration_'s field whose name is the Value Field value of the current row. + 1. Let _value_ be the value of _duration_'s internal slot whose name is the “Duration Internal Slot” value of the current row. 1. Set _result_ to _result_ + (_value_ / 10_exponent_). 1. Set _exponent_ to _exponent_ + 3. 1. Return _result_. @@ -829,7 +638,7 @@

    FormatNumericUnits ( _durationFormat_: a DurationFormat Object, - _duration_: a Duration Record, + _duration_: a Temporal.Duration, _firstNumericUnit_: a String, _signDisplayed_: a Boolean, ): a List of Records @@ -946,7 +755,7 @@

    PartitionDurationFormatPattern ( _durationFormat_: a DurationFormat, - _duration_: a Duration Record, + _duration_: a Temporal.Duration, ): a List

    @@ -959,8 +768,8 @@

    1. Let _signDisplayed_ be *true*. 1. Let _numericUnitFound_ be *false*. 1. While _numericUnitFound_ is *false*, repeat for each row in in table order, except the header row: - 1. Let _value_ be the value of _duration_'s field whose name is the Value Field value of the current row. - 1. Let _unitOptions_ be the value of _durationFormat_'s internal slot whose name is the Internal Slot value of the current row. + 1. Let _value_ be the value of _duration_'s internal slot whose name is the “Duration Internal Slot” value of the current row. + 1. Let _unitOptions_ be the value of _durationFormat_'s internal slot whose name is the “Formatter Internal Slot” value of the current row. 1. Let _style_ be _unitOptions_.[[Style]]. 1. Let _display_ be _unitOptions_.[[Display]]. 1. Let _unit_ be the Unit value of the current row. @@ -1006,8 +815,8 @@

    - - + + diff --git a/spec/locale-sensitive-functions.html b/spec/locale-sensitive-functions.html index e929b0e4..3fb10e9e 100644 --- a/spec/locale-sensitive-functions.html +++ b/spec/locale-sensitive-functions.html @@ -247,4 +247,1601 @@

    Array.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    + + +

    Properties of the Temporal.Duration Prototype Object

    + + +

    Temporal.Duration.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _duration_ be the *this* value. + 1. Perform ? RequireInternalSlot(_duration_, [[InitializedTemporalDuration]]). + 1. Let _formatter_ be ? Construct(%Intl.DurationFormat%, « _locales_, _options_ »). + 1. Let _parts_ be PartitionDurationFormatPattern(_formatter_, _duration_). + 1. Let _result_ be the empty String. + 1. For each Record { [[Type]], [[Value]], [[Unit]] } _part_ in _parts_, do + 1. Set _result_ to the string-concatenation of _result_ and _part_.[[Value]]. + 1. Return _result_. + +
    +
    + + +

    Properties of the Temporal.Instant Prototype Object

    + + +

    Temporal.Instant.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _instant_ be the *this* value. + 1. Perform ? RequireInternalSlot(_instant_, [[InitializedTemporalInstant]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~any~, ~all~). + 1. Return ? FormatDateTime(_dateFormat_, _instant_). + +
    +
    + + +

    Properties of the Temporal.PlainDate Prototype Object

    + + +

    Temporal.PlainDate.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _plainDate_ be the *this* value. + 1. Perform ? RequireInternalSlot(_plainDate_, [[InitializedTemporalDate]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~date~, ~date~). + 1. Return ? FormatDateTime(_dateFormat_, _plainDate_). + +
    +
    + + +

    Properties of the Temporal.PlainDateTime Prototype Object

    + + +

    Temporal.PlainDateTime.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _plainDateTime_ be the *this* value. + 1. Perform ? RequireInternalSlot(_plainDateTime_, [[InitializedTemporalDateTime]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~any~, ~all~). + 1. Return ? FormatDateTime(_dateFormat_, _plainDateTime_). + +
    +
    + + +

    Properties of the Temporal.PlainMonthDay Prototype Object

    + + +

    Temporal.PlainMonthDay.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _plainMonthDay_ be the *this* value. + 1. Perform ? RequireInternalSlot(_plainMonthDay_, [[InitializedTemporalMonthDay]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~date~, ~date~). + 1. Return ? FormatDateTime(_dateFormat_, _plainMonthDay_). + +
    +
    + + +

    Properties of the Temporal.PlainTime Prototype Object

    + + +

    Temporal.PlainTime.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _plainTime_ be the *this* value. + 1. Perform ? RequireInternalSlot(_plainTime_, [[InitializedTemporalTime]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~time~, ~time~). + 1. Return ? FormatDateTime(_dateFormat_, _plainTime_). + +
    +
    + + +

    Properties of the Temporal.PlainYearMonth Prototype Object

    + + +

    Temporal.PlainYearMonth.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _plainYearMonth_ be the *this* value. + 1. Perform ? RequireInternalSlot(_plainYearMonth_, [[InitializedTemporalYearMonth]]). + 1. Let _dateFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~date~, ~date~). + 1. Return ? FormatDateTime(_dateFormat_, _plainYearMonth_). + +
    +
    + + +

    Properties of the Temporal.ZonedDateTime Prototype Object

    + + +

    Temporal.ZonedDateTime.prototype.toLocaleString ( [ _locales_ [ , _options_ ] ] )

    +

    This definition supersedes the definition provided in .

    +

    This method performs the following steps when called:

    + + 1. Let _zonedDateTime_ be the *this* value. + 1. Perform ? RequireInternalSlot(_zonedDateTime_, [[InitializedTemporalZonedDateTime]]). + 1. Let _dateTimeFormat_ be ? CreateDateTimeFormat(%Intl.DateTimeFormat%, _locales_, _options_, ~any~, ~all~, _zonedDateTime_.[[TimeZone]]). + 1. If _zonedDateTime_.[[Calendar]] is not *"iso8601"* and CalendarEquals(_zonedDateTime_.[[Calendar]], _dateTimeFormat_.[[Calendar]]) is *false*, throw a *RangeError* exception. + 1. Let _instant_ be ! CreateTemporalInstant(_zonedDateTime_.[[EpochNanoseconds]]). + 1. Return ? FormatDateTime(_dateTimeFormat_, _instant_). + +
    +
    + + +

    Abstract Operations for Calendar Calculations

    + + +

    + CalendarSupportsEra ( + _calendar_: a calendar type, + ): a Boolean +

    +
    +
    description
    +
    + The following algorithm refers (via ) to the era data from Unicode Technical Standard #35 Part 4 Dates, Calendar Data. +
    +
    + + 1. If _calendar_ is listed in the “Calendar” column of , return *true*. + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Return *false*. + +

    + lists all currently known eras for the current set of calendars, including their aliases, ranges, and kinds. + The canonical source for this table is the data described in Unicode Technical Standard #35 Part 4 Dates, Calendar Data. +

    +

    + The era kind is used by CalendarDateArithmeticYearForEraYear to calculate the arithmetic year ([[Year]]): + An *Era Kind* ~epoch~ means that the era is the epoch era, so 1 Era has an arithmetic year of 1. An *Era Kind* ~negative~ means + that the era is a "negative" era growing + from the epoch, so 1 Era is an arithmetic year of 0, and larger [[EraYear]] values produce smaller, negative arithmetic years. An *Era Kind* of + ~offset~ means that the era is "offset" by a given number (in the *Offset* column), so 1 Era has an arithmetic year of *Offset*. +

    + + Eras +
    Value FieldInternal SlotDuration Internal SlotFormatter Internal Slot Unit NumberFormat Unit
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CalendarEraAliasesMinimum eraYearMaximum eraYearEra KindOffset
    *"buddhist"**"be"*-∞+∞~epoch~
    *"coptic"**"am"*-∞+∞~epoch~
    *"ethioaa"**"aa"*-∞+∞~epoch~
    *"ethiopic"**"am"*1+∞~epoch~
    *"ethiopic"**"aa"*-∞5500 ~offset~-5499
    *"gregory"**"ce"**"ad"*1+∞~epoch~
    *"gregory"**"bce"**"bc"*1+∞~negative~
    *"hebrew"**"am"*-∞+∞~epoch~
    *"indian"**"shaka"*-∞+∞~epoch~
    *"islamic-civil"**"ah"*1+∞~epoch~
    *"islamic-civil"**"bh"*1+∞~negative~
    *"islamic-tbla"**"ah"*1+∞~epoch~
    *"islamic-tbla"**"bh"*1+∞~negative~
    *"islamic-umalqura"**"ah"*1+∞~epoch~
    *"islamic-umalqura"**"bh"*1+∞~negative~
    *"japanese"**"reiwa"*1+∞~offset~2019
    *"japanese"**"heisei"*131~offset~1989
    *"japanese"**"showa"*164~offset~1926
    *"japanese"**"taisho"*115~offset~1912
    *"japanese"**"meiji"*645~offset~1868
    *"japanese"**"ce"**"ad"*11872~epoch~
    *"japanese"**"bce"**"bc"*1+∞~negative~
    *"persian"**"ap"*-∞+∞~epoch~
    *"roc"**"roc"*1+∞~epoch~
    *"roc"**"broc"*1+∞~negative~
    + + + + +

    + CanonicalizeEraInCalendar ( + _calendar_: a calendar type that is not *"iso8601"*, + _era_: a String, + ): a String or *undefined* +

    +
    +
    description
    +
    + The following algorithm refers to the era data from Unicode Technical Standard #35 Part 4 Dates, Calendar Data. +
    +
    + + 1. For each row of , except the header row, do + 1. Let _cal_ be the “Calendar” value of the current row. + 1. If _cal_ is equal to _calendar_, then + 1. Let _canonicalName_ be the “Era” value of the current row. + 1. If _canonicalName_ is equal to _era_, return _canonicalName_. + 1. Let _aliases_ be a List whose elements are the strings given in the “Aliases” column of the row. + 1. If _aliases_ contains _era_, return _canonicalName_. + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Return *undefined*. + +
    + + +

    + CalendarHasMidYearEras ( + _calendar_: a calendar type that is not *"iso8601"*, + ): a Boolean +

    +
    +
    description
    +
    It returns *true* if the calendar has eras that start in the middle of the year, or *false* if all eras start on a year boundary.
    +
    + + 1. If _calendar_ is *"japanese"*, return *true*. + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Return *false*. + +
    + + +

    + IsValidMonthCodeForCalendar ( + _calendar_: a calendar type that is not *"iso8601"*, + _monthCode_: a month code, + ): a Boolean +

    +
    +
    + + 1. Let _commonMonthCodes_ be « *"M01"*, *"M02"*, *"M03"*, *"M04"*, *"M05"*, *"M06"*, *"M07"*, *"M08"*, *"M09"*, *"M10"*, *"M11"*, *"M12"* ». + 1. If _commonMonthCodes_ contains _monthCode_, return *true*. + 1. If _calendar_ is listed in the “Calendar” column of , then + 1. Let _r_ be the row in with a value in the “Calendar” column matching _calendar_. + 1. Let _specialMonthCodes_ be a List whose elements are the strings given in the “Additional Month Codes” column of _r_. + 1. If _specialMonthCodes_ contains _monthCode_, return *true*. + 1. Return *false*. + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Return *false*. + + + + Additional Month Codes in Calendars + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CalendarAdditional Month CodesLeap to Common Month Transformation
    *"chinese"**"M01L"*, *"M02L"*, *"M03L"*, *"M04L"*, *"M05L"*, *"M06L"*, *"M07L"*, *"M08L"*, *"M09L"*, *"M10L"*, *"M11L"*, *"M12L"*~skip-backward~
    *"coptic"**"M13"*
    *"dangi"**"M01L"*, *"M02L"*, *"M03L"*, *"M04L"*, *"M05L"*, *"M06L"*, *"M07L"*, *"M08L"*, *"M09L"*, *"M10L"*, *"M11L"*, *"M12L"*~skip-backward~
    *"ethioaa"**"M13"*
    *"ethiopic"**"M13"*
    *"hebrew"**"M05L"*~skip-forward~
    +
    +
    + + +

    + YearContainsMonthCode ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _monthCode_: a month code, + ): a Boolean +

    +
    +
    description
    +
    + It returns whether the given _monthCode_ exists in _arithmeticYear_ of _calendar_. +
    +
    +

    It performs the following steps when called:

    + + 1. Assert: IsValidMonthCodeForCalendar(_calendar_, _monthCode_) is *true*. + 1. If ! ParseMonthCode(_monthCode_).[[IsLeap]] is *false*, return *true*. + 1. Return whether the leap month indicated by _monthCode_ exists in the year _arithmeticYear_ in _calendar_, using calendar-dependent behaviour. + +
    + + +

    + ConstrainMonthCode ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _monthCode_: a month code, + _overflow_: ~constrain~ or ~reject~, + ): either a normal completion containing a month code or a throw completion +

    +
    +
    description
    +
    + It returns the month code in _arithmeticYear_ of _calendar_ that best matches the given _monthCode_. If _monthCode_ does not exist in _arithmeticYear_, it is constrained to the best common month if _overflow_ is ~constrain~, or an error is thrown if _overflow_ is ~reject~. +
    +
    +

    It performs the following steps when called:

    + + 1. Assert: IsValidMonthCodeForCalendar(_calendar_, _monthCode_) is *true*. + 1. If YearContainsMonthCode(_calendar_, _arithmeticYear_, _monthCode_) is *true*, return _monthCode_. + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Assert: _calendar_ is listed in the “Calendar” column of . + 1. Let _r_ be the row in with a value in the “Calendar” column matching _calendar_. + 1. Let _shiftType_ be the value given in the “Leap to Common Month Transformation” column of _r_. + 1. If _shiftType_ is ~skip-backward~, then + 1. Return CreateMonthCode(! ParseMonthCode(_monthCode_).[[MonthNumber]], *false*). + 1. Else, + 1. Assert: _calendar_ is *"hebrew"* and _monthCode_ is *"M05L"*. + 1. Return *"M06"*. + +
    + + +

    + MonthCodeToOrdinal ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _monthCode_: a month code, + ): an integer +

    +
    +
    description
    +
    + It returns the ordinal month number for _monthCode_ in _arithmeticYear_ of _calendar_. The given _monthCode_ must exist in the given year. +
    +
    +

    It performs the following steps when called:

    + + 1. Assert: YearContainsMonthCode(_calendar_, _arithmeticYear_, _monthCode_) is *true*. + 1. Let _monthsBefore_ be 0. + 1. Let _number_ be 1. + 1. Let _isLeap_ be *false*. + 1. Let _r_ be the row in which the _calendar_ is in the “Calendar” column. + 1. If the “Leap to Common Month Transformation” column of _r_ is empty, then + 1. Return ! ParseMonthCode(_monthCode_).[[MonthNumber]]. + 1. Assert: The “Additional Month Codes” column of _r_ does not contain *"M00L"* or *"M13"*. + 1. Assert: This algorithm will return before the following loop terminates by failing its condition. + 1. Repeat, while _number_ ≤ 12, + 1. Let _currentMonthCode_ be CreateMonthCode(_number_, _isLeap_). + 1. If IsValidMonthCodeForCalendar(_calendar_, _currentMonthCode_) is *true* and YearContainsMonthCode(_calendar_, _arithmeticYear_, _currentMonthCode_) is *true*, then + 1. Set _monthsBefore_ to _monthsBefore_ + 1. + 1. If _currentMonthCode_ is _monthCode_, then + 1. Return _monthsBefore_. + 1. If _isLeap_ is *false*, then + 1. Set _isLeap_ to *true*. + 1. Else, + 1. Set _isLeap_ to *false*. + 1. Set _number_ to _number_ + 1. + +
    + + +

    + CalendarDaysInMonth ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _ordinalMonth_: a positive integer, + ): a positive integer +

    +
    +
    description
    +
    + The returned value represents the number of days in the _calendar_-specific _arithmeticYear_ and _ordinalMonth_. +
    +
    +

    It performs the following steps when called:

    + + 1. Let _isoDate_ be ! CalendarIntegersToISO(_calendar_, _arithmeticYear_, _ordinalMonth_, 1). + 1. Return CalendarISOToDate(_calendar_, _isoDate_).[[DaysInMonth]]. + +
    + + +

    + CalendarDateEra ( + _calendar_: a calendar type that is not *"iso8601"*, + _date_: an ISO Date Record, + ): a String or *undefined* +

    +
    +
    description
    +
    It performs implementation-defined processing to find the era for the date corresponding to _date_ in the context of the calendar represented by _calendar_ and returns a lowercase String value representing that era, or *undefined* for calendars that do not have eras.
    +
    + + 1. If CalendarSupportsEra(_calendar_) is *false*, return *undefined*. + 1. Let _era_ be an implementation-defined String indicating the era corresponding to _date_ in the context of the calendar represented by _calendar_. + 1. Return CanonicalizeEraInCalendar(_calendar_, _era_). + +
    + + +

    + CalendarDateEraYear ( + _calendar_: a calendar type that is not *"iso8601"*, + _date_: an ISO Date Record, + ): an integer or *undefined* +

    +
    +
    description
    +
    It performs implementation-defined processing to find the era for the date corresponding to _date_ in the context of the calendar represented by _calendar_ and returns an integer representing the ordinal position of the year of _date_ in that era, or *undefined* for calendars that do not have eras.
    +
    +

    + + 1. If CalendarSupportsEra(_calendar_) is *false*, return *undefined*. + 1. Return an implementation-defined integer indicating the era year corresponding to _date_ in the context of the calendar represented by _calendar_. + + + + +

    + CalendarDateArithmeticYear ( + _calendar_: a calendar type that is not *"iso8601"*, + _date_: an ISO Date Record, + ): an integer +

    +
    +
    description
    +
    It performs implementation-defined processing to find the arithmetic year for the date corresponding to _date_ in the context of the calendar represented by _calendar_.
    +
    + + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Let _r_ be the row in with a value in the “Calendar” column matching _calendar_. + 1. Let _epochYear_ be the value given in the “Epoch ISO Year” column of _r_. + 1. Let _epochDate_ be the first day of the calendar year starting in ISO year _epochYear_ in the calendar represented by _calendar_, according to implementation-defined processing. + 1. Let _newYear_ be the first day of the calendar year of _date_ in the calendar represented by _calendar_, according to implementation-defined processing. + 1. Let _arithmeticYear_ be the implementation-defined signed number of whole years between _epochDate_ and _newYear_ in the calendar represented by _calendar_. + 1. Return _arithmeticYear_. + + + + Epoch years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    CalendarEpoch ISO Year
    *"buddhist"*-543
    *"chinese"*0
    *"coptic"*283
    *"dangi"*0
    *"ethioaa"*-5493
    *"ethiopic"*7
    *"gregory"*0
    *"hebrew"*-3761
    *"indian"*78
    *"islamic-civil"*621
    *"islamic-tbla"*621
    *"islamic-umalqura"*621
    *"japanese"*0
    *"persian"*621
    *"roc"*1911
    +
    +
    + + +

    + CalendarDateArithmeticYearForEraYear ( + _calendar_: a calendar type that has eras, + _era_: a String, + _eraYear_: an integer, + ): an integer +

    +
    +
    description
    +
    It produces the arithmetic year for a given set of _era_, _eraYear_ in _calendar_, a calendar that includes an era named _era_.
    +
    + + 1. Let _era_ be CanonicalizeEraInCalendar(_calendar_, _era_). + 1. Assert: _era_ is not *undefined*. + 1. Assert: _calendar_ is listed in the “Calendar Type” column of . + 1. Let _r_ be the row in with a value in the “Calendar” column matching _calendar_ and a value in the “Era” column matching _era_. + 1. Let _eraKind_ be the value given in the “Era Kind” column of _r_. + 1. Let _offset_ be the value given in the “Offset” column of _r_. + 1. If _eraKind_ is ~epoch~, return _eraYear_. + 1. If _eraKind_ is ~negative~, return 1 - _eraYear_. + 1. Assert: _eraKind_ is ~offset~. + 1. Assert: _offset_ is an integer. + 1. Return _offset_ + _eraYear_ - 1. + +
    + + +

    + CalendarIntegersToISO ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _ordinalMonth_: a positive integer, + _day_: a positive integer, + ): either a normal completion containing an ISO Date Record or a throw completion +

    +
    +
    description
    +
    + It returns an ISO Date Record that corresponds with the given _calendar_-specific _arithmeticYear_, _ordinalMonth_, and _day_. +
    +
    +

    It performs the following steps when called:

    + + 1. If _arithmeticYear_, _ordinalMonth_, and _day_ do not form a valid date in _calendar_, throw a *RangeError* exception. + 1. Let _isoDate_ be an ISO Date Record such that CalendarISOToDate(_calendar_, _isoDate_) returns a Calendar Date Record whose [[Year]], [[Month]], and [[Day]] field values respectively equal _arithmeticYear_, _ordinalMonth_, and _day_. + 1. NOTE: No known calendars have repeated dates that would cause _isoDate_ to be ambiguous between two ISO Date Records. + 1. Return _isoDate_. + +
    + + +

    Calendar Date Records

    +

    + A Calendar Date Record is a Record value used to represent a valid calendar date in a non-ISO 8601 calendar. + Calendar Date Records are produced by the abstract operation CalendarISOToDate. +

    +

    Calendar Date Records have the fields listed in .

    +

    This definition supersedes the one in .

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameValueMeaning
    [[Era]]a String or *undefined* + A lowercase String value representing the date's era, or *undefined* for calendars that do not have eras.
    + The value of this field for a calendar type _calendar_ should be the result of calling CalendarDateEra(_calendar_, _date_), where _date_ is the [[ISODate]] field of a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth value corresponding to the date. +
    [[EraYear]]an integer or *undefined* + The ordinal position of the date's year within its era, or *undefined* for calendars that do not have eras.
    + The value of this field for a calendar type _calendar_ should be the result of calling CalendarDateEraYear(_calendar_, _date_), where _date_ is the [[ISODate]] field of a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth value corresponding to the date. + + Era years are 1-indexed for many calendars, but not all (e.g., the eras of the Burmese calendar, not currently available in CLDR, each start with a year 0). Years can also advance opposite the flow of time (as for BCE years in the Gregorian calendar). + +
    [[Year]]an integer + The date's arithmetic year, which is the year relative to the first day of a calendar-specific epoch year, given in .
    + The value of this field for a calendar type _calendar_ should be the result of calling CalendarDateArithmeticYear(_calendar_, _date_), where _date_ is the [[ISODate]] field of a Temporal.PlainDateTime, Temporal.PlainDate, or Temporal.PlainYearMonth value corresponding to the date. + The arithmetic year is relative to the first day of the calendar's epoch year, so if the epoch era starts in the middle of the year, the year will be the same value before and after the start date of the era. +
    [[Month]]a positive integer + The 1-based ordinal position of the date's month within its year. + + When the number of months in a year of the calendar is variable, a different value can be returned for dates that are part of the same month in different years. For example, in the Hebrew calendar, 1 Nisan 5781 is associated with value 7 while 1 Nisan 5782 is associated with value 8 because 5782 is a leap year and Nisan follows the insertion of Adar I. + +
    [[MonthCode]]a String + The month code of the date's month. The month code for a month that is not a leap month and whose 1-based ordinal position in a common year of the calendar (i.e., a year that is not a leap year) is _n_ should be the string-concatenation of *"M"* and ToZeroPaddedDecimalString(_n_, 2), and the month code for a month that is a leap month inserted after a month whose 1-based ordinal position in a common year of the calendar is _p_ should be the string-concatenation of *"M"*, ToZeroPaddedDecimalString(_p_, 2), and *"L"*. + + For example, in the Hebrew calendar, the month code of Adar (and Adar II, in leap years) is *"M06"* and the month code of Adar I (the leap month inserted before Adar II) is *"M05L"*. Theoretically, in a calendar with a leap month at the start of some years, the month code of that month would be *"M00L"*. + +
    [[Day]]a positive integer + The 1-based ordinal position of the date's day within its month. +
    [[DayOfWeek]]a positive integer + The day of the week corresponding to the date. The value should be 1-based, where 1 is the day corresponding to Monday in the given calendar. +
    [[DayOfYear]]a positive integer + The 1-based ordinal position of the date's day within its year. +
    [[WeekOfYear]]a Year-Week Record +

    The date's calendar week of year, and the corresponding week calendar year.

    +

    The Year-Week Record's [[Week]] field should be 1-based.

    +

    The Year-Week Record's [[Year]] field is an arithmetic year as in the Calendar Date Record's [[Year]] field, not relative to an era as in [[EraYear]].

    +

    + Usually the Year-Week Record's [[Year]] field will contain the same value as the Calendar Date Record's [[Year]] field, but may contain the previous or next year if the week number in the Year-Week Record's [[Week]] field overlaps two different years. + See also ISOWeekOfYear. +

    +

    The Year-Week Record contains *undefined* in [[Week]] and [[Year]] field for calendars that do not have a well-defined week numbering system.

    + + Currently, of the calendars supported in this specification, only *"iso8601"* has a well-defined, locale-independent week numbering system. + For all other calendars, the Year-Week Record fields are *undefined*. + +
    [[DaysInWeek]]a positive integer +

    The number of days in the primary notion of week used by the calendar. For all calendars currently supported by this specification, this number is 7.

    + + Some calendars have alternate cyclic notions that are similar to the 7-day week; many of them have multiple (like the Javanese calendar). This specification does not cover such calendars but can be extended to do so in the future. + +
    [[DaysInMonth]]a positive integerThe number of days in the date's month.
    [[DaysInYear]]a positive integerThe number of days in the date's year.
    [[MonthsInYear]]a positive integerThe number of months in the date's year.
    [[InLeapYear]]a Boolean + *true* if the date falls within a leap year, and *false* otherwise. + + A "leap year" is a year that contains more days than other years (for solar or lunar calendars) or more months than other years (for lunisolar calendars like Hebrew or Chinese). + Some calendars, especially lunisolar ones, have further variation in year length that is not represented in the output of this operation (e.g., the Hebrew calendar includes common years with 353, 354, or 355 days and leap years with 383, 384, or 385 days). + +
    +
    +
    + + +

    + CalendarMonthsInYear ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + ): a positive integer +

    +
    +
    description
    +
    + The returned value represents the number of months in the _calendar_-specific _arithmeticYear_. +
    +
    +

    It performs the following steps when called:

    + + 1. Let _isoDate_ be ! CalendarIntegersToISO(_calendar_, _arithmeticYear_, 1, 1). + 1. Return CalendarISOToDate(_calendar_, _isoDate_).[[MonthsInYear]]. + +
    + + +

    + BalanceNonISODate ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _ordinalMonth_: a positive integer, + _day_: an integer, + ): a Record with fields [[Year]] (an integer), [[Month]] (a positive integer), and [[Day]] (a positive integer) +

    +
    +
    description
    +
    + It interprets the given _arithmeticYear_, potentially out-of-range _ordinalMonth_, and potentially out-of-range _day_ as arithmetical values in the given _calendar_ and returns in-range values by overflowing out-of-range _ordinalMonth_ or _day_ values into the next-highest unit. + This date may correspond to a date in the ISO calendar that is outside the range given by ISODateTimeWithinLimits. +
    +
    +

    It performs the following steps when called:

    + + 1. Let _resolvedYear_ be _arithmeticYear_. + 1. Let _resolvedMonth_ be _ordinalMonth_. + 1. Let _monthsInYear_ be CalendarMonthsInYear(_calendar_, _resolvedYear_). + 1. Repeat, while _resolvedMonth_ ≤ 0, + 1. Set _resolvedYear_ to _resolvedYear_ - 1. + 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + 1. Set _resolvedMonth_ to _resolvedMonth_ + _monthsInYear_. + 1. Repeat, while _resolvedMonth_ > _monthsInYear_, + 1. Set _resolvedMonth_ to _resolvedMonth_ - _monthsInYear_. + 1. Set _resolvedYear_ to _resolvedYear_ + 1. + 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + 1. Let _resolvedDay_ be _day_. + 1. Let _daysInMonth_ be CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + 1. Repeat, while _resolvedDay_ ≤ 0, + 1. Set _resolvedMonth_ to _resolvedMonth_ - 1. + 1. If _resolvedMonth_ is 0, then + 1. Set _resolvedYear_ to _resolvedYear_ - 1. + 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + 1. Set _resolvedMonth_ to _monthsInYear_. + 1. Set _daysInMonth_ to CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + 1. Set _resolvedDay_ to _resolvedDay_ + _daysInMonth_. + 1. Repeat, while _resolvedDay_ > _daysInMonth_, + 1. Set _resolvedDay_ to _resolvedDay_ - _daysInMonth_. + 1. Set _resolvedMonth_ to _resolvedMonth_ + 1. + 1. If _resolvedMonth_ > _monthsInYear_, then + 1. Set _resolvedYear_ to _resolvedYear_ + 1. + 1. Set _monthsInYear_ to CalendarMonthsInYear(_calendar_, _resolvedYear_). + 1. Set _resolvedMonth_ to 1. + 1. Set _daysInMonth_ to CalendarDaysInMonth(_calendar_, _resolvedYear_, _resolvedMonth_). + 1. Return the Record { [[Year]]: _resolvedYear_, [[Month]]: _resolvedMonth_, [[Day]]: _resolvedDay_ }. + +
    + + +

    + NonISODateSurpasses ( + _calendar_: a calendar type that is not *"iso8601"*, + _sign_: -1 or 1, + _fromIsoDate_: an ISO Date Record, + _toIsoDate_: an ISO Date Record, + _years_: an integer, + _months_: an integer, + _weeks_: an integer, + _days_: an integer, + ): a Boolean +

    +
    +
    description
    +
    + The return value indicates whether the date _date1_, the result of adding the duration denoted by _years_, _months_, _weeks_, and _days_ to _fromIsoDate_ in the calendar system denoted by _calendar_, surpasses _toIsoDate_ in the direction denoted by _sign_. + If _weeks_ and _days_ are both zero, then _date1_ need not exist (for example, it could be February 30). +
    +
    +

    It performs the following steps when called:

    + + 1. Let _parts_ be CalendarISOToDate(_calendar_, _fromIsoDate_). + 1. Let _calDate2_ be CalendarISOToDate(_calendar_, _toIsoDate_). + 1. Let _y0_ be _parts_.[[Year]] + _years_. + 1. If CompareSurpasses(_sign_, _y0_, _parts_.[[MonthCode]], _parts_.[[Day]], _calDate2_) is *true*, return *true*. + 1. Let _m0_ be MonthCodeToOrdinal(_calendar_, _y0_, ! ConstrainMonthCode(_calendar_, _y0_, _parts_.[[MonthCode]], ~constrain~)). + 1. Let _monthsAdded_ be BalanceNonISODate(_calendar_, _y0_, _m0_ + _months_, 1). + 1. If CompareSurpasses(_sign_, _monthsAdded_.[[Year]], _monthsAdded_.[[Month]], _parts_.[[Day]], _calDate2_) is *true*, return *true*. + 1. If _weeks_ = 0 and _days_ = 0, return *false*. + 1. Let _endOfMonth_ be BalanceNonISODate(_calendar_, _monthsAdded_.[[Year]], _monthsAdded_.[[Month]] + 1, 0). + 1. Let _baseDay_ be _parts_.[[Day]]. + 1. If _baseDay_ ≤ _endOfMonth_.[[Day]], then + 1. Let _regulatedDay_ be _baseDay_. + 1. Else, + 1. Let _regulatedDay_ be _endOfMonth_.[[Day]]. + 1. Let _daysInWeek_ be 7 (the number of days in a week for all supported calendars). + 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + _daysInWeek_ * _weeks_ + _days_). + 1. Return CompareSurpasses(_sign_, _balancedDate_.[[Year]], _balancedDate_.[[Month]], _balancedDate_.[[Day]], _calDate2_). + +
    + + +

    + NonISODateAdd ( + _calendar_: a calendar type that is not *"iso8601"*, + _isoDate_: an ISO Date Record, + _duration_: a Date Duration Record, + _overflow_: ~constrain~ or ~reject~, + ): either a normal completion containing an ISO Date Record or a throw completion +

    +
    +
    description
    +
    + The operation performs processing to add _duration_ to _date_ in the context of the calendar represented by _calendar_ and returns the corresponding day, month and year of the result in the ISO 8601 calendar values as an ISO Date Record. + It may throw a *RangeError* exception if _overflow_ is ~reject~ and the resulting month or day would need to be clamped in order to form a valid date in _calendar_. +
    +
    +

    All calendars follow the steps given here, which is a generalization of the precise algorithm specified in CalendarDateAdd for *"iso8601"*.

    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Let _parts_ be CalendarISOToDate(_calendar_, _isoDate_). + 1. Let _y0_ be _parts_.[[Year]] + _duration_.[[Years]]. + 1. Let _m0_ be MonthCodeToOrdinal(_calendar_, _y0_, ? ConstrainMonthCode(_calendar_, _y0_, _parts_.[[MonthCode]], _overflow_)). + 1. Let _endOfMonth_ be BalanceNonISODate(_calendar_, _y0_, _m0_ + _duration_.[[Months]] + 1, 0). + 1. Let _baseDay_ be _parts_.[[Day]]. + 1. If _baseDay_ ≤ _endOfMonth_.[[Day]], then + 1. Let _regulatedDay_ be _baseDay_. + 1. Else, + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _regulatedDay_ be _endOfMonth_.[[Day]]. + 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + 7 * _duration_.[[Weeks]] + _duration_.[[Days]]). + 1. Let _result_ be ? CalendarIntegersToISO(_calendar_, _balancedDate_.[[Year]], _balancedDate_.[[Month]], _balancedDate_.[[Day]]). + 1. If ISODateWithinLimits(_result_) is *false*, throw a *RangeError* exception. + 1. Return _result_. + +
    + + +

    + NonISODateUntil ( + _calendar_: a calendar type that is not *"iso8601"*, + _one_: an ISO Date Record, + _two_: an ISO Date Record, + _largestUnit_: a date unit, + ): a Date Duration Record +

    +
    +
    description
    +
    + It determines the difference between the dates _one_ and _two_ using the years, months, and weeks reckoning of _calendar_. + No fields larger than _largestUnit_ will be non-zero in the resulting Date Duration Record. +
    +
    +

    All calendars follow the steps given here, which is a generalization of the precise algorithm specified in CalendarDateUntil for *"iso8601"*.

    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Let _sign_ be -1 × CompareISODate(_one_, _two_). + 1. If _sign_ = 0, return ZeroDateDuration(). + 1. Let _years_ be 0. + 1. If _largestUnit_ is ~year~, then + 1. Let _candidateYears_ be _sign_. + 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _candidateYears_, 0, 0, 0) is *false*, + 1. Set _years_ to _candidateYears_. + 1. Set _candidateYears_ to _candidateYears_ + _sign_. + 1. Let _months_ be 0. + 1. If _largestUnit_ is ~year~ or _largestUnit_ is ~month~, then + 1. Let _candidateMonths_ be _sign_. + 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _candidateMonths_, 0, 0) is *false*, + 1. Set _months_ to _candidateMonths_. + 1. Set _candidateMonths_ to _candidateMonths_ + _sign_. + 1. Let _weeks_ be 0. + 1. If _largestUnit_ is ~week~, then + 1. Let _candidateWeeks_ be _sign_. + 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _months_, _candidateWeeks_, 0) is *false*, + 1. Set _weeks_ to _candidateWeeks_. + 1. Set _candidateWeeks_ to _candidateWeeks_ + sign. + 1. Let _days_ be 0. + 1. Let _candidateDays_ be _sign_. + 1. Repeat, while NonISODateSurpasses(_calendar_, _sign_, _one_, _two_, _years_, _months_, _weeks_, _candidateDays_) is *false*, + 1. Set _days_ to _candidateDays_. + 1. Set _candidateDays_ to _candidateDays_ + _sign_. + 1. Return ! CreateDateDurationRecord(_years_, _months_, _weeks_, _days_). + +
    + + +

    + NonISOCalendarDateToISO ( + _calendar_: a calendar type that is not *"iso8601"*, + _fields_: a Calendar Fields Record, + _overflow_: ~constrain~ or ~reject~, + ): either a normal completion containing an ISO Date Record or a throw completion +

    +
    +
    description
    +
    + It converts _fields_, which represents either a date or a year and month in the built-in calendar identified by _calendar_, to a corresponding representative date in the ISO 8601 calendar, subject to overflow correction specified by _overflow_. + For ~reject~, values that do not form a valid date cause an exception to be thrown, as described below. + For ~constrain~, values that do not form a valid date are clamped to their respective valid range. +
    +
    +

    Like RegulateISODate, the operation throws a *RangeError* exception when _overflow_ is ~reject~ and the date described by _fields_ does not exist.

    +

    Clamping an invalid date to the correct range when _overflow_ is ~constrain~ is a behaviour specific to each calendar other than *"iso8601"*, but all calendars follow this guideline.

    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Assert: _fields_.[[Year]], _fields_.[[Month]], and _fields_.[[Day]] are not ~unset~. + 1. If _fields_.[[MonthCode]] is not ~unset~, then + 1. Perform ? ConstrainMonthCode(_calendar_, _fields_.[[Year]], _fields_.[[MonthCode]], _overflow_). + 1. Let _monthsInYear_ be CalendarMonthsInYear(_calendar_, _fields_.[[Year]]). + 1. If _fields_.[[Month]] > _monthsInYear_, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _month_ be _monthsInYear_. + 1. Else, + 1. Let _month_ be _fields_.[[Month]]. + 1. Let _daysInMonth_ be CalendarDaysInMonth(_calendar_, _fields_.[[Year]], _month_). + 1. If _fields_.[[Day]] > _daysInMonth_, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _day_ be _daysInMonth_. + 1. Else, + 1. Let _day_ be _fields_.[[Day]]. + 1. Return ? CalendarIntegersToISO(_calendar_, _fields_.[[Year]], _month_, _day_). + +
    + + +

    + NonISOMonthDayToISOReferenceDate ( + _calendar_: a calendar type that is not *"iso8601"*, + _fields_: a Calendar Fields Record, + _overflow_: ~constrain~ or ~reject~, + ): either a normal completion containing an ISO Date Record or a throw completion +

    +
    +
    description
    +
    + It performs implementation-defined processing to convert _fields_, which represents a calendar date without a year (i.e., month code and day pair, or equivalent) in the built-in calendar identified by _calendar_, to a corresponding reference date in the ISO 8601 calendar as described below, subject to overflow correction specified by _overflow_. + For ~reject~, values that do not form a valid date cause an exception to be thrown. + For ~constrain~, values that do not form a valid date are clamped to their respective valid range as in CalendarDateToISO. +
    +
    +

    + The fields of the returned ISO Date Record represent a reference date in the ISO 8601 calendar that, when converted to _calendar_, corresponds to the month code and day of _fields_ in an arbitrary but deterministically chosen reference year. + The reference year is almost always 1972 (the first ISO 8601 leap year after the epoch), with exceptions for calendars where some dates (e.g. leap days or days in leap months) didn't occur during that ISO 8601 year. + These exceptions are listed in . +

    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Assert: _fields_.[[Day]] is not ~unset~. + 1. If _fields_.[[Year]] is not ~unset~, then + 1. Assert: _fields_.[[Month]] is not ~unset~. + 1. [declared="isoDate"] If there exists no combination of inputs such that ! CalendarIntegersToISO(_calendar_, _fields_.[[Year]], ..., ...) with the constrained _fields_.[[Month]] and _fields_.[[Day]] would return an ISO Date Record _isoDate_ for which ISODateWithinLimits(_isoDate_) is *true*, throw a *RangeError* exception. + 1. NOTE: The above step exists so as not to require calculating whether the month and day described in _fields_ exist in user-provided years arbitrarily far in the future or past. + 1. Let _monthsInYear_ be CalendarMonthsInYear(_calendar_, _fields_.[[Year]]). + 1. If _fields_.[[Month]] > _monthsInYear_, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _month_ be _monthsInYear_. + 1. Else, + 1. Let _month_ be _fields_.[[Month]]. + 1. If _fields_.[[MonthCode]] is ~unset~, then + 1. Let _fieldsISODate_ be ! CalendarIntegersToISO(_calendar_, _fields_.[[Year]], _month_, 1). + 1. Let _monthCode_ be NonISOCalendarISOToDate(_calendar_, _fieldsISODate_).[[MonthCode]]. + 1. Else, + 1. Let _monthCode_ be ? ConstrainMonthCode(_calendar_, _fields_.[[Year]], _fields_.[[MonthCode]], _overflow_). + 1. Let _daysInMonth_ be CalendarDaysInMonth(_calendar_, _fields_.[[Year]], _month_). + 1. Else, + 1. Assert: _fields_.[[MonthCode]] is not ~unset~. + 1. Let _monthCode_ be _fields_.[[MonthCode]]. + 1. If _calendar_ is *"chinese"* or *"dangi"*, let _daysInMonth_ be 30; else, let _daysInMonth_ be the maximum number of days in the month described by _monthCode_ in any year. + 1. If _fields_.[[Day]] > _daysInMonth_, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _day_ be _daysInMonth_. + 1. Else, + 1. Let _day_ be _fields_.[[Day]]. + 1. If _calendar_ is *"chinese"* or *"dangi"*, then + 1. NOTE: This special case handles combinations of month and day that theoretically could occur but are not known to have occurred historically and cannot be accurately calculated to occur in the future, even if it may be possible to construct a PlainDate with such combinations due to inaccurate approximations. This is explicitly mentioned here because as time goes on, these dates may become known to have occurred historically, or may be more accurately calculated to occur in the future. + 1. Let _row_ be the row in with a value matching _calendar_ in the “Calendar Type” column and a value in the “Month Code” column matching _monthCode_. + 1. If the “Reference Year (Days 1-29)” column of _row_ is “—”, or _day_ = 30 and the “Reference Year (Day 30)” column of _row_ is “—”, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Set _monthCode_ to CreateMonthCode(! ParseMonthCode(_monthCode_).[[MonthNumber]], *false*). + 1. Let _row_ be the row in with a value matching _calendar_ in the “Calendar Type” column and a value in the “Month Code” column matching _monthCode_ (or “any” or “others” if there is no row matching _monthCode_ exactly). + 1. Assert: _monthCode_ and _day_ do not match an entry in _row_ that is “—”. + 1. Let _referenceYear_ be the ISO reference year for _monthCode_ and _day_ as described in _row_. + 1. Return the latest possible ISO Date Record _isoDate_ such that _isoDate_.[[Year]] = _referenceYear_ and NonISOCalendarISOToDate(_calendar_, _isoDate_) returns a Calendar Date Record whose [[MonthCode]] and [[Day]] field values respectively equal _monthCode_ and _day_. + + + + ISO Reference Years + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Calendar TypeMonth CodeReference Year (Days 1–29)Reference Year (Day 30)
    *"buddhist"*, *"gregory"*, *"indian"*, *"japanese"*, *"persian"*, *"roc"*anyAny day including 31: 1972
    *"chinese"*, *"dangi"*M0119721970
    M01L
    M021972
    M02L1947
    M031972*"chinese"*: 1966
    + *"dangi"*: 1968
    M03L19661955
    M0419721970
    M04L19631944
    M051972
    M05L19711952
    M0619721971
    M06L19601941
    M071972
    M07L19681938
    M0819721971
    M08L1957
    M091972
    M09L2014
    M101972
    M10L1984
    M1119721970
    M11LDays 1–10: 2033
    + Days 11–29: 2034
    M121972
    M12L
    *"coptic"*, *"ethioaa"*, *"ethiopic"*M13Days 1–5: 1972
    + Day 6: 1971
    + Days 7–29: —
    others1972
    *"hebrew"*M0219721971
    M0319721971
    M05L1970
    others1972
    *"islamic-civil"*, *"islamic-tbla"*M1219721971
    others1972
    *"islamic-umalqura"*M011972
    M0219721970
    M0319721971
    M041972
    M0519721971
    M061972
    M0719721969
    M081972
    M091972
    M1019721970
    M111972
    M1219721971
    +
    +
    + + +

    + CalendarExtraFields ( + _calendar_: a calendar type, + _fields_: a List of values from the “Enumeration Key” column of , + ): a List of values from the “Enumeration Key” column of +

    +
    +
    description
    +
    It characterizes calendar-specific fields that are relevant for the provided _fields_ in the built-in calendar identified by _calendar_.
    +
    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. If _fields_ contains an element equal to ~year~ and CalendarSupportsEra(_calendar_) is *true*, then + 1. Return « ~era~, ~era-year~ ». + 1. Return an empty List. + +
    + + +

    + NonISOFieldKeysToIgnore ( + _calendar_: a calendar type that is not *"iso8601"*, + _keys_: a List of values from the “Enumeration Key” column of , + ): a List of values from the “Enumeration Key” column of +

    +
    +
    description
    +
    + It determines which calendar date fields changing any of the fields named in _keys_ can potentially conflict with or invalidate, for the given _calendar_. + A field always invalidates at least itself. +
    +
    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Let _ignoredKeys_ be a copy of _keys_. + 1. For each element _key_ of _keys_, do + 1. If _key_ is ~month~, append ~month-code~ to _ignoredKeys_. + 1. If _key_ is ~month-code~, append ~month~ to _ignoredKeys_. + 1. If _key_ is one of ~era~, ~era-year~, or ~year~ and CalendarSupportsEra(_calendar_) is *true*, then + 1. Append ~era~, ~era-year~, and ~year~ to _ignoredKeys_. + 1. If _key_ is one of ~day~, ~month~, or ~month-code~ and CalendarHasMidYearEras(_calendar_) is *true*, then + 1. Append ~era~ and ~era-year~ to _ignoredKeys_. + 1. NOTE: While _ignoredKeys_ can have duplicate elements, this is not intended to be meaningful. This specification only checks whether particular keys are or are not members of the list. + 1. Return _ignoredKeys_. + +
    + + +

    + NonISOResolveFields ( + _calendar_: a calendar type that is not *"iso8601"*, + _fields_: a Calendar Fields Record, + _type_: ~date~, ~year-month~, or ~month-day~, + ): either a normal completion containing ~unused~ or a throw completion +

    +
    +
    description
    +
    + It performs implementation-defined processing to validate that _fields_ (which describes a date or partial date in the built-in calendar identified by _calendar_) is sufficiently complete to satisfy _type_ and not internally inconsistent, and mutates _fields_ into acceptable input for CalendarDateToISO or CalendarMonthDayToISOReferenceDate by merging data that can be represented in multiple forms into standard fields and removing redundant fields (for example, merging [[Era]] and [[EraYear]] into [[Year]]). +
    +
    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Let _needsYear_ be *false*. + 1. If _type_ is ~date~ or _type_ is ~year-month~, set _needsYear_ to *true*. + 1. If _fields_.[[MonthCode]] is ~unset~, set _needsYear_ to *true*. + 1. If _fields_.[[Month]] is not ~unset~, set _needsYear_ to *true*. + 1. Let _needsOrdinalMonth_ be *false*. + 1. If _fields_.[[Year]] is not ~unset~, set _needsOrdinalMonth_ to *true*. + 1. If _fields_.[[EraYear]] is not ~unset~, set _needsOrdinalMonth_ to *true*. + 1. Let _needsDay_ be *false*. + 1. If _type_ is ~date~ or _type_ is ~month-day~, set _needsDay_ to *true*. + 1. If _needsYear_ is *true*, then + 1. If _fields_.[[Year]] is ~unset~, then + 1. If CalendarSupportsEra(_calendar_) is *false*, throw a *TypeError* exception. + 1. If _fields_.[[Era]] is ~unset~ or _fields_.[[EraYear]] is ~unset~, throw a *TypeError* exception. + 1. If CalendarSupportsEra(_calendar_) is *true*, then + 1. If _fields_.[[Era]] is not ~unset~ and _fields_.[[EraYear]] is ~unset~, throw a *TypeError* exception. + 1. If _fields_.[[EraYear]] is not ~unset~ and _fields_.[[Era]] is ~unset~, throw a *TypeError* exception. + 1. If _needsDay_ is *true* and _fields_.[[Day]] is ~unset~, throw a *TypeError* exception. + 1. If _fields_.[[Month]] is ~unset~ and _fields_.[[MonthCode]] is ~unset~, throw a *TypeError* exception. + 1. If CalendarSupportsEra(_calendar_) is *true* and _fields_.[[EraYear]] is not ~unset~, then + 1. Let _canonicalEra_ be CanonicalizeEraInCalendar(_calendar_, _fields_.[[Era]]). + 1. If _canonicalEra_ is *undefined*, throw a *RangeError* exception. + 1. Let _arithmeticYear_ be CalendarDateArithmeticYearForEraYear(_calendar_, _canonicalEra_, _fields_.[[EraYear]]). + 1. If _fields_.[[Year]] is not ~unset~, and _fields_.[[Year]] ≠ _arithmeticYear_, throw a *RangeError* exception. + 1. Set _fields_.[[Year]] to _arithmeticYear_. + 1. Set _fields_.[[Era]] to ~unset~. + 1. Set _fields_.[[EraYear]] to ~unset~. + 1. NOTE: _fields_.[[Era]] and _fields_.[[EraYear]] are erased in order to allow a lenient interpretation of out-of-bounds values, which is particularly useful for consistent interpretation of dates in calendars with regnal eras. + 1. If _fields_.[[MonthCode]] is not ~unset~, then + 1. If IsValidMonthCodeForCalendar(_calendar_, _fields_.[[MonthCode]]) is *false*, throw a *RangeError* exception. + 1. If _fields_.[[Year]] is not ~unset~, then + 1. If YearContainsMonthCode(_calendar_, _fields_.[[Year]], _fields_.[[MonthCode]]) is *true*, let _constrainedMonthCode_ be _fields_.[[MonthCode]]; else let _constrainedMonthCode_ be ! ConstrainMonthCode(_calendar_, _fields_.[[Year]], _fields_.[[MonthCode]], ~constrain~). + 1. Let _month_ be MonthCodeToOrdinal(_calendar_, _fields_.[[Year]], _constrainedMonthCode_). + 1. If _fields_.[[Month]] is not ~unset~ and _fields_.[[Month]] ≠ _month_, throw a *RangeError* exception. + 1. Set _fields_.[[Month]] to _month_. + 1. NOTE: _fields_.[[MonthCode]] is intentionally not overwritten with _constrainedMonthCode_. Pending the "overflow" parameter in CalendarDateToISO or CalendarMonthDayToISOReferenceDate, a month code not occurring in _fields_.[[Year]] may cause that operation to throw. However, if _fields_.[[Month]] is present, it must agree with the constrained month code. + 1. Assert: _fields_.[[Era]] and _fields_.[[EraYear]] are ~unset~. + 1. Assert: If _needsYear_ is *true*, _fields_.[[Year]] is not ~unset~. + 1. Assert: If _needsOrdinalMonth_ is *true*, _fields_.[[Month]] is not ~unset~. + 1. Assert: If _needsDay_ is *true*, _fields_.[[Day]] is not ~unset~. + 1. Return ~unused~. + +
    + diff --git a/spec/locales-currencies-tz.html b/spec/locales-currencies-tz.html index be80bda3..c98c0943 100644 --- a/spec/locales-currencies-tz.html +++ b/spec/locales-currencies-tz.html @@ -10,9 +10,6 @@

    Case Sensitivity and Case Mapping

    For example, *"ß"* (U+00DF) must not match or be mapped to *"SS"* (U+0053, U+0053). *"ı"* (U+0131) must not match or be mapped to *"I"* (U+0049). -

    The ASCII-uppercase of a String value _S_ is the String value derived from _S_ by replacing each occurrence of an ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) with the corresponding ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) while preserving all other code units.

    -

    The ASCII-lowercase of a String value _S_ is the String value derived from _S_ by replacing each occurrence of an ASCII uppercase letter code unit (0x0041 through 0x005A, inclusive) with the corresponding ASCII lowercase letter code unit (0x0061 through 0x007A, inclusive) while preserving all other code units.

    -

    A String value _A_ is an ASCII-case-insensitive match for String value _B_ if the ASCII-uppercase of _A_ is exactly the same sequence of code units as the ASCII-uppercase of _B_. A sequence of Unicode code points _A_ is an ASCII-case-insensitive match for _B_ if _B_ is an ASCII-case-insensitive match for CodePointsToString(_A_).

    @@ -520,16 +517,142 @@

    AvailableCanonicalCollations ( ): a List of Strings

    Calendar Types

    +

    + ECMA-262 describes calendar types, of which *"iso8601"* is required to be supported. + This specification additionally requires ECMAScript implementations to support an explicit subset of calendar types defined in the Unicode Common Locale Data Repository (CLDR) and prohibits them from supporting other calendar types, although future editions may expand the list. +

    -

    This specification identifies calendars using a calendar type as defined by Unicode Technical Standard #35 Part 4 Dates, Section 2 Calendar Elements. Their canonical form is a string containing only Unicode Basic Latin lowercase letters (U+0061 LATIN SMALL LETTER A through U+007A LATIN SMALL LETTER Z) with zero or more medial hyphens (U+002D HYPHEN-MINUS).

    +

    + The following table lists the sanctioned calendar types, along with implementation notes and sources where necessary. + All calendar types must use a proleptic reckoning, meaning that the current rules for calendrical calculations are extended indefinitely into the past, ignoring dates when historical calendar reforms happened. +

    - -

    AvailableCalendars ( ): a List of Strings

    -
    -
    description
    -
    The returned List is sorted according to lexicographic code unit order, and contains unique calendar types in canonical form () identifying the calendars for which the implementation provides the functionality of Intl.DateTimeFormat objects, including their aliases (e.g., either both or neither of *"islamicc"* and *"islamic-civil"*). The List must include *"iso8601"*.
    -
    -
    +

    + For example, at various points from the 16th to the 20th century, various locales in Europe changed from the Julian to the Gregorian calendar, skipping some dates in the process. + Since the *"gregory"* calendar is proleptic, no dates are skipped; all dates are in the "new system," even if it wasn't used at the time. +

    + + + Calendar types described in CLDR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Calendar TypeDescription and implementation notes
    *"buddhist"*Thai Buddhist calendar. Month numbers, month codes, and days are identical to ISO 8601, with one era and an epoch year differing from the epoch year in *"gregory"*. All years are treated as having 12 months. For compatibility with other systems, dates prior to ISO year 1941 (2484 BE) are defined but may not correspond to historically accurate values due to the calendar reforms of 1940 and earlier.
    *"chinese"*Traditional Chinese calendar. Lunisolar calendar, based on data published by the Purple Mountain Observatory for dates between 1900 and 2100 (which complies with GB/T 33661-2017, Calculation and Promulgation of the Chinese Calendar), falling back to an implementation-defined approximation outside that range. The arithmetic year is as in *"gregory"*, and there are no eras.
    *"coptic"*Coptic calendar. Similar solar algorithm to *"ethioaa"* and *"ethiopic"* but with a different epoch year. There is one era, starting in the epoch year.
    *"dangi"*Traditional Korean calendar. Lunisolar calendar, based on data published by the Korea Astronomy and Space Science Institute (KASI) for dates between 1900 and 2050, falling back to an implementation-defined approximation outside that range. The arithmetic year is as in *"gregory"*, and there are no eras.
    *"ethioaa"*Ethiopian calendar, Amete Alem era. Similar solar algorithm to *"coptic"* and *"ethiopic"*, but with a different epoch year. There is one era, starting in the epoch year.
    *"ethiopic"*Ethiopian calendar, Amete Mihret era. Similar solar algorithm to *"coptic"* and *"ethioaa"*, but with a different epoch year. There are two eras, one starting in the epoch year of *"ethioaa"* and one starting in this calendar's epoch year.
    *"ethiopic-amete-alem"*Alias for *"ethioaa"*.
    *"gregory"*Gregorian calendar. Solar calendar almost identical to the ISO 8601 calendar, except that it does not define week numbering and it contains two eras, one before the epoch year and one after.
    *"hebrew"*Hebrew calendar. Civil calendar with Tishrei as the first month of the year. Lunisolar calendar with one leap month inserted after month 5. There is one era.
    *"indian"*Indian national (or Śaka) calendar. Solar calendar with one era.
    *"islamic-civil"*Tabular Hijri calendar with leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29 in the 30-year cycle, and civil epoch (Friday July 16, 622 Julian / 0622-07-19 ISO)
    *"islamic-tbla"*Tabular Hijri calendar with leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, 29 in the 30-year cycle, and astronomical epoch (Thursday July 15, 622 Julian / 0622-07-18 ISO)
    *"islamic-umalqura"*Hijri calendar, Umm al-Qura. Lunar calendar using months calculated by King Abdulaziz City for Science and Technology (KACST) for dates from the start of 1300 AH to the end of 1600 AH, falling back to *"islamic-civil"* outside that range.
    *"islamicc"*Alias for *"islamic-civil"*.
    *"iso8601"*ISO 8601 calendar. Fully specified in ECMA-262.
    *"japanese"*Japanese Imperial calendar, era system hybridised with the era system used in *"gregory"*. Month numbers, month codes, and days are the same as in the ISO 8601 calendar. For dates up to and including 1872-12-31, years and eras identical to *"gregory"* are used. For later dates, the eras and ranges defined by the Japanese government are used. Note that ISO year 1873 is the 6th year of the Meiji period, starting on ISO date 1868-10-23, during which calendar reforms took place. The arithmetic year is identical to *"gregory"*.
    *"persian"*Persian (or Solar Hijri) calendar. There is one era. Solar calendar using leap years as published by the Iranian calendar authority for dates between 1206 AP and 1498 AP, falling back to an implementation-defined approximation outside that range.
    *"roc"*Republic of China (or Minguo) calendar. Month numbers, month codes, and days are the same as in the ISO 8601 calendar, with two eras, one before the epoch year and one after. The epoch year is different from *"gregory"*.
    +
    +
    + + +

    AvailableCalendars ( ): a List of calendar types

    +
    +
    description
    +
    The returned List is sorted according to lexicographic code unit order, and contains unique calendar types in canonical form () identifying the calendars for which the implementation provides the functionality of Intl.DateTimeFormat objects, including their aliases.
    +
    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + 1. Let _identifiers_ be a new empty List. + 1. For each row of , except the header row, in table order, do + 1. Let _identifier_ be the “Calendar Type” value of the current row. + 1. Append _identifier_ to _identifiers_. + 1. Sort _identifiers_ according to lexicographic code unit order. + 1. Return _identifiers_. + +
    + + +

    + CanonicalizeCalendar ( + _id_: a String, + ): either a normal completion containing a calendar type, or a throw completion +

    +
    +
    description
    +
    It returns the canonical form of the calendar type denoted by _id_, or throws an exception if there is no such built-in calendar.
    +
    +

    This definition supersedes the definition provided in .

    +

    It performs the following steps when called:

    + + + 1. Let _calendars_ be AvailableCalendars(). + 1. If _calendars_ does not contain the ASCII-lowercase of _id_, throw a *RangeError* exception. + 1. Return CanonicalizeUValue(*"ca"*, _id_). +
    diff --git a/spec/negotiation.html b/spec/negotiation.html index 34f75ffb..e7b6898d 100644 --- a/spec/negotiation.html +++ b/spec/negotiation.html @@ -28,8 +28,8 @@

    Internal slots of Service Constructors

    For example, an implementation of DateTimeFormat might include the language tag *"fa-IR"* in its [[AvailableLocales]] internal slot, and must (according to ) include the keys *"ca"*, *"hc"*, and *"nu"* in its [[RelevantExtensionKeys]] internal slot. - The default calendar for that locale is usually *"persian"*, but an implementation might also support *"gregory"*, *"islamic"*, and *"islamic-civil"*. - The Record in the DateTimeFormat [[LocaleData]] internal slot would therefore include a [[fa-IR]] field whose value is a Record like { [[ca]]: « *"persian"*, *"gregory"*, *"islamic"*, *"islamic-civil"* », [[hc]]: « … », [[nu]]: « … » }, along with other locale-named fields having the same value shape but different elements in their Lists. + The default calendar for that locale is usually *"persian"*, but an implementation might also support *"gregory"* and *"islamic-civil"*. + The Record in the DateTimeFormat [[LocaleData]] internal slot would therefore include a [[fa-IR]] field whose value is a Record like { [[ca]]: « *"persian"*, *"gregory"*, *"islamic-civil"* », [[hc]]: « … », [[nu]]: « … » }, along with other locale-named fields having the same value shape but different elements in their Lists.
    diff --git a/spec/normative-references.html b/spec/normative-references.html index 6ccc8546..e4a0f1f9 100644 --- a/spec/normative-references.html +++ b/spec/normative-references.html @@ -46,6 +46,9 @@

    Normative References

  • Part 3 Numbers, Section 5.1.1 Operands
  • +
  • + Part 4 Dates, Calendar Data +
  • diff --git a/spec/numberformat.html b/spec/numberformat.html index 82ec6bc0..2a2fbc8e 100644 --- a/spec/numberformat.html +++ b/spec/numberformat.html @@ -535,112 +535,10 @@

    Properties of Intl.NumberFormat Instances

    In scientific notation, this slot affects the sign display of the mantissa but not the exponent.
  • [[RoundingIncrement]] is an integer that evenly divides 10, 100, 1000, or 10000 into tenths, fifths, quarters, or halves. It indicates the increment at which rounding should take place relative to the calculated rounding magnitude. For example, if [[MaximumFractionDigits]] is 2 and [[RoundingIncrement]] is 5, then formatted numbers are rounded to the nearest 0.05 ("nickel rounding").
  • -
  • [[RoundingMode]] is a rounding mode, one of the String values in the Identifier column of .
  • +
  • [[RoundingMode]] is a rounding mode, one of the Strings in the “String Identifier” column of .
  • [[TrailingZeroDisplay]] is one of the String values *"auto"* or *"stripIfInteger"*, indicating whether to strip trailing zeros if the formatted number is an integer (i.e., has no non-zero fraction digit).
  • - - Rounding modes in Intl.NumberFormat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    IdentifierDescriptionExamples: Round to 0 fraction digits
    -1.50.40.50.61.5
    *"ceil"*Toward positive infinity⬆️ [-1]⬆️ [1]⬆️ [1]⬆️ [1]⬆️ [2]
    *"floor"*Toward negative infinity⬇️ [-2]⬇️ [0]⬇️ [0]⬇️ [0]⬇️ [1]
    *"expand"*Away from zero⬇️ [-2]⬆️ [1]⬆️ [1]⬆️ [1]⬆️ [2]
    *"trunc"*Toward zero⬆️ [-1]⬇️ [0]⬇️ [0]⬇️ [0]⬇️ [1]
    *"halfCeil"*Ties toward positive infinity⬆️ [-1]⬇️ [0]⬆️ [1]⬆️ [1]⬆️ [2]
    *"halfFloor"*Ties toward negative infinity⬇️ [-2]⬇️ [0]⬇️ [0]⬆️ [1]⬇️ [1]
    *"halfExpand"*Ties away from zero⬇️ [-2]⬇️ [0]⬆️ [1]⬆️ [1]⬆️ [2]
    *"halfTrunc"*Ties toward zero⬆️ [-1]⬇️ [0]⬇️ [0]⬆️ [1]⬇️ [1]
    *"halfEven"*Ties toward an even rounding increment multiple⬇️ [-2]⬇️ [0]⬇️ [0]⬆️ [1]⬆️ [2]
    - The examples are illustrative of the unique behaviour of each option. ⬆️ means "resolves toward positive infinity"; ⬇️ means "resolves toward negative infinity". -
    -

    Finally, Intl.NumberFormat instances have a [[BoundFormat]] internal slot that caches the function returned by the format accessor ().

    @@ -1283,7 +1181,7 @@

    _x_: a non-negative mathematical value, _minPrecision_: an integer in the inclusive interval from 1 to 21, _maxPrecision_: an integer in the inclusive interval from 1 to 21, - _unsignedRoundingMode_: a specification type from the Unsigned Rounding Mode column of , or *undefined*, + _unsignedRoundingMode_: a specification type from the “Unsigned Rounding Mode” column of , or *undefined*, ): a Record with fields [[FormattedString]] (a String), [[RoundedNumber]] (a mathematical value), [[IntegerDigitsCount]] (an integer), and [[RoundingMagnitude]] (an integer)

    @@ -1341,7 +1239,7 @@

    _minFraction_: an integer in the inclusive interval from 0 to 100, _maxFraction_: an integer in the inclusive interval from 0 to 100, _roundingIncrement_: an integer, - _unsignedRoundingMode_: a specification type from the Unsigned Rounding Mode column of , or *undefined*, + _unsignedRoundingMode_: a specification type from the “Unsigned Rounding Mode” column of , or *undefined*, ): a Record with fields [[FormattedString]] (a String), [[RoundedNumber]] (a mathematical value), [[IntegerDigitsCount]] (an integer), and [[RoundingMagnitude]] (an integer)

    @@ -1672,148 +1570,6 @@

    - -

    - GetUnsignedRoundingMode ( - _roundingMode_: a rounding mode, - _sign_: ~negative~ or ~positive~, - ): a specification type from the Unsigned Rounding Mode column of -

    -
    -
    description
    -
    It returns the rounding mode that should be applied to the absolute value of a number to produce the same result as if _roundingMode_ were applied to the signed value of the number (negative if _sign_ is ~negative~, or positive otherwise).
    -
    - - 1. Return the specification type in the Unsigned Rounding Mode column of for the row where the value in the Identifier column is _roundingMode_ and the value in the Sign column is _sign_. - - - Conversion from rounding mode to unsigned rounding mode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    IdentifierSignUnsigned Rounding Mode
    *"ceil"*~positive~~infinity~
    ~negative~~zero~
    *"floor"*~positive~~zero~
    ~negative~~infinity~
    *"expand"*~positive~~infinity~
    ~negative~~infinity~
    *"trunc"*~positive~~zero~
    ~negative~~zero~
    *"halfCeil"*~positive~~half-infinity~
    ~negative~~half-zero~
    *"halfFloor"*~positive~~half-zero~
    ~negative~~half-infinity~
    *"halfExpand"*~positive~~half-infinity~
    ~negative~~half-infinity~
    *"halfTrunc"*~positive~~half-zero~
    ~negative~~half-zero~
    *"halfEven"*~positive~~half-even~
    ~negative~~half-even~
    -
    -
    - - -

    - ApplyUnsignedRoundingMode ( - _x_: a mathematical value, - _r1_: a mathematical value, - _r2_: a mathematical value, - _unsignedRoundingMode_: a specification type from the Unsigned Rounding Mode column of , or *undefined*, - ): a mathematical value -

    -
    -
    description
    -
    It considers _x_, bracketed below by _r1_ and above by _r2_, and returns either _r1_ or _r2_ according to _unsignedRoundingMode_.
    -
    - - 1. If _x_ is _r1_, return _r1_. - 1. Assert: _r1_ < _x_ < _r2_. - 1. Assert: _unsignedRoundingMode_ is not *undefined*. - 1. If _unsignedRoundingMode_ is ~zero~, return _r1_. - 1. If _unsignedRoundingMode_ is ~infinity~, return _r2_. - 1. Let _d1_ be _x_ – _r1_. - 1. Let _d2_ be _r2_ – _x_. - 1. If _d1_ < _d2_, return _r1_. - 1. If _d2_ < _d1_, return _r2_. - 1. Assert: _d1_ is _d2_. - 1. If _unsignedRoundingMode_ is ~half-zero~, return _r1_. - 1. If _unsignedRoundingMode_ is ~half-infinity~, return _r2_. - 1. Assert: _unsignedRoundingMode_ is ~half-even~. - 1. Let _cardinality_ be (_r1_ / (_r2_ – _r1_)) modulo 2. - 1. If _cardinality_ is 0, return _r1_. - 1. Return _r2_. - -
    -

    PartitionNumberRangePattern (