Finsternisse eingebaut

This commit is contained in:
Eskimue
2026-04-03 13:41:31 +02:00
parent 81176fb81a
commit 7f796156b2
4 changed files with 474 additions and 2 deletions
Binary file not shown.
+195 -2
View File
@@ -826,6 +826,194 @@ def action_planet_conjunctions_for_month(args: list[str]) -> dict:
}
def eclipse_kind_label(kind: astronomy.EclipseKind) -> str:
if kind == astronomy.EclipseKind.Penumbral:
return "Halbschatten"
if kind == astronomy.EclipseKind.Partial:
return "Partielle"
if kind == astronomy.EclipseKind.Annular:
return "Ringfoermige"
if kind == astronomy.EclipseKind.Total:
return "Totale"
return "Unbekannte"
def serialize_time_only(time_value: astronomy.Time, tz: ZoneInfo) -> dict:
dt_utc = time_to_datetime(time_value)
local_dt = dt_utc.astimezone(tz)
return {
"utc_iso": dt_utc.isoformat().replace("+00:00", "Z"),
"local_iso": local_dt.isoformat(),
"local_date": local_dt.strftime("%d.%m.%Y"),
"local_time": local_dt.strftime("%H:%M"),
}
def action_eclipses_for_month(args: list[str]) -> dict:
if len(args) != 6:
fail(
"Aktion eclipses_for_month erwartet 6 Argumente: latitude longitude elevation year month timezone",
extra={"argv": args},
)
latitude = parse_float(args[0], "Latitude")
longitude = parse_float(args[1], "Longitude")
elevation = parse_float(args[2], "Elevation")
try:
year = int(args[3])
month = int(args[4])
except ValueError as exc:
fail("Jahr oder Monat sind ungueltig.", extra={"details": str(exc), "argv": args})
if month < 1 or month > 12:
fail("Monat muss zwischen 1 und 12 liegen.", extra={"month": month})
timezone_name = args[5]
try:
tz = ZoneInfo(timezone_name)
except Exception as exc:
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
observer = astronomy.Observer(latitude, longitude, elevation)
local_start = datetime(year, month, 1, 0, 0, 0, tzinfo=tz)
if month == 12:
local_end = datetime(year + 1, 1, 1, 0, 0, 0, tzinfo=tz)
else:
local_end = datetime(year, month + 1, 1, 0, 0, 0, tzinfo=tz)
utc_start = local_start.astimezone(timezone.utc)
utc_end = local_end.astimezone(timezone.utc)
scan_start = dt_to_time(utc_start - timedelta(days=40))
events: list[dict] = []
lunar = astronomy.SearchLunarEclipse(scan_start)
while True:
peak_dt_utc = time_to_datetime(lunar.peak)
if peak_dt_utc >= utc_end:
break
local_peak = peak_dt_utc.astimezone(tz)
if local_peak >= local_start:
kind_label = eclipse_kind_label(lunar.kind)
penum_begin = lunar.peak.AddDays(-lunar.sd_penum / 1440.0)
penum_end = lunar.peak.AddDays(+lunar.sd_penum / 1440.0)
events.append({
"category": "lunar_eclipse",
"stage": "peak",
"kind": lunar.kind.name.lower(),
"label": f"{kind_label} Mondfinsternis - Maximum",
**serialize_time_only(lunar.peak, tz),
})
if lunar.sd_penum > 0:
events.append({
"category": "lunar_eclipse",
"stage": "penumbral_begin",
"kind": lunar.kind.name.lower(),
"label": f"{kind_label} Mondfinsternis - Halbschatten beginnt",
**serialize_time_only(penum_begin, tz),
})
events.append({
"category": "lunar_eclipse",
"stage": "penumbral_end",
"kind": lunar.kind.name.lower(),
"label": f"{kind_label} Mondfinsternis - Halbschatten endet",
**serialize_time_only(penum_end, tz),
})
if lunar.sd_partial > 0:
partial_begin = lunar.peak.AddDays(-lunar.sd_partial / 1440.0)
partial_end = lunar.peak.AddDays(+lunar.sd_partial / 1440.0)
events.append({
"category": "lunar_eclipse",
"stage": "partial_begin",
"kind": lunar.kind.name.lower(),
"label": f"{kind_label} Mondfinsternis - Partielle Phase beginnt",
**serialize_time_only(partial_begin, tz),
})
events.append({
"category": "lunar_eclipse",
"stage": "partial_end",
"kind": lunar.kind.name.lower(),
"label": f"{kind_label} Mondfinsternis - Partielle Phase endet",
**serialize_time_only(partial_end, tz),
})
if lunar.sd_total > 0:
total_begin = lunar.peak.AddDays(-lunar.sd_total / 1440.0)
total_end = lunar.peak.AddDays(+lunar.sd_total / 1440.0)
events.append({
"category": "lunar_eclipse",
"stage": "total_begin",
"kind": lunar.kind.name.lower(),
"label": "Totale Mondfinsternis - Totalitaet beginnt",
**serialize_time_only(total_begin, tz),
})
events.append({
"category": "lunar_eclipse",
"stage": "total_end",
"kind": lunar.kind.name.lower(),
"label": "Totale Mondfinsternis - Totalitaet endet",
**serialize_time_only(total_end, tz),
})
lunar = astronomy.NextLunarEclipse(lunar.peak)
solar = astronomy.SearchLocalSolarEclipse(scan_start, observer)
while True:
peak_dt_utc = time_to_datetime(solar.peak.time)
if peak_dt_utc >= utc_end:
break
local_peak = peak_dt_utc.astimezone(tz)
if local_peak >= local_start:
kind_label = eclipse_kind_label(solar.kind)
def solar_event_payload(label: str, event: astronomy.EclipseEvent, stage: str) -> dict:
payload = {
"category": "solar_eclipse",
"stage": stage,
"kind": solar.kind.name.lower(),
"label": label,
"sun_altitude_deg": float(event.altitude),
"above_horizon": float(event.altitude) >= 0.0,
}
payload.update(serialize_time_only(event.time, tz))
return payload
events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Beginn", solar.partial_begin, "partial_begin"))
events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Maximum", solar.peak, "peak"))
if solar.total_begin is not None:
phase_label = "Ringphase beginnt" if solar.kind == astronomy.EclipseKind.Annular else "Totalitaet beginnt"
events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - {phase_label}", solar.total_begin, "central_begin"))
if solar.total_end is not None:
phase_label = "Ringphase endet" if solar.kind == astronomy.EclipseKind.Annular else "Totalitaet endet"
events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - {phase_label}", solar.total_end, "central_end"))
events.append(solar_event_payload(f"{kind_label} Sonnenfinsternis - Ende", solar.partial_end, "partial_end"))
solar = astronomy.NextLocalSolarEclipse(solar.peak.time, observer)
events = [
event for event in events
if local_start <= datetime.fromisoformat(event["local_iso"]) < local_end
]
events.sort(key=lambda item: item["local_iso"])
return {
"ok": True,
"action": "eclipses_for_month",
"selected": {
"year": year,
"month": month,
"timezone": timezone_name,
},
"events": events,
}
def action_moon_star_occultations_for_month(args: list[str]) -> dict:
if len(args) != 7:
fail(
@@ -1882,7 +2070,7 @@ def action_satellite_passes(args: list[str]) -> dict:
def main() -> None:
if len(sys.argv) < 2:
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "moon_star_occultations_for_month"]})
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_star_occultations_for_month"]})
action = sys.argv[1]
args = sys.argv[2:]
@@ -1937,12 +2125,17 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=False))
return
if action == "eclipses_for_month":
result = action_eclipses_for_month(args)
print(json.dumps(result, ensure_ascii=False))
return
if action == "moon_star_occultations_for_month":
result = action_moon_star_occultations_for_month(args)
print(json.dumps(result, ensure_ascii=False))
return
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "moon_star_occultations_for_month"]})
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_star_occultations_for_month"]})
if __name__ == "__main__":