Almanac
Where the Sun, Moon and stars are, when they rise and set, how the Moon is lit, when the Earth's shadow crosses it, and when the Moon crosses the Sun from your location. No network, no data files to ship, no API key — just geometry, in your app or on your boat. The sky below is live: every star in it is this library running in your browser, placed for your location and the moment you choose. The Sun, Moon, and planet pages have more to explore.
Planets
Seven planets through tonight's sky, and linked orbital and sky views that explain retrograde motion.
Explore the planetsSun
Twilight, golden hour and blue hour from the equator to the midnight Sun, a year of the Sun's path, solar eclipses from your location, and every solar eclipse on Earth with its central line.
Explore the SunMoon
A month of phases and illumination, the Moon tilted as it sits in your sky, and lunar eclipses as the Earth's shadow crosses the Moon.
Explore the MoonThe same astronomy engine powers Slackwater's Sun and Moon views, with Moon illumination and sunrise/sunset alongside the tide timeline.
Key Features
Offline by construction
Zero network calls and zero runtime data files. Every Sun, Moon, planet, star and eclipse on these pages is computed in your browser from pure geometry; only the map tiles behind the eclipse paths are downloaded. The same code runs on a boat with no signal.
Twin ports, one behavior
TypeScript and Swift implementations validated against a shared corpus of JPL Horizons, USNO and Espenak fixtures. Neither port is the other's oracle.
Sun, Moon, planets and eclipses
Positions, rise and set, all three twilights, any Sun altitude for golden and blue hour, upper and lower transits, moon phase, illumination and tilt, all eight planets, lunar and local solar eclipses with contact times, every solar eclipse on Earth with its central line, and alt/az for any star you give a catalog position.
Held to a tolerance
Rise and set times agree with USNO to within a minute across 1950–2100, and eclipse peaks match the Espenak catalog to roughly 15 seconds.
Built for interactive sky views
Almanac uses astronomy translated from Don Cross's Astronomy Engine, with optimized event searches and TypeScript Sun calculations. Scrub the sky above to see positions update in your browser. Both ports share correctness fixtures and a performance suite covering 30 workloads, including planetary tracks and rise/set.
| Workload | TypeScript | Swift |
|---|---|---|
| Sun events · one year | 73.4% | 62.8% |
| Moon events · one year | 57.6% | 57.4% |
| Sun events · 228 hours | 73.4% | 61.9% |
| Moon events · 228 hours | 57.1% | 57.0% |
Measurements use seven interleaved process pairs with the same harness and toolchain; build and startup time are excluded. Timings vary by machine. CI checks for median regressions above 20%. Read the benchmark results and reproduction instructions.
Using Almanac
TypeScript
npm install @openwaters/almanac@0.8.0import { sunEvents, sunAltitudeEvents, moonOrientation, starAltAz, nextLunarEclipse, lunarEclipseVisibility, nextSolarEclipse, nextGlobalSolarEclipse } from '@openwaters/almanac';
const observer = { latitudeDeg: 48.5, longitudeDeg: -123.0 };
// Sunrise, sunset, twilights and transit for the next 24 hours
const now = new Date();
const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
for (const { kind, time } of sunEvents(now, tomorrow, observer)) {
console.log(kind, time.toISOString());
}
// Golden hour ends when the Sun rises through +6° and starts when it falls back
console.log(sunAltitudeEvents(now, tomorrow, observer, 6));
// Which way the Moon's lit side faces, in degrees from straight up
const moon = moonOrientation(now, observer);
console.log(moon.brightLimbAngleDeg - moon.parallacticAngleDeg);
// The next lunar eclipse, and whether you'll see it
const eclipse = nextLunarEclipse(now);
const visibility = lunarEclipseVisibility(eclipse, observer);
console.log(eclipse.kind, eclipse.peak, visibility.visibleAtPeak);
// The next solar eclipse visible from this location
const solar = nextSolarEclipse(now, observer);
console.log(solar.kind, solar.peak, solar.obscuration);
// The next solar eclipse anywhere on Earth, and where its shadow axis lands
const anywhere = nextGlobalSolarEclipse(now);
console.log(anywhere.kind, anywhere.peak, anywhere.latitudeDeg, anywhere.longitudeDeg);
// Where Sirius is right now, from its J2000 catalog position
console.log(starAltAz(101.287, -16.716, now, observer));Swift
.package(url: "https://github.com/openwatersio/almanac.git", exact: "0.8.0")import Almanac
import Foundation
let observer = try Observer(latitudeDeg: 48.5, longitudeDeg: -123.0)
let now = Date()
let tomorrow = now.addingTimeInterval(24 * 60 * 60)
for event in try sunEvents(from: now, to: tomorrow, observer: observer) {
print(event.kind, event.time)
}
print(try sunAltitudeEvents(from: now, to: tomorrow, observer: observer, altitudeDeg: 6))
let moon = try moonOrientation(at: now, observer: observer)
print(moon.brightLimbAngleDeg - moon.parallacticAngleDeg)
let eclipse = try nextLunarEclipse(after: now)
let visibility = try lunarEclipseVisibility(eclipse, observer: observer)
print(eclipse.kind, eclipse.peak, visibility.visibleAtPeak)
let solar = try nextSolarEclipse(after: now, observer: observer)
print(solar.kind, solar.peak, solar.obscuration)
let anywhere = try nextGlobalSolarEclipse(after: now)
if let latitude = anywhere.latitudeDeg, let longitude = anywhere.longitudeDeg {
print(anywhere.kind, anywhere.peak, latitude, longitude)
}
let sirius = try starAltAz(raDeg: 101.287, decDeg: -16.716, at: now, observer: observer)
print(sirius.altDeg, sirius.azDeg)Supported interval: 1950-01-01 through 2100-12-31. See the supported scope for capabilities and limits. Coming from another library? Almanac has migration guides from SunCalc and Solar, and a comparison with other libraries.
Free & Open Source
Almanac is MIT licensed, with its astronomy translated from Don Cross's Astronomy Engine. Use it, contribute to it, or fork it.