diff --git a/biblio.json b/biblio.json index b213f38..04e280e 100644 --- a/biblio.json +++ b/biblio.json @@ -133,5 +133,15 @@ "id": "sec-temporal-createmonthcode" } ] + }, + { + "location": "https://tc39.es/ecma262/", + "entries": [ + { + "type": "op", + "aoid": "ℝ", + "id": "ℝ" + } + ] } ] diff --git a/spec.emu b/spec.emu index 6cd16c6..4c1f615 100644 --- a/spec.emu +++ b/spec.emu @@ -828,7 +828,7 @@ contributors: Google, Ecma International
description
-
It produces the year relative to the epoch year (the arithmetic year) for a given set of era, eraYear for a calendar that has eras.
+
It produces the year relative to the epoch year (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_). @@ -981,6 +981,171 @@ contributors: Google, Ecma International + +

+ CalendarDateArithmeticalToISO ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _ordinalMonth_: a positive integer, + _day_: an 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. Return _isoDate_. + +
+ + +

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

+
+
description
+
+ It interprets _arithmeticYear_ and _ordinalMonth_ as arithmetical values in the given _calendar_ and returns the number of days in the corresponding month. +
+
+

It performs the following steps when called:

+ + 1. Return a calendar-dependent integer as described above. + +
+ + +

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

+
+
description
+
+ It interprets _arithmeticYear_ as arithmetical value in the given _calendar_ and returns the number of months in the corresponding year. + It returns the number of months in the _calendar_-specific _arithmeticYear_. +
+
+

It performs the following steps when called:

+ + 1. Return the number of months in arithmetic year _arithmeticYear_ of calendar _calendar_. + +
+ + +

+ BalanceNonISODate ( + _calendar_: a calendar type that is not *"iso8601"*, + _arithmeticYear_: an integer, + _ordinalMonth_: an integer, + _day_: an integer, + ): a Record with fields [[Year]] (an integer), [[Month]] (an integer), and [[Day]] (an 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 be 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 _day_ + _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 _y0_ be _parts_.[[Year]] + _years_. + 1. Let _m0_ be MonthCodeToOrdinal(_calendar_, _y0_, ! ConstrainMonthCode(_calendar_, _y0_, _parts_.[[MonthCode]], ~constrain~)). + 1. Let _endOfMonth_ be BalanceNonISODate(_calendar_, _y0_, _m0_ + _months_ + 1, 0). + 1. Let _baseDay_ be _parts_.[[Day]]. + 1. If _weeks_ is not 0 or _days_ is not 0, then + 1. If _baseDay_ < _endOfMonth_.[[Day]], then + 1. Let _regulatedDay_ be _baseDay_. + 1. Else, + 1. Let _regulatedDay_ be _endOfMonth_.[[Day]]. + 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + 7 * _weeks_ + _days_). + 1. Let _y1_ be _balancedDate_.[[Year]]. + 1. Let _m1_ be _balancedDate_.[[Month]]. + 1. Let _d1_ be _balancedDate_.[[Day]]. + 1. Else, + 1. Let _y1_ be _endOfMonth_.[[Year]]. + 1. Let _m1_ be _endOfMonth_.[[Month]]. + 1. Let _d1_ be _baseDay_. + 1. Let _calDate2_ be CalendarISOToDate(_calendar_, _toIsoDate_). + 1. If _y1_ ≠ _calDate2_.[[Year]], then + 1. If _sign_ × (_y1_ - _calDate2_.[[Year]]) > 0, return *true*. + 1. Else if _m1_ ≠ _calDate2_.[[Month]], then + 1. If _sign_ × (_m1_ - _calDate2_.[[Month]]) > 0, return *true*. + 1. Else if _d1_ ≠ _calDate2_.[[Day]], then + 1. If _sign_ × (_d1_ - _calDate2_.[[Day]]) > 0, return *true*. + 1. Return *false*. + +
+

