Sommer Winterzeit drin

This commit is contained in:
Eskimue
2026-04-03 16:25:37 +02:00
parent 4f1c06f863
commit 91f92b814a
3 changed files with 254 additions and 2 deletions
+92 -2
View File
@@ -650,6 +650,91 @@ def action_season_changes_for_month(args: list[str]) -> dict:
}
def action_time_changes_for_month(args: list[str]) -> dict:
if len(args) != 3:
fail(
"Aktion time_changes_for_month erwartet 3 Argumente: year month timezone",
extra={"argv": args},
)
try:
year = int(args[0])
month = int(args[1])
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[2]
try:
tz = ZoneInfo(timezone_name)
except Exception as exc:
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
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) - timedelta(days=2)
utc_end = local_end.astimezone(timezone.utc) + timedelta(days=2)
def utc_offset_seconds(dt_utc: datetime) -> int:
return int(dt_utc.astimezone(tz).utcoffset().total_seconds())
def refine_transition(left_utc: datetime, right_utc: datetime) -> datetime:
left = left_utc
right = right_utc
left_offset = utc_offset_seconds(left)
while (right - left) > timedelta(seconds=1):
mid = left + (right - left) / 2
if utc_offset_seconds(mid) == left_offset:
left = mid
else:
right = mid
return right
events = []
previous_utc = utc_start
previous_offset = utc_offset_seconds(previous_utc)
current_utc = previous_utc + timedelta(hours=1)
while current_utc <= utc_end:
current_offset = utc_offset_seconds(current_utc)
if current_offset != previous_offset:
transition_utc = refine_transition(previous_utc, current_utc)
local_dt = transition_utc.astimezone(tz)
if local_dt.year == year and local_dt.month == month:
delta_seconds = current_offset - previous_offset
kind = "dst_start" if delta_seconds > 0 else "dst_end"
events.append({
"kind": kind,
"offset_before_hours": previous_offset / 3600.0,
"offset_after_hours": current_offset / 3600.0,
"utc_iso": transition_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"),
})
previous_utc = current_utc
previous_offset = current_offset
current_utc += timedelta(hours=1)
events.sort(key=lambda item: item["local_iso"])
return {
"ok": True,
"action": "time_changes_for_month",
"selected": {
"year": year,
"month": month,
"timezone": timezone_name,
},
"events": events,
}
def moon_planet_separation_deg(
body: astronomy.Body,
observer: astronomy.Observer,
@@ -2702,7 +2787,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", "golden_handle_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_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", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "moon_star_occultations_for_month"]})
action = sys.argv[1]
args = sys.argv[2:]
@@ -2722,6 +2807,11 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=False))
return
if action == "time_changes_for_month":
result = action_time_changes_for_month(args)
print(json.dumps(result, ensure_ascii=False))
return
if action == "moon_phase_details":
result = action_moon_phase_details(args)
print(json.dumps(result, ensure_ascii=False))
@@ -2802,7 +2892,7 @@ def main() -> None:
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", "golden_handle_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_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", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "moon_star_occultations_for_month"]})
if __name__ == "__main__":