-
Notifications
You must be signed in to change notification settings - Fork 149
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
ZonedDateTime hoursInDay, startOfDay, round, add, subtract #1103
Conversation
Co-authored-by: Justin Grant <justingrant@users.noreply.github.com> See: #569
Co-authored-by: Justin Grant <justingrant@users.noreply.github.com> See: #569
Note this implementation is incorrect for rounding to the nearest day on days where a DST transition takes place. This case will be handled correctly when we implement ZonedDateTime difference algorithms for since() and until(). There are two tests dealing with these cases which are skipped for the time being. Co-authored-by: Justin Grant <justingrant@users.noreply.github.com> See: #569
This operation will be reused in ZonedDateTime.add() and subtract() as well. See: #569
The message is no longer accurate, since ZonedDateTime itself has landed already. Change it to say which methods are as yet unimplemented.
Codecov Report
@@ Coverage Diff @@
## main #1103 +/- ##
==========================================
- Coverage 93.55% 90.16% -3.39%
==========================================
Files 19 17 -2
Lines 7961 8178 +217
Branches 1264 1182 -82
==========================================
- Hits 7448 7374 -74
- Misses 506 794 +288
- Partials 7 10 +3
Flags with carried forward coverage won't be shown. Click here to find out more. Continue to review full report at Codecov.
|
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.
Looks great. It's so cool to see ZDT coming alive! I made a few minor suggestions and notes. Nothing major.
const timeZone = GetSlot(this, TIME_ZONE); | ||
const todayNs = GetSlot(ES.GetTemporalInstantFor(timeZone, today, 'compatible'), EPOCHNANOSECONDS); | ||
const tomorrowNs = GetSlot(ES.GetTemporalInstantFor(timeZone, tomorrow, 'compatible'), EPOCHNANOSECONDS); | ||
let { seconds, milliseconds, microseconds, nanoseconds } = ES.DifferenceInstant( |
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.
Why is all the code below here needed? Could it be replaced with something like this?
return Number(tomorrowNs - todayNs) / 3.6e12;
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.
Or is there some non-ISO time calendar reason to want to do it the way you did?
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.
Good point. We still do need to calculate the quotient and remainder separately because BigInt division is integer division, but this can be simplified a lot.
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.
Why not just convert the difference to a Number
and then use floating-point Number
math? If a "day" is longer than 140 24-hour days, some precision loss seems OK. ;-)
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.
In the spec text, the epoch nanoseconds are mathematical values (ℝ values) so you have to be explicit about when you convert them to Number values, my guess is that this is the cleanest way.
const timeZone = GetSlot(this, TIME_ZONE); | ||
const offsetNs = ES.GetOffsetNanosecondsFor(timeZone, GetSlot(this, INSTANT)); | ||
|
||
// See the 'prefer' algorithm in ToTemporalZonedDateTime |
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 don't fully follow this logic here, but as long as tests pass I assume it's fine.
|
||
// RFC 5545 requires the date portion to be added in calendar days and the | ||
// time portion to be added in exact time. | ||
// FIXME: "op" and the dateAdd/dateSubtract conditional will not be needed |
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 comment doesn't match the code below. What conditional?
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.
Sorry, left over from a previous version where I was trying to keep both AddZonedDateTime and SubtractZonedDateTime consolidated into one function. I'll remove this.
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.
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.
BTW, I'm hoping to finish the #993 fix today. Tomorrow at latest.
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.
There is still a note about #993 in SubtractZonedDateTime, so that should be fine.
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.
Thanks for the careful review, @justingrant. It seems like none of your/my comments particularly justify holding this up, so I'll merge now, and let @ptomato deal with them in the next PR.
1. Let _isoCalendar_ be ? GetISO8601Calendar(). | ||
1. Let _today_ be ? CreateTemporalDateTime(_year_, _month_, _day_, 0, 0, 0, 0, 0, 0, _isoCalendar_). | ||
1. Let _tomorrowFields_ be ? AddDate(_year_, _month_, _day_, 0, 0, 0, 1, *"reject"*). | ||
1. Let _tomorrow_ be ? CreateTemporalDateTime(_tomorrowFields_.[[ISOYear]], _tomorrowFields_.[[ISOMonth]], _tomorrowFields_.[[ISODay]], 0, 0, 0, 0, 0, 0, _isoCalendar_). |
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.
Check if tomorrowFields's fields start with ISO
1. Let _rounded_ be ? CreateTemporalDateTime(_roundResult_.[[Year]], _roundResult_.[[Month]], _roundResult_.[[Day]], _roundResult_.[[Hour]], _roundResult_.[[Minute]], _roundResult_.[[Second]], _roundResult_.[[Millisecond]], _roundResult_.[[Microsecond]], _roundResult_.[[Nanosecond]], _calendar_). | ||
1. Let _offsetNanoseconds_ be ? GetOffsetNanosecondsFor(_timeZone_, _instant_). | ||
1. Let _possibleInstants_ be ? GetPossibleInstantsFor(_timeZone_, _rounded_). | ||
1. If there exists an element _candidate_ of _possibleInstants_ for which ? GetOffsetNanosecondsFor(_timeZone_, _candidate_) = _offsetNanoseconds_, then |
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.
Should make the order of operations explicit, since all the GetOffsetNanosecondsFor calls are observable
Thanks for the reviews, I've got fixes for all of these on my next branch. |
See: #569