Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normative: Change date AOs to accept mathematical values #2518

Merged
merged 1 commit into from
Apr 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions spec/abstractops.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,109 @@ <h1>
</emu-alg>
</emu-clause>

<emu-clause id="sec-isodatetoepochdays" type="abstract operation">
<h1>
ISODateToEpochDays (
_year_: an integer,
_month_: an integer,
_date_: an integer,
): an integer
</h1>
<dl class="header">
<dt>description</dt>
<dd>It calculates a number of days.</dd>
</dl>
<emu-alg>
1. Let _resolvedYear_ be _year_ + floor(_month_ / 12).
1. Let _resolvedMonth_ be _month_ modulo 12.
1. Find a time _t_ such that EpochTimeToEpochYear(_t_) is _resolvedYear_, EpochTimeToMonthInYear(_t_) is _resolvedMonth_, and EpochTimeToDate(_t_) is 1.
1. Return EpochTimeToDayNumber(_t_) + _date_ - 1.
</emu-alg>
<emu-note type="editor"> This operation corresponds to ECMA-262 operation MakeDay(_year_, _month_, _date_). It calculates the result in mathematical values instead of Number values. These two operations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.</emu-note>
</emu-clause>

<emu-clause id="sec-epochdaystoepochms" type="abstract operation">
<h1>
EpochDaysToEpochMs (
_day_: an integer,
_time_: an integer,
): an integer
</h1>
<dl class="header">
<dt>description</dt>
<dd>It calculates a number of milliseconds.</dd>
</dl>
<emu-alg>
1. Return _day_ × ℝ(msPerDay) + _time_.
</emu-alg>
<emu-note type="editor"> This operation corresponds to ECMA-262 operation MakeDate(_date_, _time_). It calculates the result in mathematical values instead of Number values. These two operations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.</emu-note>
</emu-clause>

<emu-clause id="sec-date-equations">
<h1>Date Equations</h1>
<p>A given time _t_ belongs to day number</p>
<emu-eqn id="eqn-EpochTimeToDayNumber" aoid="EpochTimeToDayNumber">EpochTimeToDayNumber(_t_) = floor(_t_ / ℝ(msPerDay))</emu-eqn>
<p>Number of days in year are given by:</p>
<emu-eqn id="eqn-mathematicaldaysinyear" aoid="MathematicalDaysInYear">
MathematicalDaysInYear(_y_)
= 365 if ((_y_) modulo 4) ≠ 0
= 366 if ((_y_) modulo 4) = 0 and ((_y_) modulo 100) ≠ 0
= 365 if ((_y_) modulo 100) = 0 and ((_y_) modulo 400) ≠ 0
= 366 if ((_y_) modulo 400) = 0
</emu-eqn>
<p>The day number of the first day of year _y_ is given by:</p>
<emu-eqn id="eqn-epochdaynumberforyear" aoid="EpochDayNumberForYear">EpochDayNumberForYear(_y_) = 365 × (_y_ - 1970) + floor((_y_ - 1969) / 4) - floor((_y_ - 1901) / 100) + floor((_y_ - 1601) / 400)</emu-eqn>
<p>The time of the start of a year is:</p>
<emu-eqn id="eqn-epochtimeforyear" aoid="EpochTimeForYear">EpochTimeForYear(_y_) = ℝ(msPerDay) × EpochDayNumberForYear(_y_)</emu-eqn>
<p>Epoch year from time _t_ is given by:</p>
<emu-eqn id="eqn-epochtimetoepochyear" aoid="EpochTimeToEpochYear">EpochTimeToEpochYear(_t_) = the largest integral Number _y_ (closest to +∞) such that EpochTimeForYear(_y_) ≤ _t_</emu-eqn>
<p>The following function returns 1 for a time within leap year otherwise it returns 0:</p>
<emu-eqn id="eqn-mathematicalinleapyear" aoid="MathematicalInLeapYear">
MathematicalInLeapYear(_t_)
= 0 if MathematicalDaysInYear(EpochTimeToEpochYear(_t_)) is 365
= 1 if MathematicalDaysInYear(EpochTimeToEpochYear(_t_)) is 366
</emu-eqn>
Comment on lines +91 to +95
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate seeing this redundancy, but I don't currently have enough time to determine which parts of it are necessary.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the usage of EpochTimeToEpochYear (vs YearFromTime in ECMA-262) makes it necessary, until someone can go through ECMA-262 and prove that using the MV version exclusively would be unobservable. If this turns out to really be redundant, then removing it will by definition be an unobservable change.

