-- v017_features.sql -- Tests for v0.17.0: solar elongation, planet phase, -- satellite eclipse, observing night quality, lunar libration -- -- Verifies all 12 new functions added in v0.17.0. CREATE EXTENSION IF NOT EXISTS pg_orrery; NOTICE: extension "pg_orrery" already exists, skipping -- ============================================================ -- Solar elongation: Mercury always < 28 deg -- ============================================================ SELECT solar_elongation(1, '2024-01-15 00:00:00+00'::timestamptz) < 28.0 AS mercury_max_elongation; mercury_max_elongation ------------------------ t (1 row) -- ============================================================ -- Solar elongation: Venus always < 47 deg -- ============================================================ SELECT solar_elongation(2, '2024-01-15 00:00:00+00'::timestamptz) < 47.5 AS venus_max_elongation; venus_max_elongation ---------------------- t (1 row) -- ============================================================ -- Solar elongation: Mars can exceed 90 deg (superior planet) -- Use a date near opposition (2024-01-12 Mars at elongation ~180) -- At least verify it can be large for outer planets -- ============================================================ SELECT solar_elongation(4, '2024-12-08 00:00:00+00'::timestamptz) > 50.0 AS mars_large_elongation; mars_large_elongation ----------------------- t (1 row) -- ============================================================ -- Solar elongation: always [0, 180] -- ============================================================ SELECT bool_and( solar_elongation(body_id, '2024-06-15 00:00:00+00'::timestamptz) >= 0.0 AND solar_elongation(body_id, '2024-06-15 00:00:00+00'::timestamptz) <= 180.0 ) AS elongation_in_range FROM (VALUES (1),(2),(4),(5),(6),(7),(8)) AS t(body_id); elongation_in_range --------------------- t (1 row) -- ============================================================ -- Solar elongation: error on body_id 0, 3, 9 -- ============================================================ DO $$ BEGIN PERFORM solar_elongation(0, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=0: %', SQLERRM; END $$; NOTICE: elong body_id=0: solar_elongation: body_id 0 must be 1-8 (Mercury-Neptune) DO $$ BEGIN PERFORM solar_elongation(3, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=3: %', SQLERRM; END $$; NOTICE: elong body_id=3: solar_elongation: cannot compute for Earth from Earth DO $$ BEGIN PERFORM solar_elongation(9, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'elong body_id=9: %', SQLERRM; END $$; NOTICE: elong body_id=9: solar_elongation: body_id 9 must be 1-8 (Mercury-Neptune) -- ============================================================ -- Planet phase: Jupiter always near 1.0 (outer planet) -- ============================================================ SELECT planet_phase(5, '2024-01-15 00:00:00+00'::timestamptz) > 0.95 AS jupiter_nearly_full; jupiter_nearly_full --------------------- t (1 row) -- ============================================================ -- Planet phase: Neptune always near 1.0 -- ============================================================ SELECT planet_phase(8, '2024-06-15 00:00:00+00'::timestamptz) > 0.99 AS neptune_nearly_full; neptune_nearly_full --------------------- t (1 row) -- ============================================================ -- Planet phase: Venus varies significantly (inner planet) -- Check it's in valid range -- ============================================================ SELECT planet_phase(2, '2024-06-01 12:00:00+00'::timestamptz) BETWEEN 0.0 AND 1.0 AS venus_phase_valid; venus_phase_valid ------------------- t (1 row) -- ============================================================ -- Planet phase: always [0, 1] for all planets -- ============================================================ SELECT bool_and( planet_phase(body_id, '2024-01-15 00:00:00+00'::timestamptz) >= 0.0 AND planet_phase(body_id, '2024-01-15 00:00:00+00'::timestamptz) <= 1.0 ) AS phase_in_range FROM (VALUES (1),(2),(4),(5),(6),(7),(8)) AS t(body_id); phase_in_range ---------------- t (1 row) -- ============================================================ -- Planet phase: error cases match elongation -- ============================================================ DO $$ BEGIN PERFORM planet_phase(3, '2024-01-15 00:00:00+00'::timestamptz); EXCEPTION WHEN OTHERS THEN RAISE NOTICE 'phase body_id=3: %', SQLERRM; END $$; NOTICE: phase body_id=3: planet_phase: cannot compute for Earth from Earth -- ============================================================ -- Satellite eclipse: ISS point-in-time test -- (At night the ISS can be eclipsed; just verify function returns bool) -- ============================================================ SELECT satellite_is_eclipsed( E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle, '2024-01-01 12:00:00+00'::timestamptz ) IS NOT NULL AS eclipse_returns_bool; eclipse_returns_bool ---------------------- t (1 row) -- ============================================================ -- Satellite eclipse: next entry/exit return timestamps or NULL -- ============================================================ SELECT satellite_next_eclipse_entry( E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle, '2024-01-01 12:00:00+00'::timestamptz ) > '2024-01-01 12:00:00+00'::timestamptz AS entry_in_future; entry_in_future ----------------- t (1 row) SELECT satellite_next_eclipse_exit( E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle, '2024-01-01 12:00:00+00'::timestamptz ) > '2024-01-01 12:00:00+00'::timestamptz AS exit_in_future; exit_in_future ---------------- t (1 row) -- ============================================================ -- Satellite eclipse: fraction in [0, 1] for a 2-hour window -- ============================================================ SELECT satellite_eclipse_fraction( E'1 25544U 98067A 24001.50000000 .00016717 00000-0 10270-3 0 9025\n2 25544 51.6400 208.9163 0006703 30.1694 61.7520 15.50100486 00001'::tle, '2024-01-01 12:00:00+00'::timestamptz, '2024-01-01 14:00:00+00'::timestamptz ) BETWEEN 0.0 AND 1.0 AS eclipse_fraction_valid; eclipse_fraction_valid ------------------------ t (1 row) -- ============================================================ -- Observing night quality: polar summer at 65N = 'poor' -- (no astronomical darkness in June) -- ============================================================ SELECT observing_night_quality('(65.0,25.0,0)'::observer, '2024-06-21 12:00:00+00'::timestamptz) = 'poor' AS polar_summer_poor; polar_summer_poor ------------------- t (1 row) -- ============================================================ -- Observing night quality: winter mid-latitude returns valid rating -- ============================================================ SELECT observing_night_quality('(43.7,-116.4,800)'::observer, '2024-12-21 12:00:00+00'::timestamptz) IN ('excellent', 'good', 'fair', 'poor') AS winter_valid_rating; winter_valid_rating --------------------- t (1 row) -- ============================================================ -- Lunar libration: longitude in [-8, 8] range -- ============================================================ SELECT moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -8.5 AND 8.5 AS libration_lon_in_range; libration_lon_in_range ------------------------ t (1 row) SELECT moon_libration_longitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN -8.5 AND 8.5 AS libration_lon_in_range_2; libration_lon_in_range_2 -------------------------- t (1 row) -- ============================================================ -- Lunar libration: latitude in [-7, 7] range -- ============================================================ SELECT moon_libration_latitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -7.5 AND 7.5 AS libration_lat_in_range; libration_lat_in_range ------------------------ t (1 row) SELECT moon_libration_latitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN -7.5 AND 7.5 AS libration_lat_in_range_2; libration_lat_in_range_2 -------------------------- t (1 row) -- ============================================================ -- Lunar libration: position angle in [0, 360) -- ============================================================ SELECT moon_libration_position_angle('2024-01-15 00:00:00+00'::timestamptz) BETWEEN -1.0 AND 361.0 AS libration_pa_in_range; libration_pa_in_range ----------------------- t (1 row) -- ============================================================ -- Lunar libration: composite returns same as individual functions -- ============================================================ SELECT abs((moon_libration('2024-01-15 00:00:00+00'::timestamptz)).l - moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz)) < 0.001 AS composite_matches_lon; composite_matches_lon ----------------------- t (1 row) SELECT abs((moon_libration('2024-01-15 00:00:00+00'::timestamptz)).b - moon_libration_latitude('2024-01-15 00:00:00+00'::timestamptz)) < 0.001 AS composite_matches_lat; composite_matches_lat ----------------------- t (1 row) -- ============================================================ -- Lunar libration: changes over time (not constant) -- ============================================================ SELECT moon_libration_longitude('2024-01-01 00:00:00+00'::timestamptz) != moon_libration_longitude('2024-01-15 00:00:00+00'::timestamptz) AS libration_varies; libration_varies ------------------ t (1 row) -- ============================================================ -- Subsolar longitude: in [0, 360) range -- ============================================================ SELECT moon_subsolar_longitude('2024-01-15 00:00:00+00'::timestamptz) BETWEEN 0.0 AND 360.0 AS subsolar_in_range; subsolar_in_range ------------------- t (1 row) SELECT moon_subsolar_longitude('2024-06-15 00:00:00+00'::timestamptz) BETWEEN 0.0 AND 360.0 AS subsolar_in_range_2; subsolar_in_range_2 --------------------- t (1 row) -- ============================================================ -- Subsolar longitude: changes significantly over synodic month -- (full 360 degrees over ~29.5 days) -- ============================================================ SELECT abs(moon_subsolar_longitude('2024-01-01 00:00:00+00'::timestamptz) - moon_subsolar_longitude('2024-01-15 00:00:00+00'::timestamptz)) > 10.0 AS subsolar_moves; subsolar_moves ---------------- t (1 row)