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

Date time operations cleanup #1

Closed
wants to merge 6 commits into from
Closed
Changes from 1 commit
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
34 changes: 26 additions & 8 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -32060,7 +32060,23 @@ <h1>Year Number</h1>

Copy link

Choose a reason for hiding this comment

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

In how far is this commit ("Normative: Use Number arithmetic for constructing dates and times") still normative? Now that the version of ECMA-262 this PR is based on is already clarified to use Number arithmetic.

I guess my doubt would be about the changes to MakeDay. If we consider that currently "underspecified" then maybe it's not normative. (I haven't gone through the new definition with the various examples given in tc39#1087, though.)

If the MakeDay changes are normative, on the other hand, then I'd recommend splitting them out of this commit into a separate one, so that it's immediately clear to reviewers what they have to pay the most attention to.

<emu-clause id="sec-month-number">
<h1>Month Number</h1>
<p>Months are identified by an integral Number in the inclusive interval from *+0*<sub>𝔽</sub> to *11*<sub>𝔽</sub>. The mapping MonthFromTime(_t_) from a time value _t_ to a month number is defined by:</p>
<p>Months are identified by an integer in the range 0 to 11, inclusive. 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.</p>
<p>The position of a month _m_ within a year depends upon whether or not the year is a leap year:</p>
<emu-eqn id="eqn-DaysWithinYearBeforeMonth" aoid="DaysWithinYearBeforeMonth">DaysWithinYearBeforeMonth(_m_, _inLeapYear_)
= *+0*<sub>𝔽</sub> if _m_ = 0
= *31*<sub>𝔽</sub> if _m_ = 1
= *59*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 2
= *90*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 3
Copy link

Choose a reason for hiding this comment

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

I'd recommend updating this definition to use a structured header with types so that you get the standard prose. (although I hope it's still possible to specify oldids on a structured header?)

= *120*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 4
= *151*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 5
= *181*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 6
= *212*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 7
Copy link

Choose a reason for hiding this comment

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

month is a Number here but later on it's treated as a mathematical value (MV 1 is added to it and it's passed to DaysWithinYearBeforeMonth which takes a MV). So, it should either be consistently a Number or consistently a MV.

I'm not sure which. MV seemed most in line with the definition of a month number in "Months are identified..." above, but on the other hand the result of MonthFromTime is returned directly to JS in some places, like Date.prototype.getMonth, and so those places would have to be passed through 𝔽. (For precision or overflow purposes it doesn't matter which one we choose, since it's always exactly 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, or 11.)

= *243*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 8
= *273*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 9
= *304*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 10
= *334*<sub>𝔽</sub> + _inLeapYear_ if _m_ = 11
</emu-eqn>
<p>The mapping MonthFromTime(_t_) from a time value _t_ to a month number is defined by:</p>
<emu-eqn id="eqn-MonthFromTime" aoid="MonthFromTime">
MonthFromTime(_t_)
= *+0*<sub>𝔽</sub> if *+0*<sub>𝔽</sub> &le; DayWithinYear(_t_) &lt; *31*<sub>𝔽</sub>
Copy link

Choose a reason for hiding this comment

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

Double-check the types here — I think this might be MonthFromTime(*+0*<sub>𝔽</sub>) = 0 (also taking into account the above comment about the return type of MonthFromTime)

Expand All @@ -32078,7 +32094,7 @@ <h1>Month Number</h1>
</emu-eqn>
<p>where</p>
<emu-eqn id="eqn-DayWithinYear" aoid="DayWithinYear">DayWithinYear(_t_) = Day(_t_) - DayFromYear(YearFromTime(_t_))</emu-eqn>
<p>A month value of *+0*<sub>𝔽</sub> specifies January; *1*<sub>𝔽</sub> specifies February; *2*<sub>𝔽</sub> specifies March; *3*<sub>𝔽</sub> specifies April; *4*<sub>𝔽</sub> specifies May; *5*<sub>𝔽</sub> specifies June; *6*<sub>𝔽</sub> specifies July; *7*<sub>𝔽</sub> specifies August; *8*<sub>𝔽</sub> specifies September; *9*<sub>𝔽</sub> specifies October; *10*<sub>𝔽</sub> specifies November; and *11*<sub>𝔽</sub> specifies December. Note that <emu-eqn>MonthFromTime(*+0*<sub>𝔽</sub>) = *+0*<sub>𝔽</sub></emu-eqn>, corresponding to Thursday, 1 January 1970.</p>
<p>Note that <emu-eqn>MonthFromTime(0) = 0</emu-eqn>, corresponding to Thursday, 01 January, 1970.</p>
</emu-clause>

<emu-clause id="sec-date-number">
Expand Down Expand Up @@ -32358,12 +32374,14 @@ <h1>
1. If _year_ is not finite or _month_ is not finite or _date_ is not finite, return *NaN*.
1. Let _y_ be 𝔽(! ToIntegerOrInfinity(_year_)).
1. Let _m_ be 𝔽(! ToIntegerOrInfinity(_month_)).
1. Let _dt_ be 𝔽(! ToIntegerOrInfinity(_date_)).
1. Let _ym_ be _y_ + 𝔽(floor(ℝ(_m_) / 12)).
1. If _ym_ is not finite, return *NaN*.
1. Let _mn_ be 𝔽(ℝ(_m_) modulo 12).
1. Find a finite time value _t_ such that YearFromTime(_t_) is _ym_ and MonthFromTime(_t_) is _mn_ and DateFromTime(_t_) is *1*<sub>𝔽</sub>; but if this is not possible (because some argument is out of range), return *NaN*.
1. Return Day(_t_) + _dt_ - *1*<sub>𝔽</sub>.
1. Let _d_ be 𝔽(! ToIntegerOrInfinity(_date_)).
1. Let _wholeYears_ be _y_ + 𝔽(floor(ℝ(_m_) / 12)).
1. If _wholeYears_ is not finite, return *NaN*.
1. Let _monthWithinYear_ be 𝔽(ℝ(_m_) modulo 12).
1. Let _inLeapYear_ be InLeapYear(TimeFromYear(_wholeYears_)).
1. Let _day_ be DayFromYear(_wholeYears_) + DaysWithinYearBeforeMonth(_monthWithinYear_, _inLeapYear_) *1*<sub>𝔽</sub>.
1. If _day_ is not finite, return *NaN*.
1. Return _day_.
</emu-alg>
</emu-clause>

Expand Down