<p>The month number for a time _t_ is given by:</p>
<emu-eqn id="eqn-epochtimetomonthinyear" aoid="EpochTimeToMonthInYear">
EpochTimeToMonthInYear(_t_)
= 0 if 0 ≤ EpochTimeToDayInYear(_t_) &lt; 31
= 1 if 31 ≤ EpochTimeToDayInYear(_t_) &lt; 59 + MathematicalInLeapYear(_t_)
= 2 if 59 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 90 + MathematicalInLeapYear(_t_)
= 3 if 90 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 120 + MathematicalInLeapYear(_t_)
= 4 if 120 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 151 + MathematicalInLeapYear(_t_)
= 5 if 151 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 181 + MathematicalInLeapYear(_t_)
= 6 if 181 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 212 + MathematicalInLeapYear(_t_)
= 7 if 212 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 243 + MathematicalInLeapYear(_t_)
= 8 if 243 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 273 + MathematicalInLeapYear(_t_)
= 9 if 273 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 304 + MathematicalInLeapYear(_t_)
= 10 if 304 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 334 + MathematicalInLeapYear(_t_)
= 11 if 334 + MathematicalInLeapYear(_t_) ≤ EpochTimeToDayInYear(_t_) &lt; 365 + MathematicalInLeapYear(_t_)
</emu-eqn>
<p>where</p>
<emu-eqn id="eqn-epochtimetodayinyear" aoid="EpochTimeToDayInYear">EpochTimeToDayInYear(_t_) = EpochTimeToDayNumber(_t_) - EpochDayNumberForYear(EpochTimeToEpochYear(_t_))</emu-eqn>
<p>A month value of 0 specifies January; 1 specifies February; 2 specifies March; 3 specifies April; 4 specifies May; 5 specifies June; 6 specifies July; 7 specifies August; 8 specifies September; 9 specifies October; 10 specifies November; and 11 specifies December. Note that <emu-eqn>EpochTimeToMonthInYear(0) = 0</emu-eqn>, corresponding to Thursday, 1 January 1970.</p>
<p>The date number for a time _t_ is given by:</p>
<emu-eqn id="eqn-epochtimetodate" aoid="EpochTimeToDate">
EpochTimeToDate(_t_)
= EpochTimeToDayInYear(_t_) + 1 if EpochTimeToMonthInYear(_t_) is 0
= EpochTimeToDayInYear(_t_) - 30 if EpochTimeToMonthInYear(_t_) is 1
= EpochTimeToDayInYear(_t_) - 58 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 2
= EpochTimeToDayInYear(_t_) - 89 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 3
= EpochTimeToDayInYear(_t_) - 119 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 4
= EpochTimeToDayInYear(_t_) - 150 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 5
= EpochTimeToDayInYear(_t_) - 180 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 6
= EpochTimeToDayInYear(_t_) - 211 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 7
= EpochTimeToDayInYear(_t_) - 242 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 8
= EpochTimeToDayInYear(_t_) - 272 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 9
= EpochTimeToDayInYear(_t_) - 303 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 10
= EpochTimeToDayInYear(_t_) - 333 - MathematicalInLeapYear(_t_) if EpochTimeToMonthInYear(_t_) is 11
</emu-eqn>
<p>The weekday for a particular time _t_ is defined as:</p>
<emu-eqn id="eqn-epochtimetoweekday" aoid="EpochTimeToWeekDay">EpochTimeToWeekDay(_t_) =(EpochTimeToDayNumber(_t_) + 4) modulo 7</emu-eqn>
<p>A weekday value of 0 specifies Sunday; 1 specifies Monday; 2 specifies Tuesday; 3 specifies Wednesday; 4 specifies Thursday; 5 specifies Friday; and 6 specifies Saturday. Note that <emu-eqn>EpochTimeToWeekDay(0) = 4</emu-eqn>, corresponding to Thursday, 1 January 1970.</p>
<emu-note type="editor"> These equations correspond to ECMA-262 equations defined in <emu-xref href="#sec-year-number">Year Number</emu-xref>, <emu-xref href="#sec-month-number">Month Number</emu-xref>, <emu-xref href="#sec-date-number">Date Number</emu-xref>, <emu-xref href="#sec-week-day">Week Day</emu-xref> respectively. These calculate the result in mathematical values instead of Number values. These equations would be unified when https://github.com/tc39/ecma262/issues/1087 is fixed.</emu-note>
<emu-note type="editor"> Note that the operation EpochTimeToMonthInYear(_t_) uses 0-based months unlike rest of Temporal since it's intended to be unified with MonthFromTime(_t_) when the above mentioned issue is fixed.</emu-note>
</emu-clause>
<!-- Copied from ECMA-402 GetOptionsObject -->
<emu-clause id="sec-getoptionsobject" aoid="GetOptionsObject">
<h1>GetOptionsObject ( _options_ )</h1>
Expand Down
24 changes: 11 additions & 13 deletions spec/calendar.html
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ <h1>
1. If _month_ is 1, 3, 5, 7, 8, 10, or 12, return 31.
1. If _month_ is 4, 6, 9, or 11, return 30.
1. Assert: _month_ is 2.
1. Return 28 + ℝ(InLeapYear(TimeFromYear(𝔽(_year_)))).
1. Return 28 + MathematicalInLeapYear(EpochTimeForYear(_year_)).
</emu-alg>
</emu-clause>

