Skip to content

Functions: Rise/Set & Constellations

Functions for predicting when celestial bodies rise and set, and for identifying which constellation a sky coordinate falls in. Rise/set prediction uses bisection search on elevation with a 7-day search window. Constellation identification uses the Roman (1987) boundary table (CDS VI/42, 357 segments), precessing input coordinates to B1875.0 internally.


Returns the next geometric sunrise after the given time. The geometric horizon is 0 degrees --- no refraction or semidiameter correction.

sun_next_rise(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next sunrise, or NULL if the Sun does not rise within 7 days (circumpolar or never-rises).

-- Next sunrise from Boise
SELECT sun_next_rise('43.7N 116.4W 800m'::observer, now());

Returns the next geometric sunset after the given time.

sun_next_set(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next sunset, or NULL if the Sun does not set within 7 days.

-- How long until sunset?
SELECT sun_next_set('43.7N 116.4W 800m'::observer, now()) - now() AS time_until_sunset;

Returns the next geometric moonrise after the given time.

moon_next_rise(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next moonrise, or NULL if the Moon does not rise within 7 days.

-- Next moonrise
SELECT moon_next_rise('40.0N 105.3W 1655m'::observer, now());

Returns the next geometric moonset after the given time.

moon_next_set(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next moonset, or NULL if the Moon does not set within 7 days.

-- Moon visibility window
SELECT moon_next_rise('40.0N 105.3W 1655m'::observer, now()) AS moonrise,
moon_next_set('40.0N 105.3W 1655m'::observer, now()) AS moonset;

Returns the next geometric rise time for a planet after the given time.

planet_next_rise(body_id int4, obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
body_idint4Planet identifier: 1=Mercury, 2=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next rise, or NULL if the planet does not rise within 7 days. Raises an error for invalid body_id (0=Sun, 3=Earth, 10=Moon have dedicated functions).

-- When does Jupiter rise tonight?
SELECT planet_next_rise(5, '43.7N 116.4W 800m'::observer, now());

Returns the next geometric set time for a planet after the given time.

planet_next_set(body_id int4, obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
body_idint4Planet identifier: 1=Mercury, 2=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next set, or NULL if the planet does not set within 7 days.

-- Venus visibility window
SELECT planet_next_rise(2, '43.7N 116.4W 800m'::observer, now()) AS venus_rise,
planet_next_set(2, '43.7N 116.4W 800m'::observer, now()) AS venus_set;

Returns the next refracted sunrise after the given time. The threshold is -0.833 degrees geometric elevation, accounting for atmospheric refraction (0.569 deg) and the Sun’s semidiameter (0.266 deg). Refracted sunrise is earlier than geometric sunrise.

sun_next_rise_refracted(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted sunrise, or NULL if the Sun does not rise within 7 days.

-- Refracted vs geometric sunrise difference
SELECT sun_next_rise_refracted(obs, t) AS refracted,
sun_next_rise(obs, t) AS geometric
FROM (VALUES ('43.7N 116.4W 800m'::observer, '2024-01-15 00:00:00+00'::timestamptz)) AS v(obs, t);

Returns the next refracted sunset after the given time. Uses the same -0.833 degree threshold. Refracted sunset is later than geometric sunset.

sun_next_set_refracted(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted sunset, or NULL if the Sun does not set within 7 days.

-- How much longer is the refracted day?
SELECT sun_next_set_refracted(obs, t) - sun_next_rise_refracted(obs, t) AS refracted_day,
sun_next_set(obs, t) - sun_next_rise(obs, t) AS geometric_day
FROM (VALUES ('43.7N 116.4W 800m'::observer, '2024-03-20 00:00:00+00'::timestamptz)) AS v(obs, t);

Returns the next refracted moonrise after the given time. Uses the -0.833 degree threshold (refraction + semidiameter).

moon_next_rise_refracted(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted moonrise, or NULL if the Moon does not rise within 7 days.

SELECT moon_next_rise_refracted('40.0N 105.3W 1655m'::observer, now());

Returns the next refracted moonset after the given time. Uses the -0.833 degree threshold.

moon_next_set_refracted(obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted moonset, or NULL if the Moon does not set within 7 days.

SELECT moon_next_set_refracted('40.0N 105.3W 1655m'::observer, now());

Returns the next refracted rise time for a planet after the given time. The threshold is -0.569 degrees geometric elevation, accounting for atmospheric refraction only (planets are point sources).

planet_next_rise_refracted(body_id int4, obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
body_idint4Planet identifier: 1=Mercury, 2=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted rise, or NULL if the planet does not rise within 7 days.

-- Refracted vs geometric rise for Saturn
SELECT planet_next_rise_refracted(6, obs, t) AS refracted,
planet_next_rise(6, obs, t) AS geometric
FROM (VALUES ('43.7N 116.4W 800m'::observer, now())) AS v(obs, t);

Returns the next refracted set time for a planet after the given time. Uses the -0.569 degree threshold.

planet_next_set_refracted(body_id int4, obs observer, t timestamptz) → timestamptz
ParameterTypeDescription
body_idint4Planet identifier: 1=Mercury, 2=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune
obsobserverObserver location
ttimestamptzSearch start time

The timestamptz of the next refracted set, or NULL if the planet does not set within 7 days.

-- Mars visibility tonight (refracted)
SELECT planet_next_rise_refracted(4, obs, t) AS mars_rise,
planet_next_set_refracted(4, obs, t) AS mars_set
FROM (VALUES ('43.7N 116.4W 800m'::observer, now())) AS v(obs, t);

Reports whether the Sun rises and sets, is circumpolar, or never rises at the given location and time. Samples elevation at 48 points across 24 hours.

sun_rise_set_status(obs observer, t timestamptz) → text
ParameterTypeDescription
obsobserverObserver location
ttimestamptzReference time (defines the 24h sampling window)

One of three text values: 'rises_and_sets', 'circumpolar', or 'never_rises'.

-- Why doesn't the Sun set? (Arctic summer)
SELECT sun_rise_set_status('70N 25E 0m'::observer, '2024-06-21 00:00:00+00'::timestamptz);
-- → 'circumpolar'
-- Normal mid-latitude behavior
SELECT sun_rise_set_status('43.7N 116.4W 800m'::observer, now());
-- → 'rises_and_sets'

Reports whether the Moon rises and sets, is circumpolar, or never rises at the given location and time.

moon_rise_set_status(obs observer, t timestamptz) → text
ParameterTypeDescription
obsobserverObserver location
ttimestamptzReference time

One of three text values: 'rises_and_sets', 'circumpolar', or 'never_rises'.

-- Check Moon status before querying rise/set
SELECT moon_rise_set_status('80N 0E 0m'::observer, now()) AS status,
moon_next_rise('80N 0E 0m'::observer, now()) AS next_rise;

Reports whether a planet rises and sets, is circumpolar, or never rises at the given location and time.

planet_rise_set_status(body_id int4, obs observer, t timestamptz) → text
ParameterTypeDescription
body_idint4Planet identifier: 1=Mercury, 2=Venus, 4=Mars, 5=Jupiter, 6=Saturn, 7=Uranus, 8=Neptune
obsobserverObserver location
ttimestamptzReference time

One of three text values: 'rises_and_sets', 'circumpolar', or 'never_rises'.

-- Check all planets' status from a high-latitude site
SELECT body_id, name,
planet_rise_set_status(body_id, '65N 18W 0m'::observer, now()) AS status
FROM (VALUES (1,'Mercury'),(2,'Venus'),(4,'Mars'),(5,'Jupiter'),
(6,'Saturn'),(7,'Uranus'),(8,'Neptune')) AS p(body_id, name);

Returns the 3-letter IAU constellation abbreviation for a sky position. Uses the Roman (1987) boundary table (CDS VI/42) with 357 boundary segments. Input coordinates are precessed from J2000 to B1875.0 internally to match the boundary epoch.

constellation(eq equatorial) → text
constellation(ra_hours float8, dec_deg float8) → text

Overload 1 --- from equatorial type:

ParameterTypeDescription
eqequatorialEquatorial sky position (RA in hours, Dec in degrees)

Overload 2 --- from explicit coordinates:

ParameterTypeUnitDescription
ra_hoursfloat8hoursRight ascension in J2000, range [0, 24)
dec_degfloat8degreesDeclination in J2000, range [-90, 90]

A 3-letter IAU constellation abbreviation (e.g., 'Ori', 'UMa', 'Sgr'). There are 88 possible values, one for every IAU constellation.

-- What constellation is Jupiter in?
SELECT constellation(planet_equatorial(5, now()));
-- → 'Ari'
-- Polaris
SELECT constellation(2.5303, 89.2641);
-- → 'UMi'
-- Orion's belt star Alnitak
SELECT constellation(5.679, -1.943);
-- → 'Ori'

Converts a 3-letter IAU constellation abbreviation to its full IAU name.

constellation_full_name(abbr text) → text
ParameterTypeDescription
abbrtext3-letter IAU abbreviation (e.g., 'Ori', 'UMa')

The full IAU constellation name (e.g., 'Orion', 'Ursa Major'), or NULL if the abbreviation is not recognized.

-- Full name for display
SELECT constellation_full_name(constellation(planet_equatorial(5, now())));
-- → 'Aries'
-- All 88 constellations (abbreviated sample)
SELECT constellation_full_name('Ori') AS orion,
constellation_full_name('UMa') AS ursa_major,
constellation_full_name('Sgr') AS sagittarius,
constellation_full_name('Crx') AS invalid;
-- → 'Orion', 'Ursa Major', 'Sagittarius', NULL
-- What constellation is each planet in right now?
SELECT name,
constellation(planet_equatorial(body_id, now())) AS abbr,
constellation_full_name(constellation(planet_equatorial(body_id, now()))) AS constellation
FROM (VALUES (1,'Mercury'),(2,'Venus'),(4,'Mars'),(5,'Jupiter'),
(6,'Saturn'),(7,'Uranus'),(8,'Neptune')) AS p(body_id, name);