YEAR_SEMANTICS_AUDIT - TheDaniel166/moira GitHub Wiki
Year Semantics Audit
Date: 2026-03-30
Purpose
Audit every live use of 365.25, 36525.0, JULIAN_YEAR, TROPICAL_YEAR,
and SIDEREAL_YEAR in the moira/ codebase so the project distinguishes:
- exact Julian-year doctrine
- tropical-year timing
- sidereal-year/orbital timing
- standard Julian-date algorithm constants
- sites that remain candidates for future refinement
Summary Verdict
Most remaining 365.25 uses are correct and should remain.
The codebase currently contains five distinct semantic classes:
Julian yearby doctrine or convention: keep.Tropical yearfor seasonal/solar timing: useTROPICAL_YEAR.Sidereal yearfor orbital/stellar period timing: useSIDEREAL_YEAR.Julian century(36525.0) in standard astronomical polynomials: keep.365.25inside canonical calendar/JD conversion algorithms: keep.
After the latest correction pass, the main live upgrade targets that remain are
small in number. The largest genuinely ambiguous site is the annual-resolution
integration in delta_t_physical.py.
Class A: Keep As Exact Julian-Year Doctrine
These are not loose approximations. They are explicit Julian-year doctrine, historical astrological convention, or standard astronomical convention.
moira/constants.pyJULIAN_YEAR = 365.25- Correct. Exact by definition.
moira/dasha.pyjulian_365.25basis and allJULIAN_YEARuses- Correct. This is an explicit doctrinal year basis, contrasted with
savana_360.
moira/timelords.py_JULIAN_YEAR = 365.25- Correct. The module explicitly says JD arithmetic uses Julian years.
moira/profections.pyage_years = int(elapsed_days / 365.25)- Plausibly correct if the subsystem intends completed ages in fractional Julian years.
- This is doctrinal rather than physical astronomy. Keep unless the profection doctrine is intentionally revised.
moira/primary_directions/keys.py_NAIBOD_RATE = 360.0 / 365.25- Correct. Naibod is a doctrinal key, not a generic solar-year approximation.
moira/primary_directions/__init__.py_DEFAULT_SOLAR_RATE = 360.0 / 365.25- Likely correct within primary-direction key doctrine unless the subsystem explicitly adopts a different key basis.
moira/stars.py- proper-motion propagation:
dt_years = (jd_tt - _J2000) / 365.25 - light-time conversion:
_DAYS_PER_YEAR = 365.25 - Correct by astronomical convention. Proper motion is normally expressed per Julian year; the light-year is conventionally tied to the Julian year.
- proper-motion propagation:
moira/multiple_stars.pyOrbitalElements.period_yris documented as Julian yearst_yr = (jd - orb.epoch_jd) / 365.25- Correct because the module explicitly defines orbital periods in Julian years.
moira/sothic.py1460 × 365.25 = 533265cycle_pos = ((jd_rise - epoch_jd) / 365.25) % _SOTHIC_CYCLE_YEARS- Correct. The Sothic cycle identity is specifically Julian-year based.
Class B: Keep As Tropical-Year Timing
These are places where the code means seasonal or solar-cycle timing rather than a generic Julian year.
moira/constants.pyTROPICAL_YEAR = 365.24219
moira/harmonics.py- age harmonic timing uses
TROPICAL_YEAR - Correct.
- age harmonic timing uses
moira/progressions.py- progression age conversion uses
TROPICAL_YEAR - Correct.
- progression age conversion uses
moira/transits.pysolar_return()search seed now usesTROPICAL_YEAR- Correct. The solar return is seasonal/solar, not Julian-year doctrine.
Class C: Keep As Sidereal-Year / Orbital Timing
These are places where the code means orbital period or sidereal cycle timing.
moira/constants.pySIDEREAL_YEAR = 365.256363Body.SIDEREAL_PERIODS[EARTH] = SIDEREAL_YEAR- Correct.
moira/phenomena.py- perihelion/aphelion fallback search windows now use
SIDEREAL_YEAR - Correct. These are orbital search heuristics, not seasonal year lengths.
- perihelion/aphelion fallback search windows now use
Class D: Keep As Julian-Century Polynomial Time
These are standard astronomical polynomial scales. They are not “approximate years” in the sense at issue here.
moira/constants.pyJULIAN_CENTURY = 36525.0
moira/coordinates.pyT = (jd_tt - 2451545.0) / 36525.0
moira/eclipse.pycenturies = delta_days / 36525.0
moira/hermetic_decans.pyT = (jd - 2451545.0) / 36525.0
moira/nodes.py- rates divided by
36525.0
- rates divided by
moira/precession.pyT * 36525.0
These should remain exactly as they are unless the underlying polynomial model itself changes.
Class E: Keep As Canonical JD/Calendar Algorithm Terms
These uses occur inside standard Meeus-style or related calendar/JD conversion formulae. They are algorithm constants, not physical year approximations.
moira/julian.pymath.floor(365.25 * (year + 4716))(B - 122.1) / 365.25D = math.floor(365.25 * C)
moira/planets.py- inverse calendar/JD helper with the same constants
These should not be rewritten as tropical or sidereal years.
Class F: Genuine Remaining Audit Candidate
This is the main live site that still merits a model-level decision.
moira/delta_t_physical.pydt_days = (y1 - y0) * 365.25
Assessment:
- The code integrates an annual-resolution LOD anomaly series expressed in decimal years.
365.25is serviceable, but this is not as doctrinally locked as the Julian-year, light-year, Naibod, or JD algorithm cases.- A better choice might be:
TROPICAL_YEARif the decimal years are interpreted as mean civil/seasonal spacing- a file-driven exact epoch delta if the source timestamps are actual annual epochs
- leave as
JULIAN_YEARif the series is intended as a uniform year axis
Recommendation:
- Do not change this site blindly.
- Resolve it only after checking the source-data convention for the LOD files.
Low-Priority Cosmetic Improvements
These are not correctness bugs, but could be made more explicit over time.
moira/profections.py- could import
JULIAN_YEARinstead of spelling365.25
- could import
moira/stars.py- could import
JULIAN_YEARinstead of local_DAYS_PER_YEAR = 365.25
- could import
moira/timelords.py- could import
JULIAN_YEARinstead of local_JULIAN_YEAR = 365.25
- could import
moira/multiple_stars.py- could import
JULIAN_YEARfor consistency with its “Julian years” doctrine
- could import
These are semantic-clarity refactors, not accuracy fixes.
Recommended Next Steps
- Leave all Class A, C, D, and E sites untouched.
- Optionally normalize explicit Julian-year imports in Class A for consistency.
- Do a source-convention check on
moira/data/core_angular_momentum.txtand related ΔT files before changingmoira/delta_t_physical.py. - If desired, annotate key modules with “Julian year”, “tropical year”, or “sidereal year” comments at the constant declaration points to prevent future drift.