Finds the most recent full moon (within 35 days), prints illumination, phase angle, alt/az, and parallactic angle, then calls sun_events_in_range() for the surrounding day. The sun_events call is the direct regression path for the sunrise_sunset() observer fix (bare topos, not earth+topos). https://claude.ai/code/session_01JieSeNQZ3X6fhsb11YyJrK
67 lines
2.1 KiB
Python
67 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""test_last_full_moon.py — smoke-test moon_phase.py against the most recent full moon.
|
|
|
|
Exercises:
|
|
- full_moons_in_range() — phase detection
|
|
- sun_events_in_range() — sunrise/sunset almanac (requires bare topos, not earth+topos)
|
|
- illumination() / altaz() / parallactic_angle()
|
|
|
|
Run from the sky-cam directory:
|
|
|
|
python3 test_last_full_moon.py
|
|
"""
|
|
|
|
import sys
|
|
import pathlib
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
HERE = pathlib.Path(__file__).resolve().parent
|
|
sys.path.insert(0, str(HERE))
|
|
|
|
import moon_phase as mp
|
|
|
|
|
|
def main() -> int:
|
|
now = datetime.now(timezone.utc)
|
|
|
|
# Last full moon: search back up to 35 days
|
|
candidates = mp.full_moons_in_range(now - timedelta(days=35), now)
|
|
if not candidates:
|
|
print("ERROR: no full moon found in the last 35 days", file=sys.stderr)
|
|
return 1
|
|
fm = candidates[-1]
|
|
|
|
print(f"last full moon (UTC) : {fm.strftime('%Y-%m-%dT%H:%M:%SZ')}")
|
|
print(f"local : {mp._format_local(fm)}")
|
|
|
|
# Moon stats at exact full moon moment
|
|
illum = mp.illumination(fm)
|
|
pa = mp.phase_angle(fm)
|
|
alt, az = mp.altaz(fm)
|
|
para = mp.parallactic_angle(fm)
|
|
print(f"illumination : {illum:.4f} ({illum*100:.1f}%)")
|
|
print(f"phase angle : {pa:.2f}° (0° = full)")
|
|
print(f"altitude / azimuth : {alt:.2f}° / {az:.2f}°")
|
|
print(f"parallactic angle : {para:.2f}°")
|
|
print()
|
|
|
|
# Sunrise/sunset for the 24-hour window around the full moon — exercises the fix
|
|
day_start = fm.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
day_end = day_start + timedelta(days=1)
|
|
events = mp.sun_events_in_range(day_start, day_end)
|
|
if events:
|
|
print(f"sun events on {day_start.strftime('%Y-%m-%d')} (UTC):")
|
|
for t, is_rise in events:
|
|
label = "sunrise" if is_rise else "sunset "
|
|
print(f" {label} {t.strftime('%H:%M:%S')} UTC ({mp._format_local(t)})")
|
|
else:
|
|
print(f"no sun events found on {day_start.strftime('%Y-%m-%d')} (polar location?)")
|
|
|
|
print()
|
|
print("OK")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|