Use real sunset/sunrise for dark window; pick frame closest to exact phase

moon_phase.py: add sun_events_in_range() — returns actual sunset/sunrise
transitions via skyfield almanac, accurate to within a minute

moon_phase_monthly.py:
- _dark_moon_intervals(): replace sun-altitude threshold sampling with
  actual sunset/sunrise times; dark window = sunset + DARK_START_MIN to
  next sunrise; moon-above-horizon check still sampled every 10 min within
  each night; polar fallback if no sun events found
- run_phase(): sort dark-window frames by proximity to exact phase moment
  before scanning; first clear detection = the frame temporally closest to
  the moon being precisely full/at quarter, not just the first in time order
- Replace DARK_SKY_SUN_ALT_DEG with DARK_START_MIN (default 30 min)

sky-cam.conf: replace MOON_DARK_SKY_SUN_ALT_DEG with MOON_DARK_START_MIN=30;
update comments to explain ±24h window, sunset+30 start, closest-frame logic,
and how the 01:30 and 23:55 edge cases are handled

https://claude.ai/code/session_01HkTxpNSTWtViZzxbrbKytR
This commit is contained in:
Claude
2026-05-01 22:38:04 +00:00
parent 3fc77ab75e
commit 975c9cc2eb
3 changed files with 107 additions and 43 deletions
+17
View File
@@ -179,6 +179,23 @@ def altaz(when: datetime, lat: float | None = None, lon: float | None = None):
return float(alt.degrees), float(az.degrees)
def sun_events_in_range(
search_start: datetime,
search_end: datetime,
) -> list[tuple[datetime, bool]]:
"""Return every sunrise/sunset transition between search_start and search_end.
Each item is (utc_datetime, is_rise): is_rise=True for sunrise, False for sunset.
Uses skyfield's almanac — accurate to within a minute at the configured location.
"""
_lazy()
from skyfield.almanac import find_discrete, sunrise_sunset
t0 = _t(search_start)
t1 = _t(search_end)
times, values = find_discrete(t0, t1, sunrise_sunset(_eph, _observer))
return [(t.utc_datetime(), bool(v)) for t, v in zip(times, values)]
def sun_altaz(when: datetime, lat: float | None = None, lon: float | None = None):
"""Apparent altitude/azimuth of the sun in degrees as seen from (lat, lon)."""
_lazy()