Moon Phase Times
A single-file JavaScript module (MIT) for the times of new moon, first quarter, full moon and last quarter, and the Moon's illuminated fraction. This page imports it, and runs its tests live.
Caveats: every coefficient in the module was typed from memory, not copied from Meeus's book, and is vouched for only by the comparison with astronomy-engine below; times differ from astronomy-engine by about a minute, and the illuminated fraction is a low-accuracy formula (worst difference shown below). Made by Claude, an AI model.
Try it
All times are UT (close to UTC). The drawing shows the Moon as seen from the northern hemisphere. Supported dates are ; the module accepts others but the delta-T it uses there is only a rough guide.
The page runs the tests
Running the tests in a background worker; this takes a few seconds…
(a) Against astronomy-engine, row by row
Positive means this module is later. "Dyn." compares the dynamical-time instants (no delta-T involved); "UT" also includes the two programs' delta-T models. Rows marked oldest, newest and largest are picked by the code from the whole sweep; the rest are evenly spaced through it.
(b) Against a plain mean-month estimate
(c) Round trip: illuminated fraction at each computed phase time
What the checks do and do not vouch for
Use it
import { phasesBetween, nextPhase, previousPhase, illuminatedFraction } from "./moonphase.js";
nextPhase(new Date("2026-10-18T12:00:00Z"));
// { name: "first quarter", index: 1, date: Date (UT), jde: 2461... }
phasesBetween(new Date("2026-01-01"), new Date("2026-12-31")); // array, oldest first; [] if none
illuminatedFraction(new Date()); // 0 (new) to 1 (full)
Also exported: phase(n) (n = 4 × lunation + 0, 1, 2, 3 from the January 2000 new moon), phaseAngle(date), phaseJDE(k), deltaT(year) and PHASES. Bad input throws TypeError or RangeError. Tests: node test-node.mjs.
Files: moonphase.js (the module, one file, no dependencies), tests.js, test-node.mjs, runner.js, LICENSE, README.md.
Licence
Code: moonphase.js, the tests and this page are MIT licensed, © 2026 Claude (an AI model) for Vigil studio (LICENSE). Vendored library, used only by the checks and not needed to use the module: astronomy-engine 2.1.19 by Don Cross, MIT (vendor/LICENSE-astronomy-engine.txt), taken from its npm package, unmodified except that the author's e-mail address was removed from the copyright and author lines (vendor/astronomy.js). Its licence text was fetched from the project's repository and shows a different year range (2019-2025) from the code header (2019-2023). The 40-second residual limit and the 1.5-day mean-month limit were both set after seeing the results. Method: the series is Jean Meeus's, as I remember it; the book's text is not copied.