Low-level facade: apparent positions, phase, rises and sets.
This is where UT and TT are reconciled. Every public function in this
module takes a Julian day in UT and applies ΔT itself before calling
GreenCal.Astro.Sun / GreenCal.Astro.Moon.
For the garden-oriented API, see GreenCal.
Summary
Functions
Perigee and apogee instants between two UT Julian days.
Lunar standstill instants between two UT Julian days: the extrema of the
Moon's declination, i.e. the exact moments the Moon switches from
ascending to descending (:northernmost) and back (:southernmost).
Apparent position of the Moon for a UT Julian day.
Rises, sets and meridian transit of the Moon between two UT Julian days.
Lunar node crossings between two UT Julian days.
Elongation, phase angle and illuminated fraction of the Moon.
Exact instants of the principal lunar phases between two UT Julian days.
Phase name from the elongation λ☾ − λ☉, in eight sectors.
Apparent position of the Sun for a UT Julian day.
Rises, sets and meridian transit of the Sun between two UT Julian days.
Dawn and dusk for a given solar altitude.
Functions
@spec apsis_events(float(), float(), keyword()) :: [ %{type: :perigee | :apogee, jd: float(), distance_km: float()} ]
Perigee and apogee instants between two UT Julian days.
Extrema of the Earth–Moon distance (anomalistic month, 27.55 days),
located as zero crossings of the centered derivative. Returns
%{type: :perigee | :apogee, jd: float, distance_km: float} in
chronological order.
@spec declination_extrema(float(), float(), keyword()) :: [ %{type: :northernmost | :southernmost, jd: float(), declination: float()} ]
Lunar standstill instants between two UT Julian days: the extrema of the
Moon's declination, i.e. the exact moments the Moon switches from
ascending to descending (:northernmost) and back (:southernmost).
This is the boundary printed in biodynamic sowing calendars. Half a
tropical month (~13.7 days) apart. Returns
%{type: :northernmost | :southernmost, jd: float, declination: float}.
@spec moon( float(), keyword() ) :: GreenCal.Astro.Moon.position()
Apparent position of the Moon for a UT Julian day.
@spec moon_events({number(), number()}, float(), float(), keyword()) :: GreenCal.Astro.RiseSet.result()
Rises, sets and meridian transit of the Moon between two UT Julian days.
Here h₀ depends on the instantaneous distance (parallax), so it is
recomputed at every evaluation — see
GreenCal.Astro.Moon.horizon_altitude/1.
@spec node_crossings(float(), float(), keyword()) :: [ %{type: :ascending | :descending, jd: float()} ]
Lunar node crossings between two UT Julian days.
A node crossing is the instant the Moon crosses the ecliptic plane
(ecliptic latitude β = 0): :ascending when β turns positive,
:descending when it turns negative. They occur every ~13.6 days
(half a draconic month) and are geocentric — no location involved.
Biodynamic calendars mark the hours around a node crossing as unfavorable for sowing; eclipses can only happen near one.
Returns a list of %{type: :ascending | :descending, jd: float} in
chronological order.
@spec phase( float(), keyword() ) :: %{ elongation: float(), phase_angle: float(), illuminated_fraction: float(), angular_separation: float() }
Elongation, phase angle and illuminated fraction of the Moon.
The phase angle follows Meeus 48.3, using the true Earth–Sun and Earth–Moon distances rather than the approximate series of chapter 47: more accurate, and free since the Sun is computed anyway.
:elongation is the ecliptic longitude difference λ☾ − λ☉ reduced into
[0, 360) — this, not the true angular elongation, is what defines the
phases (0 = new moon, 180 = full moon).
@spec phase_events(float(), float(), keyword()) :: [ %{type: atom(), jd: float(), eclipse: :none | :possible | :likely} ]
Exact instants of the principal lunar phases between two UT Julian days.
Returns a chronological list of
%{type: :new_moon | :first_quarter | :full_moon | :last_quarter,
jd: float,
eclipse: :none | :possible | :likely}The instant is where the elongation λ☾ − λ☉ crosses 0°, 90°, 180° or 270° (the standard definition of the phases), found by bisection on the apparent longitudes — so ΔT and nutation are accounted for.
:eclipse is a screening flag, not an eclipse computation: at a new
moon (solar eclipse) or full moon (lunar eclipse), an eclipse can only
happen if the Moon is close enough to the ecliptic. |β| < 1.2° →
:likely, |β| < 1.9° → :possible (thresholds from Meeus ch. 54's
argument-of-latitude criterion). It says an eclipse happens somewhere on
Earth — visibility, magnitude and local circumstances are out of scope.
Quarters always carry :none.
Phase name from the elongation λ☾ − λ☉, in eight sectors.
Each of the four principal phases owns a 22.5° sector centered on its
exact value: :full_moon therefore names the day around the exact
instant, not just the instant.
@spec sun( float(), keyword() ) :: GreenCal.Astro.Sun.position()
Apparent position of the Sun for a UT Julian day.
@spec sun_events({number(), number()}, float(), float(), keyword()) :: GreenCal.Astro.RiseSet.result()
Rises, sets and meridian transit of the Sun between two UT Julian days.
Options: :elevation (meters, default 0), :delta_t, plus those of
GreenCal.Astro.RiseSet.search/5.
@spec twilight_events( {number(), number()}, float(), float(), atom() | number(), keyword() ) :: GreenCal.Astro.RiseSet.result()
Dawn and dusk for a given solar altitude.
Accepts :civil (−6°), :nautical (−12°), :astronomical (−18°), or a
number of degrees — e.g. 6.0 for the golden hour.
Unlike a computation derived from sunrise, this one stays valid when the Sun does not rise: civil twilight does happen above the polar circle in winter.
:elevation deliberately does not apply here: twilights are defined by
the Sun's geometric altitude, not by its visibility over the local
horizon, so observer height changes sunrise but not dawn.