The local circumstances of a lunar eclipse: how it is seen from a place on the Earth.
A lunar eclipse is the Moon passing through the Earth's shadow, so
unlike a solar eclipse it happens at the same instants for everyone:
its contacts and greatest eclipse are those of Astro.Lunar.Eclipse.
What depends on the place is whether the Moon is above the horizon,
and how high, while it happens.
The Moon's altitude is topocentric: the Moon is close enough that seen from the Earth's surface it is displaced by up to about 1°, its horizontal parallax, from where it is seen from the Earth's centre. The observer's position, from the geodetic latitude, the Earth's flattening and the height above the ellipsoid, is subtracted from the Moon's geocentric position, both in the equatorial frame of date turned by the local apparent sidereal time, and the altitude is the angle of what remains above the plane perpendicular to the observer's vertical. It is geometric: refraction, which lifts the Moon by about 34′ at the horizon, is not applied.
An eclipse is seen if at some moment between the first and last penumbral contacts the Moon's upper limb is above the horizon, allowing for standard refraction, which is the condition for moonrise.
Summary
Types
The local circumstances of a lunar eclipse: the fields of
Astro.Lunar.Eclipse.t/0, every instant a DateTime.t/0, and
the Moon's geometric topocentric altitude in degrees at greatest
eclipse and each contact, keyed by the contact.
Functions
Returns the local circumstances at a location of a lunar eclipse.
Types
@type t() :: %Astro.Lunar.Eclipse.Local{ gamma: float(), greatest: DateTime.t(), moon_altitudes: %{required(atom()) => float()}, partial_begins: DateTime.t() | nil, partial_ends: DateTime.t() | nil, penumbral_begins: DateTime.t(), penumbral_ends: DateTime.t(), penumbral_magnitude: float(), saros: integer(), total_begins: DateTime.t() | nil, total_ends: DateTime.t() | nil, type: Astro.Lunar.Eclipse.eclipse_type(), umbral_magnitude: float() }
The local circumstances of a lunar eclipse: the fields of
Astro.Lunar.Eclipse.t/0, every instant a DateTime.t/0, and
the Moon's geometric topocentric altitude in degrees at greatest
eclipse and each contact, keyed by the contact.
Functions
@spec circumstances(map(), Geo.PointZ.t()) :: {:ok, map()} | {:error, :not_visible}
Returns the local circumstances at a location of a lunar eclipse.
Arguments
eclipseis a lunar eclipse's circumstances asAstro.Lunar.Eclipse.eclipse_at_or_after/2returns them, every instant a moment.locationis aGeo.PointZ.t/0, its altitude in metres above the ellipsoid.
Returns
{:ok, circumstances}, the eclipse's circumstances with the key:moon_altitudes, a map of the Moon's altitude in degrees at greatest eclipse and at each contact the eclipse has.{:error, :not_visible}if the Moon is below the horizon from the first penumbral contact to the last.
Examples
The total eclipse of 14 March 2025 was seen from Dallas, the Moon high in the south at greatest eclipse:
iex> {:ok, eclipse} = Astro.Lunar.Eclipse.eclipse_at_or_after(739_676.0, :danjon)
iex> dallas = %Geo.PointZ{coordinates: {-96.80, 32.78, 0.0}}
iex> {:ok, local} = Astro.Lunar.Eclipse.Local.circumstances(eclipse, dallas)
iex> Float.round(local.moon_altitudes.greatest, 1)
59.0