Repository navigation
Keep polar sunrises and sunsets near the date line on their own date - #296
Merged
Merged
Conversation
getInstantFromTime receives the event's UTC time folded into [0, 24) and picks its date from the local mean time. It moved a sunrise after 18:00 back a day and a sunset before 06:00 forward a day, but not the other way. Just west of the date line, a sunrise near local noon has a UTC time just past 24:00. It folds to just past 00:00 and was placed a day early. East of the date line a sunset near local noon could fold the other way and land a day late. This happens in polar winter and summer, when sunrise and sunset are close to noon. A sunrise at -6 hours local mean time or earlier now moves forward a day, and a sunset at +30 hours or later moves back a day. The date mapping then matches the window each date's sunrise (18:00 the evening before through 18:00) and sunset (06:00 through 06:00 the next morning) belong to.
One test per branch, each with a real place and date that takes it: a sunrise after 18:00 local mean time, a sunset before 06:00 or at +30 hours or later, solar midnight before noon, and solar noon before 0 or after 24 hours local mean time. The existing date-line sunrise test covers a sunrise at -6 hours or earlier. Each test pins the instant to within a second, so a result on the wrong day fails. Disabling any one branch makes its own test fail.
The comment now says why the UTC time of day alone doesn't give the date, what window of local mean time each event belongs to, and why each check moves the date, with an example of the wrap just west of the date line.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Near the date line, in polar winter or summer,
getSunriseandgetSunsetcan return a time on the wrong day, and every zman built on them goes wrong with it.At Cape Schmidt, Chukotka (68.88, -179.37,
Asia/Anadyr) on 10 January 2021, the sun is up for about ten minutes around noon. All three calculators return a sea-level sunrise of 2021-01-09 12:00:23 local time, a day early. Sunset correctly comes back as 2021-01-10 12:09:57, so the "day" runs for more than 24 hours.getSofZmanShmaGRAthen comes out as 2021-01-09 18:02:47 instead of about 12:02 on the 10th.Why
getInstantFromTimegets the event's UTC time folded into [0, 24) and picks the date from the local mean time. It moves a sunrise after 18:00 back a day and a sunset before 06:00 forward a day, but it never handles the opposite wrap.Just west of the date line, a sunrise near local noon has a true UTC time just past 24:00. It folds to just past 00:00 and lands a day early. Just east of the line, a sunset near local noon can fold the other way and land a day late.
The fix
A sunrise at -6 hours local mean time or earlier now moves forward a day, and a sunset at +30 hours or later moves back a day. The mapping then matches the window each date's events belong to. A sunrise belongs from 18:00 the evening before through 18:00, and a sunset from 06:00 through 06:00 the next morning. Ordinary days never reach those values, so their times don't change.
The comment above the checks now explains each one in plain words, with an example of the wrap just west of the date line.
Testing
AstronomicalCalendarTest.polarSunriseNearTheDateLineIsOnItsOwnDatechecks Cape Schmidt on 10 January 2021 with the NOAA, Meeus and SPA calculators. It fails without the fix ("expected 2021-01-10 but was 2021-01-09") and passes with it.getInstantFromTimenow has its own test, each with a real place and date that takes it. There's a sunrise after 18:00 local mean time, a sunset before 06:00 or at +30 hours or later, solar midnight before noon, and solar noon before 0 or after 24 hours. The date-line sunrise test above covers a sunrise at -6 hours or earlier. Each test pins the instant to within a second, so a result on the wrong day fails. Disabling any one branch makes its own test fail.