Expand Down Expand Up @@ -794,11 +794,11 @@ <h1>
1. Let _dayOfJan1st_ be ToISODayOfWeek(_year_, 1, 1).
1. If _dayOfJan1st_ is _friday_, then
1. Return the Year-Week Record { [[Week]]: _maxWeekNumber_, [[Year]]: _year_ - 1 }.
1. If _dayOfJan1st_ is _saturday_, and InLeapYear(TimeFromYear(𝔽(_year_ - 1))) is *1*<sub>𝔽</sub>, then
1. If _dayOfJan1st_ is _saturday_, and MathematicalInLeapYear(EpochTimeForYear(_year_ - 1)) is 1, then
1. Return the Year-Week Record { [[Week]]: _maxWeekNumber_. [[Year]]: _year_ - 1 }.
1. Return the Year-Week Record { [[Week]]: _maxWeekNumber_ - 1, [[Year]]: _year_ - 1 }.
1. If _week_ is _maxWeekNumber_, then
1. Let _daysInYear_ be DaysInYear(𝔽(_year_)).
1. Let _daysInYear_ be MathematicalDaysInYear(_year_).
1. Let _daysLaterInYear_ be _daysInYear_ - _dayOfYear_.
1. Let _daysAfterThursday_ be _thursday_ - _dayOfWeek_.
1. If _daysLaterInYear_ &lt; _daysAfterThursday_, then
Expand Down Expand Up @@ -955,9 +955,8 @@ <h1>
</dl>
<emu-alg>
1. Assert: IsValidISODate(_year_, _month_, _day_) is *true*.
1. Let _epochDays_ be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)).
1. Assert: _epochDays_ is finite.
1. Return ℝ(DayWithinYear(MakeDate(_epochDays_, *+0*<sub>𝔽</sub>))) + 1.
1. Let _epochDays_ be ISODateToEpochDays(year, month - 1, day).
1. Return EpochTimeToDayInYear(EpochDaysToEpochMs(_epochDays_, 0)) + 1.
</emu-alg>
</emu-clause>