NonISODateAdd ( @@ -997,23 +1162,26 @@ contributors: Google, Ecma International 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_. -

The behaviour is implementation-defined, but all calendars follow the general steps given here, which is a generalization of the precise algorithm specified in CalendarDateAdd for *"iso8601"*.

+

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 _calendarDate_ be CalendarISOToDate(_calendar_, _isoDate_). - 1. Add _duration_.[[Years]] to _calendarDate_ without changing any less-significant fields. - 1. If YearContainsMonthCode(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]]) is *false*, then - 1. NOTE: This only happens in lunisolar calendars. - 1. Set _calendarDate_.[[MonthCode]] to ! ConstrainMonthCode(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]], ~constrain~). - 1. Set _calendarDate_.[[Month]] to MonthCodeToOrdinal(_calendar_, _calendarDate_.[[Year]], _calendarDate_.[[MonthCode]]). - 1. Add _duration_.[[Months]] to _calendarDate_, balancing _calendarDate_ if it goes over a year boundary. - 1. If the date described by _calendarDate_ does not exist, then + 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]], ~constrain~)). + 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. If _overflow_ is ~reject~, throw a *RangeError* exception. - 1. If _calendarDate_.[[MonthCode]] is a valid month code for _calendarDate_.[[Year]], but the date described by _calendarDate_ does not exist, set _calendarDate_.[[Day]] to the closest day in the same month. If there are two equally-close dates in the same month, pick the later one. - 1. (This step does not apply to any currently supported calendars.) If the date described by _calendarDate_ still does not exist, set _calendarDate_ to the closest date in the same year. If there are two equally-close dates in that year, pick the later one. - 1. Add _duration_.[[Weeks]] and _duration_.[[Days]] to _calendarDate_, balancing _calendarDate_ if it goes over a month or year boundary. - 1. Let _result_ be ? CalendarDateToISO(_calendar_, _calendarDate_, _overflow_). + 1. Let _regulatedDay_ be _endOfMonth_.[[Day]]. + 1. Else, + 1. Let _regulatedDay_ be _baseDay_. + 1. Let _balancedDate_ be BalanceNonISODate(_calendar_, _endOfMonth_.[[Year]], _endOfMonth_.[[Month]], _regulatedDay_ + 7 * _duration_.[[Weeks]] + _duration_.[[Days]]). + 1. Let _result_ be ? CalendarDateArithmeticalToISO(_calendar_, _balancedDate_.[[Year]], _balancedDate_.[[Month]], _balancedDate_.[[Day]]). 1. If ISODateWithinLimits(_result_) is *false*, throw a *RangeError* exception. 1. Return _result_. @@ -1035,19 +1203,36 @@ contributors: Google, Ecma International No fields larger than _largestUnit_ will be non-zero in the resulting Date Duration Record. -

The algorithm is implementation-defined, but all calendars follow the general steps given here, which is a generalization of the precise algorithm specified in CalendarDateUntil for *"iso8601"*.

+

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. Add (without constraining) as many years as possible to _one_, in the direction from _one_ to _two_, without surpassing _two_. "Surpassing" here (and in all steps below) means to compare years numerically, then month codes lexicographically, then days numerically; if any of them exceed _two_ in the direction from _one_ to _two_, then _two_ is surpassed. - 1. Constrain _one_ to a real year and month, not taking day into account. This step only matters for lunisolar calendars. - 1. If _largestUnit_ is ~year~ or ~month~, then - 1. Add (without constraining) as many months as possible to _one_ without surpassing _two_. - 1. Constrain _one_ to a real year, month, and day. - 1. If _largestUnit_ is ~week~, add as many weeks as possible to _one_ without surpassing _two_. - 1. Add as many days as possible to _one_ until it is equal to _two_. - 1. Return a Date Duration Record of the number of years, months, weeks, and days added. + 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_). @@ -1087,8 +1272,13 @@ contributors: Google, Ecma International 1. Let _ordinalMonth_ be _fields_.[[Month]]. 1. Let _day_ be _fields_.[[Day]]. 1. Assert: _day_ is not ~unset~. - 1. If the date described by _calendar_, _arithmeticYear_, _ordinalMonth_, and _day_ does not exist, set _day_ to the closest day in the same month. If there are two equally-close dates in the same month, pick the later one. - 1. Return an implementation-defined ISO Date Record that corresponds to the date described by _calendar_, _arithmeticYear_, _ordinalMonth_, and _day_. + 1. Let _daysInMonth_ be CalendarDaysInMonth(_calendar_, _arithmeticYear_, _ordinalMonth_). + 1. If _daysInMonth_ ≤ _day_, then + 1. If _overflow_ is ~reject~, throw a *RangeError* exception. + 1. Let _regulatedDay_ be _daysInMonth_. + 1. Else, + 1. Let _regulatedDay_ be _day_. + 1. Return ? CalendarDateArithmeticalToISO(_calendar_, _arithmeticYear_, _ordinalMonth_, _regulatedDay_).