Sun
Where the Sun is, when it rises and sets, how deep each twilight runs, and when the Moon crosses it, from your location or anywhere on Earth. Every demo here is Almanac running in your browser.
Where night disappears
A full day, from sunlight through civil, nautical and astronomical twilight into night. Change latitude and season to find the midnight Sun—or a day when the Sun never rises.
Your location stays in this browser tab. We don't send it to our servers or store it.
16h 7m of daylight
Choose another location to compare the length of the day. Times are local to Salish Sea on .
Exact twilight intervals
- 00:00–01:00 · Astronomical twilight
- 01:00–01:27 · Night
- 01:27–03:29 · Astronomical twilight
- 03:29–04:28 · Nautical twilight
- 04:28–05:10 · Civil twilight
- 05:10–21:18 · Daylight
- 21:18–22:00 · Civil twilight
- 22:00–22:59 · Nautical twilight
- 22:59–24:00 · Astronomical twilight
Show the TypeScript
import { sunEvents, sunAltAz } from '@openwaters/almanac';
const observer = { latitudeDeg: 70, longitudeDeg: 0 };
const start = new Date('2026-06-21T00:00:00Z');
const end = new Date('2026-06-22T00:00:00Z');
const crossings = sunEvents(start, end, observer)
.filter(event => event.kind !== 'transit');
// Use each crossing time as a color boundary in the 24-hour ribbon.
// Dawn enters a lighter band; dusk enters a darker one.
// No crossings? Check altitude: midnight Sun is not a missing result.
console.log(crossings, sunAltAz(start, observer).altDeg);A year of the Sun
Your location stays in this browser tab. We don't send it to our servers or store it.
The Sun at the same UTC time every day in 2026, chosen near noon at this longitude. Earth's tilt and changing orbital speed trace this figure eight, called an analemma.
Altitude 18.6° · azimuth 179.1° · sampled at UTC daily. Dashed line: horizon. Negative altitude means the Sun is below it.
Show the TypeScript
import { sunAltAz } from '@openwaters/almanac';
const observer = { latitudeDeg: 48.5, longitudeDeg: -123 };
const points = Array.from({ length: 365 }, (_, day) => {
// A fixed UTC time near local mean noon, independent of daylight saving.
const time = new Date(Date.UTC(2026, 0, day + 1, 12)
- observer.longitudeDeg / 360 * 86_400_000);
return { time, ...sunAltAz(time, observer) };
});
console.log(points);Solar eclipses from here
A solar eclipse is a different event from every place: your location determines which eclipses appear, their contact times, and how much of the Sun the Moon covers. A solar eclipse is the Moon's shadow falling on the Earth; the Earth's shadow falling on the Moon is a lunar eclipse.
Show the TypeScript
import { solarEclipses, solarObscuration } from '@openwaters/almanac';
const observer = { latitudeDeg: 48.5, longitudeDeg: -123 };
const start = new Date();
const end = new Date(start);
end.setUTCFullYear(end.getUTCFullYear() + 10);
for (const eclipse of solarEclipses(start, end, observer)) {
console.log(eclipse.kind, eclipse.peak, eclipse.obscuration);
console.log(solarObscuration(eclipse.peak, observer));
}Solar eclipses anywhere on Earth
A few recent solar eclipses, and every one in the next ten years, wherever it happens, marked where greatest eclipse falls. For a total or annular eclipse, follow the Moon's shadow along its central line from where it first touches the Earth to where it leaves.
Show the TypeScript
import { globalSolarEclipses, solarEclipseCentralLine } from '@openwaters/almanac';
const start = new Date();
const end = new Date(start);
end.setUTCFullYear(end.getUTCFullYear() + 10);
// No observer: every solar eclipse on Earth, with where greatest eclipse
// falls. For a partial, whose shadow axis misses the Earth, that is the point
// on the Earth's edge nearest the axis, with the Sun on the horizon.
for (const eclipse of globalSolarEclipses(start, end)) {
console.log(eclipse.kind, eclipse.peak, eclipse.greatestLatitudeDeg,
eclipse.greatestLongitudeDeg, eclipse.greatestObscuration);
// The central line, one point a minute, each total or annular.
const line = solarEclipseCentralLine(eclipse.peak);
console.log(line.map(({ time, latitudeDeg, longitudeDeg, kind }) =>
[time, latitudeDeg, longitudeDeg, kind]));
}