The Machines · Core numerics

ephemeris

The Sky as Arithmetic — machines/ephemeris.shoddy

the ephemeris machine's icon

Summary

ephemeris answers where everything is, for any observer and any date. It carries sidereal time — time kept by the turning of the stars rather than the sun. It carries the transform from a sky position to an altitude and a compass azimuth. It carries the sun and the moon as sky positions, the moon's phase, age, distance, rise and set, and the five naked-eye planets from Keplerian elements — the handful of numbers that describe an orbit. It is the machine geo's out-of-scope promised — geo kept the sun as experienced at a place; this is the rest of the sky.

Pure throughout, and no clock anywhere near it: every word takes a Julian day number and a UTC hour as arguments. julian's JulDayNumber makes one from a calendar date (geo's GeoJulian is the same word by another name), and clock's ClockDate() supplies “today” at the caller's edge.

A Brief History of the Almanac

An ephemeris — a table of where the sky's bodies will be, date by date — is one of the oldest products of organised computation. The Nautical Almanac, established by Astronomer Royal Nevil Maskelyne in 1767, printed the moon's position precisely so that a navigator could read longitude off the sky. It was produced by a cottage industry of freelance human computers who worked at home by post, in pairs whose answers were checked against each other — distributed, redundant computation, two centuries before the words meant machinery. The tables in that tradition were built from series: sums of periodic terms, each term a cycle the moon or a planet is known to follow, truncated at whatever accuracy the page could justify. That is still the shape of the thing. The definitive modern ephemerides are numerically integrated at JPL. But the compact printed forms — the Almanac's low-precision moon, Keplerian elements fitted over a few centuries — are exactly what this machine carries: the almanac tradition with the page removed, each word honest about the accuracy at which its series was cut.

Why It's Useful

“What's that bright thing over the rooftops” is a question a latitude, a longitude and a clock reading can answer, and this machine is the arithmetic between them. EphSun, EphMoon and EphPlanet answer where a body is on the celestial sphere; EphAltAz turns that into where it stands in your sky — an altitude and a bearing you can point a compass at.

The boundary with geo is stated so it cannot drift. geo answers the sun as experienced at a place: rise, set, noon, day length, twilight — and stays the canonical machine for all of those. ephemeris answers the sky as observed from a place. EphSun exists here because the moon's phase and every planet's elongation — its angular distance from the sun — are measured from it. The two machines' suns are two small models of one star, and the test suite asserts they agree rather than trusting it.

A sky position is EphSky and not GeoPt, though both live on a sphere. Declination is latitude-shaped and right ascension longitude-shaped. But geo folds longitudes into (−180, 180], which would mangle a right ascension, and a word accepting either record would someday be handed the wrong one silently. Two meanings, two types.

Accuracy is a number, per body. The sun is good to about a minute of arc. The moon is the Astronomical Almanac's low-precision series — about a third of a degree, geocentric, meaning measured from the Earth's centre. The observer's parallax is deliberately unmodelled; its average is folded into the rise altitude instead, which is the almanac's own convention for rise times. The planets are the JPL approximate Keplerian elements, valid 1800..2050 and well under a degree there. Ample for pointing and planning; an observatory wants a different class of library, and would be right to.

Option is the design for rise and set, exactly as in geo: a circumpolar moon has no rise because it never set. The scan is the UTC day, 0..24. Roughly once a month a calendar day genuinely has no moonrise, because the moon rises about fifty minutes later each day and one rise falls the far side of midnight. That day answers None honestly rather than borrowing tomorrow's.

User's Guide

Tonight's moon, from anywhere — the date arrives through julian or clock, and everything after that is arithmetic:

Include "julian.shoddy"
Include "geo.shoddy"
Include "ephemeris.shoddy"