Expand All @@ -975,11 +974,10 @@ <h1>
</dl>
<emu-alg>
1. Assert: IsValidISODate(_year_, _month_, _day_) is *true*.
1. Let _epochDays_ be MakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day)).
1. Assert: _epochDays_ is finite.
1. Let _dayOfWeek_ be WeekDay(MakeDate(_epochDays_, *+0*<sub>𝔽</sub>)).
1. If _dayOfWeek_ = *+0*<sub>𝔽</sub>, return 7.
1. Return ℝ(_dayOfWeek_).
1. Let _epochDays_ be ISODateToEpochDays(year, month - 1, day).
1. Let _dayOfWeek_ be EpochTimeToWeekDay(EpochDaysToEpochMs(_epochDays_, 0)).
1. If _dayOfWeek_ = 0, return 7.
1. Return _dayOfWeek_.
</emu-alg>
</emu-clause>
</emu-clause>
Expand Down Expand Up @@ -1406,7 +1404,7 @@ <h1>Temporal.Calendar.prototype.daysInYear ( _temporalDateLike_ )</h1>
1. Assert: _calendar_.[[Identifier]] is *"iso8601"*.
1. If Type(_temporalDateLike_) is not Object or _temporalDateLike_ does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
1. Set _temporalDateLike_ to ? ToTemporalDate(_temporalDateLike_).
1. Return DaysInYear(𝔽(_temporalDateLike_.[[ISOYear]])).
1. Return 𝔽(MathematicalDaysInYear(_temporalDateLike_.[[ISOYear]])).
</emu-alg>
</emu-clause>

Expand Down Expand Up @@ -1444,7 +1442,7 @@ <h1>Temporal.Calendar.prototype.inLeapYear ( _temporalDateLike_ )</h1>
1. Assert: _calendar_.[[Identifier]] is *"iso8601"*.
1. If Type(_temporalDateLike_) is not Object or _temporalDateLike_ does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
1. Set _temporalDateLike_ to ? ToTemporalDate(_temporalDateLike_).
1. If InLeapYear(TimeFromYear(𝔽(_temporalDateLike_.[[ISOYear]]))) is *1*<sub>𝔽</sub>, return *true*.
1. If MathematicalInLeapYear(EpochTimeForYear(_temporalDateLike_.[[ISOYear]])) is 1, return *true*.
1. Return *false*.
</emu-alg>
</emu-clause>
Expand Down
8 changes: 3 additions & 5 deletions spec/duration.html
Original file line number Diff line number Diff line change
Expand Up @@ -1572,11 +1572,9 @@ <h1>
If _earlier_ is later than _later_, then the result is negative.</dd>
</dl>
<emu-alg>
1. Let _epochDays1_ be MakeDay(𝔽(_earlier_.[[ISOYear]]), 𝔽(_earlier_.[[ISOMonth]] - 1), 𝔽(_earlier_.[[ISODay]])).
1. Assert: _epochDays1_ is finite.
1. Let _epochDays2_ be MakeDay(𝔽(_later_.[[ISOYear]]), 𝔽(_later_.[[ISOMonth]] - 1), 𝔽(_later_.[[ISODay]])).
1. Assert: _epochDays2_ is finite.
1. Return ℝ(_epochDays2_) - ℝ(_epochDays1_).
1. Let _epochDays1_ be ISODateToEpochDays(_earlier_.[[ISOYear]], _earlier_.[[ISOMonth]] - 1, _earlier_.[[ISODay]]).
1. Let _epochDays2_ be ISODateToEpochDays(_later_.[[ISOYear]], _later_.[[ISOMonth]] - 1, _later_.[[ISODay]]).
1. Return _epochDays2_ - _epochDays1_.
</emu-alg>
</emu-clause>

