/** * Astronomy utilities — moon phase, moonrise/moonset, and extended twilight. * * All computation is local via `astronomy-engine` (±1 arcminute accuracy, * zero transitive dependencies) — pure, deterministic, no I/O, no caching. * Times are returned as Luxon DateTimes in the zone of the input date, so * callers pass the forecast's IANA timezone once and formatting stays simple. */ import { DateTime } from 'luxon'; import type { UnitPreferences } from '../config/units.js'; /** * Astronomy facts for one calendar day at one location. * * All ten time fields are nullable: a null means the event does not occur * during that calendar day. For the moon this happens routinely (the moon * rises ~50 minutes later each day, so about once a month a day has no * moonrise or no moonset); for twilight it happens in polar conditions. */ export interface DayAstronomy { /** One of the 8 standard phase names (New Moon, Waxing Crescent, ...). */ phaseName: string; /** Illuminated fraction of the moon's disc, 0-100. */ illuminationPct: number; moonrise: DateTime | null; moonset: DateTime | null; civilDawn: DateTime | null; civilDusk: DateTime | null; nauticalDawn: DateTime | null; nauticalDusk: DateTime | null; astroDawn: DateTime | null; astroDusk: DateTime | null; /** * Sun altitude (degrees) at local solar noon (approximated as clock noon). * Used by the formatter to distinguish "polar day" (sun never descends to * a twilight threshold) from "polar night" (sun never ascends to it) when * a twilight event is missing. */ sunNoonAltitude: number; } /** The next full and new moon instants after a given time. */ export interface NextMoonQuarters { nextFull: DateTime; nextNew: DateTime; } /** * Bucket a moon phase angle (0-360°, 0 = new, 180 = full) into one of the 8 * standard phase names. Buckets are centered on the principal phases, so the * date USNO labels "New Moon" reports "New Moon" here (e.g. 350° and 10° are * both New Moon; boundaries fall at 22.5°, 67.5°, ..., 337.5°). */ export declare function moonPhaseName(phaseAngle: number): string; /** * Compute moon phase, moonrise/moonset, and civil/nautical/astronomical * dawn+dusk for the calendar day containing `date` (in `date`'s zone) at the * given coordinates. * * Phase and illumination are evaluated at local noon — a representative * instant for "the" phase of a calendar day. */ export declare function computeDayAstronomy(latitude: number, longitude: number, date: DateTime): DayAstronomy; /** * Find the next full moon and next new moon after `from`. * Iterates the lunar quarter sequence (new=0, first=1, full=2, third=3); * both are always found within one synodic month (4-5 iterations). */ export declare function nextMoonQuarters(from: DateTime): NextMoonQuarters; /** * Format the per-day astronomy block — the two lines added to each daily * forecast entry when `include_astronomy` is set: * * **Moon:** Waxing Gibbous (78% illuminated) · Rise 3:42 PM · Set 1:15 AM * **Twilight:** Civil 5:29 AM / 9:02 PM · Nautical 4:47 AM / 9:44 PM · Astronomical 3:58 AM / 10:33 PM * * Every field always renders: missing moon rise/set shows "none" (a normal * monthly occurrence at any latitude), missing twilight shows the polar * wording. Ends with a trailing newline. */ export declare function formatAstronomyBlock(astro: DayAstronomy, prefs: UnitPreferences): string; /** * Format the once-per-response next-quarters line: * * **Next full moon:** Aug 27 · **Next new moon:** Sep 11 * * Dates are rendered in the forecast's IANA timezone. Ends with a trailing * newline. */ export declare function formatNextQuarters(quarters: NextMoonQuarters, timezone: string): string; //# sourceMappingURL=astronomy.d.ts.map