import math from pytz import timezone from datetime import datetime from datetime import timedelta def next_full_moon(start): # date of the known full moon y2k = datetime(1999, 12, 22, 18, 31, 18).astimezone( timezone('Europe/Berlin')) since2000 = (start - y2k) / timedelta(days=365.25) rads = 3.14159265359/180 phase = 0.5 # 0.5 equals full moon # Anzahl der Mondphasen seit 2000 k = math.floor((since2000)*12.36853087)+phase # Mittlerer JDE Wert des Ereignisses JDE = 2451550.09766+29.530588861*k # Relevante Winkelwerte in [Radiant] M = (2.5534+29.10535670*k)*rads Ms = (201.5643+385.81693528*k)*rads F = (160.7108+390.67050284*k)*rads # Korrekturterme JDE fuer Vollmond JDE += -0.40614*math.sin(Ms) JDE += 0.17302*math.sin(M) JDE += 0.01614*math.sin(2*Ms) JDE += 0.01043*math.sin(2*F) JDE += 0.00734*math.sin(Ms-M) JDE += -0.00515*math.sin(Ms+M) JDE += 0.00209*math.sin(2*M) JDE += -0.00111*math.sin(Ms-2*F) # Konvertierung von Julianischem Datum auf Gregorianisches Datum z = math.floor(JDE + 0.5) f = (JDE + 0.5) - math.floor(JDE + 0.5) if (z < 2299161): a = z else: g = math.floor((z - 1867216.25) / 36524.25) a = z + 1 + g - math.floor(g / 4) b = a + 1524 c = math.floor((b - 122.1) / 365.25) d = math.floor(365.25 * c) e = math.floor((b - d) / 30.6001) # //Tag incl. Tagesbruchteilen tag_temp = b - d - math.floor(30.6001 * e) + f stunde_temp = (tag_temp - math.floor(tag_temp)) * 24 minute_temp = (stunde_temp - math.floor(stunde_temp)) * 60 stunde = math.floor(stunde_temp) minute = math.floor(minute_temp) sekunde = round((minute_temp - math.floor(minute_temp)) * 60) tag = math.floor(tag_temp) if (e < 14): monat = e - 1 else: monat = e - 13 if (monat > 2): jahr = c - 4716 else: jahr = c - 4715 fmutc = datetime(jahr, monat, tag, stunde, minute, sekunde, tzinfo=timezone('UTC')) return fmutc.astimezone(start.tzinfo) def is_full_moon(mday: datetime): nmoon = next_full_moon(mday) till_next_full = nmoon-mday if (till_next_full < timedelta(days=1) or till_next_full < timedelta(days=28)): return True return False def moon_phase_as_text(mday: datetime): nmoon = next_full_moon(mday) till_next_full = nmoon - mday till_next_full_text = strfdelta( till_next_full, "{days} Tage {hours} Stunden bis Vollmond") if (till_next_full < timedelta(days=1)): return ("🌕 Vollmond") if (till_next_full < timedelta(days=6)): return ("🌔 Zunehmender Dreiviertelmond\n" + till_next_full_text) if (till_next_full < timedelta(days=10)): return ("🌓 Zunehmender Halbmond\n" + till_next_full_text) if (till_next_full < timedelta(days=14)): return ("🌒 Zunehmender Sichelmond\n" + till_next_full_text) if (till_next_full < timedelta(days=16)): return ("🌑 Neumond\n" + till_next_full_text) if (till_next_full < timedelta(days=20)): return ("🌘 Abnehmender Sichelmond\n" + till_next_full_text) if (till_next_full < timedelta(days=24)): return ("🌗 Abnehmender Halbmond\n" + till_next_full_text) if (till_next_full < timedelta(days=28.5)): return ("🌖 Abnehmender Dreiviertelmond\n" + till_next_full_text) return ("🌕 Vollmond") def strfdelta(tdelta, fmt): d = {"days": tdelta.days} d["hours"], rem = divmod(tdelta.seconds, 3600) d["minutes"], d["seconds"] = divmod(rem, 60) return fmt.format(**d) def till_next_full_as_text(mday): nmoon = next_full_moon(mday) till_next_full = nmoon-mday return (strfdelta(till_next_full, "{days} Tage {hours} Stunden bis Vollmond"))