Expand Down
4 changes: 2 additions & 2 deletions spec/intl.html
Original file line number Diff line number Diff line change
Expand Up @@ -2137,7 +2137,7 @@ <h1>Temporal.Calendar.prototype.daysInYear ( _temporalDateLike_ )</h1>
1. If Type(_temporalDateLike_) is not Object or _temporalDateLike_ does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
1. Set _temporalDateLike_ to ? ToTemporalDate(_temporalDateLike_).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. Return DaysInYear(𝔽(_temporalDateLike_.[[ISOYear]])).
1. Return 𝔽(MathematicalDaysInYear(_temporalDateLike_.[[ISOYear]])).
1. Let _daysInYear_ be ! CalendarDateDaysInYear(_calendar_.[[Identifier]], _temporalDateLike_).
1. Return 𝔽(_daysInYear_).
</emu-alg>
Expand Down Expand Up @@ -2174,7 +2174,7 @@ <h1>Temporal.Calendar.prototype.inLeapYear ( _temporalDateLike_ )</h1>
1. If Type(_temporalDateLike_) is not Object or _temporalDateLike_ does not have an [[InitializedTemporalDate]], [[InitializedTemporalDateTime]], or [[InitializedTemporalYearMonth]] internal slot, then
1. Set _temporalDateLike_ to ? ToTemporalDate(_temporalDateLike_).
1. If _calendar_.[[Identifier]] is *"iso8601"*, then
1. If InLeapYear(TimeFromYear(𝔽(_temporalDateLike_.[[ISOYear]]))) is *1*<sub>𝔽</sub>, then
1. If MathematicalInLeapYear(EpochTimeForYear(_temporalDateLike_.[[ISOYear]])) is 1, then
1. Let _inLeapYear_ be *true*.
1. Else,
1. Let _inLeapYear_ be *false*.
Expand Down
15 changes: 6 additions & 9 deletions spec/plaindate.html
Original file line number Diff line number Diff line change
Expand Up @@ -824,11 +824,9 @@ <h1>
1. Return ! CreateDateDurationRecord(_years_, _months_, 0, _days_).
1. Else,
1. Assert: _largestUnit_ is *"day"* or *"week"*.
1. Let _epochDays1_ be MakeDay(𝔽(_y1_), 𝔽(_m1_ - 1), 𝔽(_d1_)).
1. Assert: _epochDays1_ is finite.
1. Let _epochDays2_ be MakeDay(𝔽(_y2_), 𝔽(_m2_ - 1), 𝔽(_d2_)).
1. Assert: _epochDays2_ is finite.
1. Let _days_ be ℝ(_epochDays2_) - ℝ(_epochDays1_).
1. Let _epochDays1_ be ISODateToEpochDays(_y1_, _m1_ - 1, _d1_).
1. Let _epochDays2_ be ISODateToEpochDays(_y2_, _m2_ - 1, _d2_).
1. Let _days_ be _epochDays2_ - _epochDays1_.
1. Let _weeks_ be 0.
1. If _largestUnit_ is *"week"*, then
1. Set _weeks_ to truncate(_days_ / 7).
Expand Down Expand Up @@ -906,10 +904,9 @@ <h1>BalanceISODate (
</dd>
</dl>
<emu-alg>
1. Let _epochDays_ be MakeDay(𝔽(_year_), 𝔽(_month_ - 1), 𝔽(_day_)).
1. Assert: _epochDays_ is finite.
1. Let _ms_ be MakeDate(_epochDays_, *+0*<sub>𝔽</sub>).
1. Return CreateISODateRecord(ℝ(YearFromTime(_ms_)), ℝ(MonthFromTime(_ms_)) + 1, ℝ(DateFromTime(_ms_))).
1. Let _epochDays_ be ISODateToEpochDays(_year_, _month_ - 1, _day_).
1. Let _ms_ be EpochDaysToEpochMs(_epochDays_, 0).
1. Return CreateISODateRecord(EpochTimeToEpochYear(_ms_), EpochTimeToMonthInYear(_ms_) + 1, EpochTimeToDate(_ms_)).
</emu-alg>
</emu-clause>

Expand Down
6 changes: 3 additions & 3 deletions spec/timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,9 @@ <h1>
1. Assert: ! IsValidEpochNanoseconds(ℤ(_epochNanoseconds_)) is *true*.
1. Let _remainderNs_ be _epochNanoseconds_ modulo 10<sup>6</sup>.
1. Let _epochMilliseconds_ be 𝔽((_epochNanoseconds_ - _remainderNs_) / 10<sup>6</sup>).
1. Let _year_ be ℝ(! YearFromTime(_epochMilliseconds_)).
1. Let _month_ be ℝ(! MonthFromTime(_epochMilliseconds_)) + 1.
1. Let _day_ be ℝ(! DateFromTime(_epochMilliseconds_)).
1. Let _year_ be EpochTimeToEpochYear(_epochMilliseconds_).
1. Let _month_ be EpochTimeToMonthInYear(_epochMilliseconds_) + 1.
1. Let _day_ be EpochTimeToDate(_epochMilliseconds_).
1. Let _hour_ be ℝ(! HourFromTime(_epochMilliseconds_)).
1. Let _minute_ be ℝ(! MinFromTime(_epochMilliseconds_)).
1. Let _second_ be ℝ(! SecFromTime(_epochMilliseconds_)).
Expand Down