Def Main()
    Let here = GeoAt(53.72, -1.86)
    Let jd = JulDayNumber(JulOf(2026, 8, 12))     ' or ClockDate() via clock
    Let moon = EphMoon(jd, 21)                     ' 21:00 UTC
    Let seen = EphAltAz(here, moon, jd, 21)
    Print(EphAlt(seen))                            ' degrees above the horizon
    Print(EphAzim(seen))                           ' compass bearing to face
    Print(EphMoonPhase(jd, 21))                    ' 0 new .. 1 full
    Select Case EphMoonRise(here, jd)
        Case Some(h)
            Print(h)                               ' UTC hours of moonrise
        Case None
            Print("no moonrise today")             ' an ordinary answer

A planet is the same shape — name it, place it, look at it:

Let mars = EphPlanet(EphMars(), jd, 21)
Print(EphSeparation(mars, EphSun(jd, 21)))         ' its elongation from the sun
Print(EphAlt(EphAltAz(here, mars, jd, 21)))        ' is it even up?

Things worth remembering:

Word Reference

Time and frames, the bodies, the observer

Time and frames

WordDescription
Type EphSkyA position on the celestial sphere: EphRa 0..360 and EphDec −90..90, both degrees, equinox of date.
Type EphViewWhat an observer sees: EphAlt above the horizon and EphAzim as a compass bearing, both degrees.
EphSidereal(jd, hours)Greenwich mean sidereal time at that UTC hour, degrees 0..360 — the one formula that turns a clock time into a direction in the sky. Add an east longitude for the local form.
EphAltAz(p, sky, jd, hours)A sky position as seen from a GeoPt at an instant, as an EphView. The azimuth convention is geo's bearing convention, so you can point a compass at it.
EphSeparation(a, b)The angle between two sky positions, degrees — by haversine, so a moon two degrees from the sun keeps its digits.

The sun and the moon

WordDescription
EphSun(jd, hours)The sun as a sky position. For rise and set at a place, geo remains the machine; this word is for the sky, and it is what phase and elongation are measured from.
EphMoon(jd, hours)The moon as a sky position, geocentric, to about a third of a degree.
EphMoonDistance(jd, hours)The distance to the moon in metres, from its parallax.
EphMoonPhase(jd, hours)The illuminated fraction, 0 at new through 1 at full — from the full angular separation of sun and moon, which is what makes it honest during an eclipse.
EphMoonAge(jd, hours)Days since new moon, 0 up to a synodic month of 29.53.
EphMoonAltitude()The altitude of the moon's centre at the moment we call moonrise, +0.125° — the almanac's convention, folding average parallax against refraction and semi-diameter. A word so it can be seen and substituted, exactly as GeoSunAltitude is.
EphMoonRise(p, jd)UTC hours of moonrise on that day, or None — a day with no moonrise is roughly monthly and a circumpolar moon near a pole has none for weeks. Walked hourly and bisected, because unlike the sun the moon has no closed form.
EphMoonSet(p, jd)Moonset, on the same terms.

The planets

WordDescription
EphMercury() … EphSaturn()The five choosers, as words rather than numbers to remember. Mercury 1, Venus 2, Mars 4, Jupiter 5, Saturn 6 — slot 3 is the Earth-Moon barycentre, which the geocentric subtraction uses and a caller cannot ask for.
EphPlanet(which, jd, hours)A planet as a geocentric sky position, from the JPL approximate Keplerian elements: Kepler's equation by Newton, the standard rotation through perihelion, inclination and node, the Earth subtracted, and one frame change into right ascension and declination. Light-time and aberration are below the stated accuracy and deliberately absent.

Who Uses It

No machine and no mill includes it yet — the sky is already at the reckoner's prompt through its seed, and a mill that puts it to work will appear here.

The Machines It Uses

MachineWhy
geoThe observer is a GeoPt, read through its radian accessors, and the azimuth answer goes through GeoWrapBrg — one compass convention for the whole tree.
mathRad, Deg, Clamp and Hypot, exactly as geo uses them.