Astro.Time (ex_astro v0.3.0)

View Source

Convert between calendar dates, split Julian Dates, astronomical time scales, and SPICE ephemeris time.

This module uses ERFA's two-part Julian Date representation throughout the public Julian Date API. A Julian Date is therefore represented as {jd1, jd2} rather than a single float.

Supported time scales include:

  • Coordinated Universal Time (UTC)
  • International Atomic Time (TAI)
  • Terrestrial Time (TT)
  • Geocentric Coordinate Time (TCG)
  • Barycentric Dynamical Time (TDB)
  • Barycentric Coordinate Time (TCB)
  • SPICE Ephemeris Time (ET, TDB seconds past J2000)

Why Split Julian Dates?

A single floating-point Julian Date loses precision near modern epochs. ERFA/SOFA avoid that by splitting the value into two parts whose sum is the full Julian Date. This representation preserves sub-microsecond detail for precision-sensitive conversions such as TT <-> TDB.

The split itself is not canonical. Different functions may return equivalent pairs whose sums match the same physical Julian Date.

Conventions

  • JD-based functions accept and return {jd1, jd2}.
  • str2et/1 and utc2et/1 return scalar ephemeris seconds.
  • unitim/3 remains a low-level SPICE primitive and uses scalar numeric epochs because the accepted units are not all Julian Dates.
  • jd_to_float/1 and jd_from_float/1 are explicit interop helpers for code that still needs a single float.
  • Native string inputs must be non-empty binaries without embedded NUL bytes. str2et/1 accepts up to 256 bytes, utc2et/1 accepts up to 80 bytes, and unitim/3 time-system names accept up to 5 bytes. Invalid native strings raise ArgumentError.

Example

iex> jd_utc = Astro.Time.dtf2d(2000, 1, 1, 12, 0, 0.0)
iex> Astro.Time.jd_to_float(jd_utc)
2451545.0
iex> tai = Astro.Time.utc2tai(jd_utc)
iex> tt = Astro.Time.tai2tt(tai)
iex> Astro.Time.jd_to_float(tt) > Astro.Time.jd_to_float(tai)
true

iex> Astro.Time.str2et("2000 JAN 01 12:00:00 TDB")
0.0

Summary

Functions

Convert a split Julian Date to seconds past J2000.

Convert a Gregorian UTC date and time to a split Julian Date.

Convert SPICE Ephemeris Time (ET, TDB seconds past J2000) to a UTC NaiveDateTime.

Convert a split Julian Date to Gregorian calendar components.

Wrap a single float Julian Date as {jd, 0.0}.

Collapse a split Julian Date to a single float.

Convert seconds past J2000 to a split Julian Date.

Parse a time string and convert it to SPICE Ephemeris Time (ET).

Convert a TAI split Julian Date to Terrestrial Time (TT).

Convert a TAI split Julian Date to UTC.

Convert a TCB split Julian Date to TDB.

Convert a TCG split Julian Date to TT.

Convert a TDB split Julian Date to Barycentric Coordinate Time (TCB).

Convert a TDB split Julian Date to TT using geocentric observer terms.

Convert a TDB split Julian Date to TT using explicit observer terms for ERFA's eraDtdb model.

Convert a split Julian Date to a NaiveDateTime.

Convert a DateTime or NaiveDateTime to SPICE Ephemeris Time (ET).

Convert a DateTime or NaiveDateTime to a split Julian Date.

Convert a TT split Julian Date to TAI.

Convert a TT split Julian Date to Geocentric Coordinate Time (TCG).

Convert a TT split Julian Date to Barycentric Dynamical Time (TDB) using geocentric observer terms.

Convert a TT split Julian Date to TDB using explicit observer terms for ERFA's eraDtdb model.

Convert an epoch between SPICE uniform numeric time systems.

Convert a UTC time string to SPICE Ephemeris Time (ET).

Convert a UTC split Julian Date to International Atomic Time (TAI).

Types

ephemeris_time()

@type ephemeris_time() :: float()

gregorian_datetime_tuple()

@type gregorian_datetime_tuple() ::
  {year :: integer(), month :: integer(), day :: integer(), hour :: integer(),
   minute :: integer(), second :: integer(), microsecond :: integer()}

jd_part()

@type jd_part() :: float()

julian_date()

@type julian_date() :: {jd_part(), jd_part()}

kilometers()

@type kilometers() :: float()

radians()

@type radians() :: float()

uniform_time_system()

@type uniform_time_system() :: String.t()

Functions

day2sec(julian_date)

@spec day2sec(julian_date()) :: float()

Convert a split Julian Date to seconds past J2000.

Example

iex> Astro.Time.day2sec({2451545.0, 0.25})
21600.0

dtf2d(year, month, day, hour, min, sec)

@spec dtf2d(integer(), integer(), integer(), integer(), integer(), float()) ::
  julian_date()

Convert a Gregorian UTC date and time to a split Julian Date.

Example

iex> Astro.Time.dtf2d(2000, 1, 1, 12, 0, 0.0)
{2451544.5, 0.5}

