Skip to content

fix: sunrise/sunset times being identical when Phase 3 convergence ends below threshold - #241

Merged
rt-bishop merged 1 commit into
rt-bishop:mainfrom
atsunatsu:fix/sunrise-sunset-convergence
Aug 19, 2026
Merged

fix: sunrise/sunset times being identical when Phase 3 convergence ends below threshold#241
rt-bishop merged 1 commit into
rt-bishop:mainfrom
atsunatsu:fix/sunrise-sunset-convergence

Conversation

@atsunatsu

Copy link
Copy Markdown
Contributor

Bug description

The findSunRiseSet algorithm sometimes returns identical sunrise and sunset times. This happens when Phase 3 converges to an elevation slightly below the -0.8333 deg threshold (e.g. -0.838 deg instead of -0.8333 deg). Phase 4's sunPos.elevation > -threshold check fails immediately, skipping the sunset search, and Phase 5 converges to the same point.

Root cause

Phase 2 uses a coarse step (0.008 daynum approx 11.5 min) to find the approximate sunrise point, jumping from below-threshold to well above it. Phase 3 then converges by symmetric stepping, but the step size 0.004 * delta causes the final elevation to land below threshold in about 30% of cases.

Fix

Start Phase 4 from daynum = sunrise + 0.001 (~1.4 minutes after sunrise), ensuring the sun is clearly above the threshold before the sunset search begins. This is a deterministic fix - the bug was reproducible 100% of the time for locations like the equator at equinox.

Reproduction

Call CelestialComputer.findSunRiseSet(GeoPos(0.0, 0.0), any time on March 20 or September 23). The sunrise and sunset times will be identical.

Verification

Tested with a Python port of the algorithm against 52 location/date combinations. The fix resolves all cases where sunrise/sunset were identical without affecting the remaining cases.

@rt-bishop

Copy link
Copy Markdown
Owner

Hey there! Only managed to get to this today.

The change makes sense, although ideally I'd prefer to see some unit tests added with those various locations you mentioned. That would protect the functionality against potential breaks in the future and also make this PR much more useful/complete.

…gence ends below threshold

The findSunRiseSet algorithm's Phase 3 converges on the sunrise elevation
using a symmetric stepping approach. Due to the convergence step size,
the final elevation can land slightly below the -0.8333° threshold (e.g.
-0.838° instead of -0.8333°). When this happens, Phase 4's while-loop
condition (sunPos.elevation > -threshold) evaluates to false immediately,
causing it to skip entirely. Phase 5 then converges to the same point,
producing identical sunrise and sunset times.

The fix adds a small offset (daynum = sunrise + 0.001, ~1.4 minutes) at
the start of Phase 4, ensuring the sun is clearly above the threshold
before the sunset search begins. This is a deterministic fix — the bug
was reproducible 100% of the time for any location where the convergence
lands below threshold (e.g. equator at equinox).

Fixes: sunrise/sunset showing identical times (~30% of location/date combinations)
@atsunatsu
atsunatsu force-pushed the fix/sunrise-sunset-convergence branch from 5a23bcf to 9971f4c Compare August 19, 2026 12:41
@atsunatsu

Copy link
Copy Markdown
Contributor Author

Thanks! I added JVM unit tests covering equinox regression cases plus representative southern/northern hemisphere locations, and verified with ./gradlew :core:domain:test --rerun-tasks --no-daemon.

@rt-bishop rt-bishop left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Yay, that's much better! Thanks for doing it so quickly =)

@rt-bishop
rt-bishop merged commit a42a5f1 into rt-bishop:main Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants