Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Parses niph's lunations calculator at https://github.com/dlebansais/PgMoon/blob/master/PgMoon-Plugin/PhaseCalculator.Lunations.cs
- # this is itself from PG code shared by Citan and should be 100% accurate
- # the output is a TSV of dates (starting at the relatively arbitrary 4/11/2021)
- # requires python 3.9+. On Windows machines, it also depends on an up-to-date tzdata package
- # (python -m pip install tzdata)
- import datetime
- import re
- from zoneinfo import ZoneInfo
- from typing import IO
- LINEMATCH_RE = re.compile(
- r'new\(\) \{ Index = (?P<index>\d+), NewMoon = ParseDateTime\("(?P<new_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), WaxingCrescentMoon = ParseDateTime\("(?P<waxing_crescent_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), QuarterMoon = ParseDateTime\("(?P<quarter_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), WaxingGibbousMoon = ParseDateTime\("(?P<waxing_gibbous_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), FullMoon = ParseDateTime\("(?P<full_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), WaningGibbousMoon = ParseDateTime\("(?P<waning_gibbous_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), LastQuarterMoon = ParseDateTime\("(?P<last_quarter_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), WaningCrescentMoon = ParseDateTime\("(?P<waning_crescent_moon>\d\d/\d\d/\d\d\d\d \d\d:\d\d:\d\d)"\), Duration = ParseTimeSpan\("(?P<duration>\d+\.\d+):00:00"\) },'
- )
- IGNORE = {
- "namespace PgMoon;",
- "",
- "/// <summary>",
- "/// Represents a moon phase calculator.",
- "/// </summary>",
- "public partial class PhaseCalculator",
- "{",
- "private static readonly Lunation[] LunationTable =",
- "[",
- "];",
- "}",
- }
- SKIP_TO_THIS_DATE = datetime.datetime(2021, 4, 11, tzinfo=datetime.UTC)
- lunation_to_sheet = (
- ("new_moon", "New"),
- ("waxing_crescent_moon", "Waxing Crescent"),
- ("quarter_moon", "First Quarter"),
- ("waxing_gibbous_moon", "Waxing Gibbous"),
- ("full_moon", "Full"),
- ("waning_gibbous_moon", "Waning Gibbous"),
- ("last_quarter_moon", "Third Quarter"),
- ("waning_crescent_moon", "Waning Crescent"),
- )
- def main(f: IO, tformat: str):
- last_phase_dt, last_phase_sheet_name = None, None
- for line in f.readlines():
- stripped = line.strip()
- if stripped in IGNORE:
- continue
- if lunation := LINEMATCH_RE.match(stripped):
- idx = int(lunation["index"])
- # duration = datetime.timedelta(days=float(lunation["duration"]))
- # ^ also available if needed, the total duration of the lunation
- for phase_idx, phase_sheet_name in lunation_to_sheet:
- phase_start_dt = (
- datetime.datetime.strptime(lunation[phase_idx], "%m/%d/%Y %H:%M:%S")
- .replace(tzinfo=datetime.UTC)
- .astimezone(tz=ZoneInfo("US/Eastern"))
- )
- if phase_start_dt < SKIP_TO_THIS_DATE:
- continue
- if phase_start_dt.hour != 0:
- raise Exception(
- f"{idx=} had phase not at midnight Eastern {phase_idx=},{phase_start_dt=}"
- )
- if last_phase_dt:
- for i in range((phase_start_dt - last_phase_dt).days):
- print(
- f"{(last_phase_dt + datetime.timedelta(days=i)).strftime('%#m/%#d/%Y')}\t{last_phase_sheet_name}"
- )
- last_phase_dt = phase_start_dt
- last_phase_sheet_name = phase_sheet_name
- else:
- raise Exception(f"didn't match:\n{stripped}, add to ignore or adjust regex")
- assert last_phase_dt
- print(f"{last_phase_dt.strftime(tformat)}\t{last_phase_sheet_name}")
- if __name__ == "__main__":
- import platform
- if platform.system() == "Windows":
- format = "%#m/%#d/%Y"
- else:
- format = "%-m/%-d/%Y"
- with open("PhaseCalculator.Lunations.cs") as f:
- main(f, format)
Advertisement