Purpose
A birth moment enters HORCOM as a civil date and clock time and must become a Julian date in Ephemeris Time before any planet can be computed. This module holds that road. It follows Jean Meeus, whose book Robert names as his source, with Robert's own decisions layered on top, a per chart calendar override, a delta T table he extended by hand over the years, and the Newcomb sidereal time series.
Origin map
| original | ported as | file |
|---|---|---|
juld | julian_day | src/horcom/time/calendar.* |
dat | calendar_date | |
juld1 (without somo) | time_arguments | |
utet | delta_t_minutes | src/horcom/time/delta_t.* |
utet1 | ut_to_et | |
etut | et_to_ut | |
sidt | gmst0_hours, apparent_sidereal_hours, sidereal_at_hours | src/horcom/time/sidereal.* |
Calendar and Julian date
The conversion is the classic Meeus algorithm with one HORCOM speciality. Every
chart carries a calendar flag, in the original a string containing
"(JULIAN.)" or "(GREGOR.)". Without a flag the
historical rule applies, Julian calendar before the reform of 1582-10-15 and
Gregorian from then on. The flags force one calendar across the boundary, so a
researcher can enter proleptic Gregorian dates for antiquity or keep Julian
dates for countries that reformed late. The port models the flag as the
Calendar enum.
Negative years go through a dedicated branch,
FIX(365.25 * y - 0.75), the truncation trick
from the book that makes the formula hold all the way down to the Julian day
zero in 4713 BC. Years count astronomically, the year 0 exists.
Delta T
Planets run in Ephemeris Time, houses in Universal Time. The difference is delta T, and Robert kept it as a table of measured values from 1620 to 2008, linearly interpolated, in minutes, with three polynomial branches beyond the table. His annotations mark the ranges
delt = 1.2053 * t1 + 0.4992 * t1 * t1 - 0.7506263 //2008 a.d. ........ delt = 0.425 + 0.85 * t1 + 0.425 * t1 * t1 //948 a.d. ..... 1600 a.d. delt = 28.74 + 6.81 * t1 + 0.7383 * t1 * t1 //390 b.c. .... 948 a.d.
He extended the table repeatedly, his change log notes
// UTET extrapolated up to 2008 28.06.04
One charming detail is preserved knowingly. When the year is exactly 1620 the interpolation loop lands on the zero element of the GFA arrays and still produces the correct 124 seconds, by arithmetic accident rather than design. The port reproduces the loop exactly and its test pins that edge.
Sidereal time
The original sidt rewinds the clock to 0h UT of the calendar
day, recomputes the Julian date there, evaluates Greenwich mean sidereal time
at midnight with the Newcomb series, optionally applies the equation of the
equinoxes, and then advances to the moment with the solar to sidereal rate
1.002737908. Robert's default is the apparent variant, his settings call it
stzw& = 1 // true sidereal time
The port splits the procedure into three pure functions, midnight GMST, apparent correction and advance to the moment, so the chart pipeline can reproduce the original call order without hidden state. Two behaviours are documented for that pipeline. The cubic term of the series runs on centuries from J2000 while the linear terms run on centuries from 1900, exactly as the original computes it. And in the original, rewinding to midnight leaves the nutation state of 0h behind in the globals until the pipeline recomputes it, the port keeps no such state at all.
Verification
tests/test_calendar.cpp reproduces seventeen worked examples from
Meeus in both directions, the reform boundary days, the calendar override
including a proleptic Gregorian round trip, and the time arguments at J2000.
tests/test_delta_t.cpp pins table nodes including the 1620 edge,
an interpolated year, all three polynomial branches and the UT to ET round
trip. tests/test_sidereal.cpp pins the exact transcription values
and checks the Meeus example within half a second, the Newcomb series agrees
with the modern value to 0.066 s there, and the equation of the equinoxes
example lands within a millisecond of the book.