Astronomy

Astronomy is an astronomical engine in pure PHP: where the Sun, the Moon and the planets are at a given instant, and the long tail of things that follow from knowing it. Eclipses and occultations, a catalogue of fixed stars, rise and set over a real horizon, orbits, five reference frames, and the time scales underneath all of it.
It has no framework under it, no Composer dependencies, and it never touches the network while it runs. The data ships inside the package.
Written against version 1.0.
Why it exists
PHP could not do this.
A position good to better than an arcsecond, over several centuries, is not a formula you write in an afternoon. It is fifty thousand coefficients, a correction towards a numerical integration, two time scales that must not be confused, precession, nutation, light time, aberration and the bending of light near the Sun. Leave out the last one and a planet sitting half a degree from the Sun comes out almost a full arcsecond wrong.
What the language had were two options. One was a binding to a C library, which means compiling an extension on every machine you deploy to and ruling out most shared hosting. The other was one of the truncated-series implementations, which are honest about being good to arcminutes. An arcminute is sixty arcseconds: for plenty of uses that is fine, and for anything that has to agree with a published table it is not.
This computes the positions itself, in PHP, and checks them against the Jet Propulsion Laboratory's own ephemeris system. There is nothing to compile, nothing to install alongside it and nothing to call while it runs.
How good the numbers are
Every body it knows, compared against JPL Horizons live, between 1600 and 2400:
| worst difference | |
|---|---|
| All bodies, 1600 to 2400 | 0.18″ |
| All bodies, twentieth century | 0.04″ |
| Median, twentieth century | 0.002″ |
| Fixed stars against their catalogue positions | 0.04″ at 2000, 0.3″ at 1900 and 2100 |
| The 24 solar and 26 lunar eclipses of 2020 to 2030 | identical in date and type |
| Rise and set of the Sun, Venus and Jupiter, 431 events | 0.12 s |
That check is not a claim in a README. It ships in the package as HorizonsCheck, it asks Horizons over the network, and you can run it yourself:
vendor/bin/astronomy check
What is left is not the ephemerides. It is a 0.13″ frame difference from the precession model, which is the 1976 one because that is what VSOP87 and the JPL tables are written in, and that is a measured decision rather than an oversight.
What it is not
It is not a Laravel package. There is no service provider, no facade and no config file, and no class in it names Illuminate. It is plain PHP that works anywhere, and the continuous integration fails the build if that ever stops being true.
It does not interpret anything. It returns a longitude, a latitude, a distance and a speed. What those mean is not its business.
It is not a binding. There is no C library underneath and nothing to compile. The series, the tables and the corrections are in the package, and the arithmetic is PHP.
It does not call anybody while it runs. The only things in it that touch the network are the twelve commands that rebuild the data, and those are for whoever maintains it, not for whoever installs it.
Three decisions worth knowing up front
There is not one hand-typed coefficient. Fifty thousand numbers went into this and a single mistyped one gives a wrong position that nobody catches by looking at the output. So nothing is typed: twelve commands download the published sources from CDS, ERFA, the IERS and the JPL and write the tables, and rerunning one reproduces its file byte for byte. The residual each command prints is the check.
Two time scales, and confusing them is the classic mistake. Bodies go in Terrestrial Time and anything that depends on how far the Earth has turned goes in Universal Time. They are about seventy seconds apart today. Time::fromClock() returns both at once, in that order, so that the pair travels together and cannot be mixed up.
The data lives in the package, and that is the point. Ten megabytes of series, tables and corrections, so that a deployment does not depend on a server in Strasbourg being up that morning. There is no migration, nothing in a database and no cache to warm.
What is in it
| Positions | the Sun, the Moon, the eight planets, Pluto, Chiron, Pholus and four asteroids, with speed |
| Time and calendars | UTC, UT1, TT, delta T from observation, leap seconds, the Julian calendar |
| Frames | geocentric, heliocentric, barycentric, topocentric and seen from another planet |
| Houses | twenty-three systems, built geometrically, with their cusp speeds |
| Fixed stars | 1,099 objects from SIMBAD and Hipparcos-2, with the IAU constellations |
| Eclipses and occultations | global and local circumstances, the central path, the saros number |
| Rise and set | passes, twilights, a horizon behind a mountain or below the sea |
| Orbits | nodes, apsides, osculating and mean elements, extreme distances |
| Phenomena | phase, apparent diameter, magnitude, the Moon's lunations |
| Crossings and retrogrades | when a body reaches a longitude, and where it turns around |
| The sidereal zodiac | forty-three ayanamsas and the lunar mansions |
| Downloadable bodies | any asteroid, satellite or comet the JPL has |
Where to go next
Installation is one command. Quick start is a position, a set of houses and a star, in about twenty lines. The data says where every number came from and how to rebuild it, and precision is how all of it is checked.