Solar position, orbital mechanics, and equinox/solstice calculations.
This module implements the analytical (polynomial + periodic-term) algorithms from Jean Meeus' Astronomical Algorithms for the Sun's geometric and apparent position, declination, equation of time, and equinox/solstice events.
For sunrise and sunset calculations see Astro.Solar.SunRiseSet,
which uses the JPL DE440s ephemeris rather than the Meeus
approximations in this module.
Function groups
Position
solar_position/1— right ascension, declination and distancesolar_declination/1— declination from Julian centuriessolar_distance/1— Earth–Sun distance in AUsolar_ecliptic_longitude/1— ecliptic longitude at a momentsolar_ecliptic_longitude_after/2,estimate_prior_solar_ecliptic_longitude/2
Apparent longitude and related
sun_apparent_longitude/1— apparent longitude (nutation + aberration corrected)sun_apparent_longitude_alt/1— higher-precision 49-term series (Meeus Table 25.D)sun_true_longitude/1,sun_equation_of_center/1sun_geometric_mean_longitude/1,sun_geometric_mean_anomaly/1aberration/1
Time and geometry
equation_of_time/1— difference between apparent and mean solar timesolar_noon_utc/2— UTC solar noon for a given longitudeearth_orbit_eccentricity/1obliquity_correction/1,mean_obliquity_of_ecliptic/1
Equinoxes and solstices
equinox_and_solstice/2— March/September equinox or June/December solstice
Solar elevation
solar_elevation/1— zenith angle for geometric, civil, nautical, astronomical twilight or a custom elevation
Time conventions
Functions in this module accept either a moment (fractional days
since epoch) or Julian centuries from J2000.0, as noted in each
function's documentation. Use Astro.Time.julian_centuries_from_moment/1
to convert between the two.
Summary
Functions
Returns the Earth's orbital eccentricity.
Returns the equation of time in minutes.
Returns the UTC datetime of an equinox or solstice.
Returns an approximate moment at or before t
when the solar ecliptic longitude just exceeded lambda degrees.
Returns the mean obliquity of the ecliptic in degrees.
Returns the corrected obliquity of the ecliptic in degrees.
Returns the solar declination in degrees.
Returns the solar ecliptic longitude in degrees.
Returns the moment (UT) of the first time at or after moment t
when the solar ecliptic longitude will be lambda degrees.
Returns solar noon as minutes since midnight UTC.
Returns the Sun's apparent longitude in degrees.
Returns the Sun's equation of the centre in degrees.
Returns the Sun's geometric mean anomaly in degrees.
Returns the Sun's geometric mean longitude in degrees.
Returns the Sun's true longitude in degrees.
Functions
Returns the Earth's orbital eccentricity.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- a unitless value of eccentricity as a
float. A value of 0 is a circular orbit, values between 0 and 1 form an elliptic orbit, 1 is a parabolic escape orbit, and greater than 1 is a hyperbola. Earth's current eccentricity is approximately 0.0167.
Examples
iex> Astro.Solar.earth_orbit_eccentricity(0.0)
0.016708634
Returns the equation of time in minutes.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the discrepancy between apparent solar time and
mean solar time in minutes as a
float. A positive value means the sundial is ahead of the clock.
Notes
The equation of time describes the discrepancy between apparent solar time (which directly tracks the Sun's diurnal motion) and mean solar time (which tracks a theoretical mean Sun with uniform motion).
During a year the equation of time ranges from about +16 min 33 s (around 3 November) to −14 min 6 s (around 11 February), with zeros near 15 April, 13 June, 1 September, and 25 December.
The two principal causes are the obliquity of the ecliptic (~23.44°) and the eccentricity of the Earth's orbit (~0.0167).
Examples
iex> Astro.Solar.equation_of_time(0.0)
-3.3012588023605938
@spec equinox_and_solstice(pos_integer(), :march | :june | :september | :december) :: {:ok, DateTime.t()}
Returns the UTC datetime of an equinox or solstice.
Arguments
yearis a positive integer Gregorian year.eventis one of:march,:june,:september, or:decemberidentifying the equinox or solstice.
Returns
{:ok, datetime}wheredatetimeis aDateTime.t()in UTC.
Notes
The :march and :september events are the equinoxes
(Sun's ecliptic longitude 0° and 180° respectively).
The :june and :december events are the solstices
(ecliptic longitude 90° and 270°).
Examples
iex> {:ok, dt} = Astro.Solar.equinox_and_solstice(2024, :march)
iex> dt.year
2024
iex> dt.month
3
iex> dt.day
20
Returns an approximate moment at or before t
when the solar ecliptic longitude just exceeded lambda degrees.
Arguments
lambdais the target solar ecliptic longitude in degrees.tis any moment in time expressed as a moment (fractional days since the epoch).
Returns
- the approximate moment (fractional days since the epoch)
at or before
twhen the solar ecliptic longitude last exceededlambdadegrees.
Examples
# Estimate when the Sun last passed 90° before the June solstice
iex> moment = Astro.Time.date_time_to_moment(~D[2024-06-21])
iex> result = Astro.Solar.estimate_prior_solar_ecliptic_longitude(90, moment)
iex> {:ok, dt} = Astro.Time.date_time_from_moment(result)
iex> dt.year
2024
iex> dt.month
6
Returns the mean obliquity of the ecliptic in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the mean obliquity of the ecliptic in degrees
as a
float.
Notes
Obliquity is the angle between the Earth's rotational
axis and the perpendicular to its orbital plane. Earth's
current mean obliquity is about 23.44° and decreasing
very slowly over millennia. This function returns the
mean value without the short-period nutation correction;
see obliquity_correction/1 for the corrected value.
Examples
iex> Astro.Solar.mean_obliquity_of_ecliptic(0.0)
23.43929111111111
Returns the corrected obliquity of the ecliptic in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the corrected obliquity of the ecliptic in degrees
as a
float.
Notes
The corrected obliquity accounts for the nutation in obliquity (a short-period oscillation), in addition to the mean obliquity which changes slowly over millennia.
Examples
iex> Astro.Solar.obliquity_correction(0.0)
23.437821291789415
Returns the solar declination in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the solar declination in degrees as a
float.
Notes
The solar declination is the angle between the direction of the centre of the solar disk measured from Earth's centre and the equatorial plane. It ranges from approximately +23.44° at the June solstice to −23.44° at the December solstice, and is 0° at the equinoxes.
Examples
iex> Astro.Solar.solar_declination(0.0)
...> |> Float.round(4)
-23.0325
Returns the solar ecliptic longitude in degrees.
Arguments
tis any moment in time expressed as a moment (fractional days since the epoch).
Returns
- the solar ecliptic longitude in degrees as a
float, in the range 0..360.
Notes
The solar ecliptic longitude is the position of the Sun on the celestial sphere along the ecliptic. It is also an effective measure of the position of the Earth in its orbit around the Sun, taken as 0° at the moment of the vernal equinox.
Since it is based on how far the Earth has moved in its orbit since the equinox, it is a measure of what time of the tropical year (the year of seasons) has elapsed, without the inaccuracies of a calendar date which is perturbed by leap years and calendar imperfections.
Examples
iex> moment = Astro.Time.date_time_to_moment(~D[2024-03-20])
iex> Astro.Solar.solar_ecliptic_longitude(moment)
359.87362951019264
@spec solar_ecliptic_longitude_after(number(), Astro.Time.time()) :: Astro.Time.time()
Returns the moment (UT) of the first time at or after moment t
when the solar ecliptic longitude will be lambda degrees.
Arguments
lambdais the target solar ecliptic longitude in degrees.tis any moment in time expressed as a moment (fractional days since the epoch).
Returns
- the moment (fractional days since the epoch) when
the solar ecliptic longitude reaches
lambdadegrees.
Examples
# Find the June solstice (longitude 90°) in 2024
iex> moment = Astro.Time.date_time_to_moment(~D[2024-05-22])
iex> result = Astro.Solar.solar_ecliptic_longitude_after(90, moment)
iex> {:ok, dt} = Astro.Time.date_time_from_moment(result)
iex> dt.year
2024
iex> dt.month
6
@spec solar_noon_utc(float(), Astro.longitude()) :: float()
Returns solar noon as minutes since midnight UTC.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.longitudeis the longitude in degrees of the location from which solar noon is to be measured. West is negative.
Returns
- solar noon as a
floatnumber of minutes since midnight UTC.
Notes
Solar noon is the moment when the Sun passes a location's meridian and reaches its highest position in the sky. In most cases it does not occur at 12:00 local time.
Examples
iex> Astro.Solar.solar_noon_utc(0.0, 151.2093)
1328.3378566361976
@spec sun_apparent_longitude(Astro.Time.julian_centuries()) :: float()
Returns the Sun's apparent longitude in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the Sun's apparent longitude in degrees as a
float, in the range 0..360.
Notes
The apparent longitude is the Sun's celestial longitude corrected for aberration and nutation, as opposed to mean longitude.
An equinox is the instant when the Sun's apparent geocentric longitude is 0° (northward equinox) or 180° (southward equinox).
Examples
iex> Astro.Solar.sun_apparent_longitude(0.0)
280.3725548788095
Returns the Sun's equation of the centre in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the equation of the centre in degrees as a
float.
Notes
In two-body Keplerian orbital mechanics, the equation of the centre is the angular difference between the actual position of a body in its elliptical orbit and the position it would occupy if its motion were uniform, in a circular orbit of the same period. It is defined as the difference between the true anomaly ν and the mean anomaly M.
Examples
iex> Astro.Solar.sun_equation_of_center(0.0)
-0.08430148943719645
Returns the Sun's geometric mean anomaly in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the mean anomaly in degrees as a
float, in the range 0..360.
Notes
In celestial mechanics, the mean anomaly is the fraction of an elliptical orbit's period that has elapsed since the orbiting body passed periapsis, expressed as an angle. It is the angular distance from the pericentre which a fictitious body would have if it moved in a circular orbit, with constant speed, in the same orbital period as the actual body in its elliptical orbit.
Examples
iex> Astro.Solar.sun_geometric_mean_anomaly(0.0)
357.52911
Returns the Sun's geometric mean longitude in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the mean solar longitude in degrees as a
float, in the range 0..360.
Notes
Mean longitude is a convenient uniform measure of how far around its orbit a body has progressed since passing the reference direction. While mean longitude assumes constant speed, true longitude accounts for the body's actual speed which varies around its elliptical orbit. The difference between the two is the equation of the centre.
Examples
iex> Astro.Solar.sun_geometric_mean_longitude(0.0)
280.46646
Returns the Sun's true longitude in degrees.
Arguments
julian_centuriesis any moment in time expressed as Julian centuries from J2000.0.
Returns
- the Sun's true longitude in degrees as a
float.
Notes
In celestial mechanics, true longitude is the ecliptic longitude at which an orbiting body could actually be found if its inclination were zero. It is the sum of the geometric mean longitude and the equation of the centre.
Examples
iex> Astro.Solar.sun_true_longitude(0.0)
280.38215851056276