-
Notifications
You must be signed in to change notification settings - Fork 160
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
Editorial: Spec out ToISOWeekOfYear w/ algorithm #2378
Conversation
Also refactor ToISODayOfYear and ToISODayOfWeek.
Codecov Report
@@ Coverage Diff @@
## main #2378 +/- ##
==========================================
- Coverage 95.03% 95.02% -0.01%
==========================================
Files 20 20
Lines 10812 10817 +5
Branches 1927 1929 +2
==========================================
+ Hits 10275 10279 +4
- Misses 503 504 +1
Partials 34 34
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
address #1641 |
Co-authored-by: Jordan Harband <[email protected]>
Co-authored-by: Jordan Harband <[email protected]>
Co-authored-by: Jordan Harband <[email protected]>
@ljharb thanks |
spec/calendar.html
Outdated
1. If _dayOfWeek_ is 0, then | ||
1. Set _dayOfWeek_ to 7. | ||
1. Let _week_ be floor((_dayOfYear_ - _dayOfWeek_ + 10) / 7). | ||
1. If _week_ < 1, then | ||
1. Let _dayOfJan1st_ be ToISODayOfWeek(_year_, 1, 1). | ||
1. If _dayOfJan1st_ is 5, then | ||
1. Return 53. | ||
1. If _dayOfJan1st_ is 6, then | ||
1. Return 52 + ℝ(InLeapYear(TimeFromYear(𝔽(_year_ - 1)))). | ||
1. Return 52. | ||
1. If _week_ is 53, then | ||
1. Let _test_ be InLeapYear(TimeFromYear(𝔽(_year_))) + 365 - _dayOfYear_ - 4 + _dayOfWeek_. | ||
1. If _test_ < 0, then | ||
1. Return 1. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are a lot of magic numbers - can they be placed in named constants?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got them from the polyfill
It is truly a magic number to me. It will be nice if the polyfill author could suggest the name for such constant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment at #1641 (comment)
spec/calendar.html
Outdated
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*<sub>𝔽</sub>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you elaborate on this line? is sunday the last day of the week or the first in ISO?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Monday is 1, Sunday is 7.
however the utility function Temporals dayOfWeek uses the 1..7 ISO values. So step-1 is superfluous. The 10 in step-2 comes from the rule being that week-1 is the week containing the first Thursday of the year. (7days in a full week + 3days before a Thursday). The rest of the constants are just from the Day-enum or actual week-numbers. |
Add const, PTAL |
spec/calendar.html
Outdated
1. If _week_ < 1, then | ||
1. Let _dayOfJan1st_ be ToISODayOfWeek(_year_, 1, 1). | ||
1. If _dayOfJan1st_ is _friday_, then | ||
1. Return 53. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we have some kind of "weeks in a year" constant for 52, and this can be that plus 1?
spec/calendar.html
Outdated
1. If _dayOfWeek_ is 0, then | ||
1. Set _dayOfWeek_ to _saturday_. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems confusing to me; it would be clearer to explicitly map the entire 0-6 range to 1-7 mod 7 (also isn't this one supposed to be sunday, not saturday?)
Sorry, the latest changes are very wrong, so I have not been nearly as clear as I hoped. Alas I’m on my phone right now and therefor typing impaired. Can I come back to you both tomorrow with a clearer algorithm spec. |
Week of Year Algorithm
|
Steps 3-5 there seem like they’d make a very helpful separate AO to encapsulate that validation. It’s still a bit confusing why specific days (January 5th, 6th, etc) are magic values. |
For steps 3–5 we have IsValidISODate |
The formula in step 12 has as a consequence that the week is only smaller than 1 if January 1st is either Friday, Saturday or Sunday. In any of those cases the week number is the last one of the previous year. So it’s just a question of which one that is. (Note: I also corrected the algorithm because it had an error in that section by referring to jan5 & jan6) |
sorry, I accidentally click the wrong key |
It would be a good idea to explain with reference to ISO 8601-1:2019 section 3.1.1.23 week calendar:
Note that this supports rather comprehensible algorithms—ISO week 01 of every calendar year includes its January 4 and starts on the first Monday on or before that, the ISO week calendar year of any date is its calendar year adjusted by -1 if it precedes that Monday or by +1 if it falls on or after that Monday of week 01 for the next calendar year, and the ISO week number of any date is 1 plus the number of complete weeks from the start of its week calendar week 01 (e.g., Or alternatively, the algorithms can use lookups against compiled data such as the table at https://en.wikipedia.org/wiki/ISO_week_date#First_week . |
fix linter error, PTAL |
spec/calendar.html
Outdated
1. Let _week_ be floor((_dayOfYear_ - (_daysInWeek_ - _dayOfWeek_ + _wednesday_ )) / _daysInWeek_). | ||
1. If _week_ < 1, then | ||
1. NOTE: This is the last week of the previous year. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This formula seems to be incorrect. Consider 2023-01-02, which is the Monday at the start of 2023-W01: https://www.timeanddate.com/calendar/monthly.html?year=2023&month=1&country=9
- Let dayOfYear be ToISODayOfYear(year, month, day). → 2
- Let dayOfWeek be ToISODayOfWeek(year, month, day). → 1
- Let week be floor((dayOfYear - (daysInWeek - dayOfWeek + wednesday )) / daysInWeek) → floor((2 - (7 - 1 + 3 )) / 7) → floor(-1) → -1
- If week < 1, then
- NOTE: This is the last week of the previous year.
Which is an inaccurate classification of the input date.
Co-authored-by: Richard Gibson <[email protected]>
Co-authored-by: Richard Gibson <[email protected]>
Co-authored-by: Richard Gibson <[email protected]>
Co-authored-by: Richard Gibson <[email protected]>
Should this be
|
Polyfill code is
instead |
2023-01-02 then will be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The algorithm is a bit opaque as compared to something based on #2378 (comment) such as
1. Let _weekCalendarYear_ be _year_.
1. Let _jan4DayOfWeek_ be ToISODayOfWeek(_weekCalendarYear_, 1, 4).
1. Let _week01StartDayOfYear_ be 4 - _jan4DayOfWeek_ + 1.
1. NOTE: If _week01StartDayOfYear_ is less than 1, then the week calendar year starts in the last few calendar days of calendar year _year_ - 1.
1. Let _dayOfYear_ be ToISODayOfYear(_year_, _month_, _day_).
1. If _dayOfYear_ ≥ 363, then
1. Let _dayOfWeek_ be ToISODayOfWeek(_year_, _month_, _day_).
1. Let _daysUntilThisWeekThursday_ be 4 - _dayOfWeek_.
1. If _daysUntilThisWeekThursday_ > 0 and (_dayOfYear_ + _daysUntilThisWeekThursday_) > DaysInYear(𝔽(_weekCalendarYear_)), then
1. NOTE: The upcoming Thursday is in the next calendar year, so the entire containing week is the first week of that week calendar year.
1. Return 1.
1. If _dayOfYear_ < _week01StartDayOfYear_, then
1. NOTE: The date belongs to the last week of the previous week calendar year.
1. Set _weekCalendarYear_ to _year_ - 1.
1. Set _jan4DayOfWeek_ to ToISODayOfWeek(_weekCalendarYear_, 1, 4).
1. Set _week01StartDayOfYear_ to 4 - _jan4DayOfWeek_ + 1.
1. Set _dayOfYear_ to DaysInYear(𝔽(_weekCalendarYear_)) + _dayOfYear_.
1. Assert: _dayOfYear_ ≥ _week01StartDayOfYear_.
1. Let _daysSinceStart_ be _dayOfYear_ - _week01StartDayOfYear_.
1. Return 1 + floor(_daysSinceStart_ / 7).
Regardless, it seems correct to me.
Can we got all approved and merge this PR ASAP? Thanks |
@ljharb any other comments? |
That is because I changed the PR to follow #2378 (comment) |
I still find the algorithm a bit inscrutable due to the use of arbitrary days of the week, but it seems correct enough. |
the v8 implementation sync to this could be found in https://chromium-review.googlesource.com/c/v8/v8/+/3531567 Adam expressed he prefer we finalize the algorithm in spec text before he continue the review so this PR is blocking the merge of that. |
I'm OK with merging this as it's blocking the V8 implementation. (However skeptical I am that it lends any extra correctness to the V8 implementation to have this finalized first, since we are just pulling in an algorithm from somewhere else too.) I didn't double-check the most recent change from subtraction to addition in the algorithm, but I trust that @gibson042 did. Thanks, @FrankYFTang for putting this together. |
Also add AO: ToISOWeekOfYear Spec Text: https://tc39.es/proposal-temporal/#sec-temporal.calendar.prototype.weekofyear https://tc39.es/proposal-temporal/#sec-temporal-toisoweekofyear Note- this is only the non-intl version. intl version in https://tc39.es/proposal-temporal/#sup-temporal.calendar.prototype.weekofyear will be implemented in later cl. PR tc39/proposal-temporal#2378 Sync spec text for ToISODayOfYear and ToISODayOfWeek in the comment and add DCHECK for assertion. Bug: v8:11544 Change-Id: If07ff76551707d17d125e41bc624c12da6efa45a Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3531567 Commit-Queue: Frank Tang <[email protected]> Reviewed-by: Shu-yu Guo <[email protected]> Cr-Commit-Position: refs/heads/main@{#82733}
Also refactor ToISODayOfYear and ToISODayOfWeek.
@ptomato Based on algorithm in https://github.com/tc39/proposal-temporal/blob/main/polyfill/lib/ecmascript.mjs#L2387