pg_orrery/sql/pg_orrery--0.15.0--0.16.0.sql
Ryan Malloy 46c8a30575 Add v0.16.0: twilight dawn/dusk, lunar phase, planet apparent magnitude
Twilight: 6 functions (civil/nautical/astronomical × dawn/dusk) reusing
the existing find_next_crossing() bisection search with Sun depression
angle thresholds (-6°, -12°, -18°). Returns NULL for polar regions
where the threshold is never reached.

Lunar phase: 4 functions computing Sun-Earth-Moon geometry from VSOP87
+ ELP2000-82B. Phase angle [0,360) via elongation + cross product
z-component for waxing/waning discrimination. 8 named phases in 45°
bins. Moon age approximated from phase angle and mean synodic month.

Planet magnitude: Mallama & Hilton (2018) polynomial model with VSOP87
heliocentric distances and phase angle via law of cosines. All 7
planets (Mercury-Neptune, excluding Earth). Saturn ring tilt not
modeled.

151 → 162 SQL objects. 26 → 27 test suites, all passing.
2026-02-26 12:42:01 -07:00

80 lines
3.9 KiB
SQL

-- pg_orrery 0.15.0 -> 0.16.0: twilight, lunar phase, planet magnitude
-- ============================================================
-- Twilight functions (6)
-- ============================================================
CREATE FUNCTION sun_civil_dawn(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_civil_dawn'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_civil_dawn(observer, timestamptz) IS
'Next civil dawn (Sun crosses -6 deg rising). Outdoor activities without artificial light.';
CREATE FUNCTION sun_civil_dusk(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_civil_dusk'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_civil_dusk(observer, timestamptz) IS
'Next civil dusk (Sun crosses -6 deg setting). Artificial light needed.';
CREATE FUNCTION sun_nautical_dawn(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_nautical_dawn'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_nautical_dawn(observer, timestamptz) IS
'Next nautical dawn (Sun crosses -12 deg rising). Horizon visible at sea.';
CREATE FUNCTION sun_nautical_dusk(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_nautical_dusk'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_nautical_dusk(observer, timestamptz) IS
'Next nautical dusk (Sun crosses -12 deg setting). Horizon no longer visible at sea.';
CREATE FUNCTION sun_astronomical_dawn(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_astronomical_dawn'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_astronomical_dawn(observer, timestamptz) IS
'Next astronomical dawn (Sun crosses -18 deg rising). Sky was fully dark.';
CREATE FUNCTION sun_astronomical_dusk(observer, timestamptz) RETURNS timestamptz
AS 'MODULE_PATHNAME', 'sun_astronomical_dusk'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION sun_astronomical_dusk(observer, timestamptz) IS
'Next astronomical dusk (Sun crosses -18 deg setting). Sky becomes fully dark.';
-- ============================================================
-- Lunar phase functions (4)
-- ============================================================
CREATE FUNCTION moon_phase_angle(timestamptz) RETURNS float8
AS 'MODULE_PATHNAME', 'moon_phase_angle'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION moon_phase_angle(timestamptz) IS
'Sun-Earth-Moon phase angle in degrees [0,360). 0=new, 90=first quarter, 180=full, 270=last quarter.';
CREATE FUNCTION moon_illumination(timestamptz) RETURNS float8
AS 'MODULE_PATHNAME', 'moon_illumination'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION moon_illumination(timestamptz) IS
'Illuminated fraction of the Moon disk [0.0, 1.0].';
CREATE FUNCTION moon_phase_name(timestamptz) RETURNS text
AS 'MODULE_PATHNAME', 'moon_phase_name'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION moon_phase_name(timestamptz) IS
'Moon phase name: new_moon, waxing_crescent, first_quarter, waxing_gibbous, full_moon, waning_gibbous, last_quarter, waning_crescent.';
CREATE FUNCTION moon_age(timestamptz) RETURNS float8
AS 'MODULE_PATHNAME', 'moon_age'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION moon_age(timestamptz) IS
'Days since last new moon [0, ~29.53), approximated from phase angle.';
-- ============================================================
-- Planet magnitude (1)
-- ============================================================
CREATE FUNCTION planet_magnitude(int4, timestamptz) RETURNS float8
AS 'MODULE_PATHNAME', 'planet_magnitude'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
COMMENT ON FUNCTION planet_magnitude(int4, timestamptz) IS
'Apparent visual magnitude of a planet (Mallama & Hilton 2018). Body IDs 1-8. Saturn ring tilt not modeled.';