from_et(et)

@spec from_et(ephemeris_time()) :: NaiveDateTime.t()

Convert SPICE Ephemeris Time (ET, TDB seconds past J2000) to a UTC NaiveDateTime.

is_jd(jd)

(macro)

jd2dt(julian_date)

Convert a split Julian Date to Gregorian calendar components.

Example

iex> Astro.Time.jd2dt({2451545.0, 0.0})
{2000, 1, 1, 12, 0, 0, 0}

jd_from_float(jd)

@spec jd_from_float(float()) :: julian_date()

Wrap a single float Julian Date as {jd, 0.0}.

This helper is intended for interop with APIs that still expose Julian Dates as one float.

jd_to_float(jd)

@spec jd_to_float(julian_date()) :: float()

Collapse a split Julian Date to a single float.

This is convenient for display or interop, but it discards the extra precision preserved by the split representation.

sec2day(seconds)

@spec sec2day(float()) :: julian_date()

Convert seconds past J2000 to a split Julian Date.

Example

iex> Astro.Time.sec2day(21600.0)
{2451545.0, 0.25}

str2et(time)

@spec str2et(String.t()) :: ephemeris_time()

Parse a time string and convert it to SPICE Ephemeris Time (ET).

Returns TDB seconds past J2000.

tai2tt(julian_date)

@spec tai2tt(julian_date()) :: julian_date()

Convert a TAI split Julian Date to Terrestrial Time (TT).

tai2utc(julian_date)

@spec tai2utc(julian_date()) :: julian_date()

Convert a TAI split Julian Date to UTC.

tcb2tdb(julian_date)

@spec tcb2tdb(julian_date()) :: julian_date()

Convert a TCB split Julian Date to TDB.

tcg2tt(julian_date)

@spec tcg2tt(julian_date()) :: julian_date()

Convert a TCG split Julian Date to TT.

tdb2tcb(julian_date)

@spec tdb2tcb(julian_date()) :: julian_date()

Convert a TDB split Julian Date to Barycentric Coordinate Time (TCB).

tdb2tt(julian_date)

@spec tdb2tt(julian_date()) :: julian_date()

Convert a TDB split Julian Date to TT using geocentric observer terms.

tdb2tt(julian_date, ut, elong, u, v)

@spec tdb2tt(julian_date(), float(), radians(), kilometers(), kilometers()) ::
  julian_date()

Convert a TDB split Julian Date to TT using explicit observer terms for ERFA's eraDtdb model.

to_datetime(julian_date)

@spec to_datetime(julian_date()) :: NaiveDateTime.t()

Convert a split Julian Date to a NaiveDateTime.

Example

iex> Astro.Time.to_datetime({2451545.0, 0.0})
~N[2000-01-01 12:00:00.000000]

to_et(dt)

@spec to_et(DateTime.t() | NaiveDateTime.t()) :: ephemeris_time()

Convert a DateTime or NaiveDateTime to SPICE Ephemeris Time (ET).

Calendar fields are interpreted as UTC. Returns TDB seconds past J2000, computed via ERFA (UTC -> TAI -> TT -> TDB), so no leap second kernel is required. Equivalent to utc2et/1 for string inputs.

to_julian_date(dt)

@spec to_julian_date(DateTime.t() | NaiveDateTime.t()) :: julian_date()

Convert a DateTime or NaiveDateTime to a split Julian Date.

Calendar fields are interpreted as UTC.

tt2tai(julian_date)

@spec tt2tai(julian_date()) :: julian_date()

Convert a TT split Julian Date to TAI.

tt2tcg(julian_date)

@spec tt2tcg(julian_date()) :: julian_date()

Convert a TT split Julian Date to Geocentric Coordinate Time (TCG).

tt2tdb(julian_date)

@spec tt2tdb(julian_date()) :: julian_date()

Convert a TT split Julian Date to Barycentric Dynamical Time (TDB) using geocentric observer terms.

tt2tdb(julian_date, ut, elong, u, v)

@spec tt2tdb(julian_date(), float(), radians(), kilometers(), kilometers()) ::
  julian_date()

Convert a TT split Julian Date to TDB using explicit observer terms for ERFA's eraDtdb model.

Inputs:

  • ut - universal time of day in seconds
  • elong - observer east longitude in radians
  • u - distance from Earth's spin axis in km
  • v - distance north of Earth's equatorial plane in km

unitim(epoch, insys, outsys)

@spec unitim(float(), uniform_time_system(), uniform_time_system()) :: float()

Convert an epoch between SPICE uniform numeric time systems.

This is the low-level SPICE interface and therefore uses scalar numeric epochs rather than split Julian Dates.

utc2et(time)

@spec utc2et(String.t()) :: ephemeris_time()

Convert a UTC time string to SPICE Ephemeris Time (ET).

Returns TDB seconds past J2000.

utc2tai(julian_date)

@spec utc2tai(julian_date()) :: julian_date()

Convert a UTC split Julian Date to International Atomic Time (TAI).