Skip to main content

celestial_time/scales/conversions/
mod.rs

1//! Time scale conversions between astronomical time systems.
2//!
3//! This module provides traits and implementations for converting between the eight
4//! major astronomical time scales: GPS, TAI, TT, TCG, TCB, TDB, UT1, and UTC.
5//!
6//! # Time Scale Overview
7//!
8//! | Scale | Full Name | Basis | Primary Use |
9//! |-------|-----------|-------|-------------|
10//! | UTC | Coordinated Universal Time | Atomic + leap seconds | Civil timekeeping |
11//! | TAI | International Atomic Time | Atomic clocks | Reference for other scales |
12//! | TT | Terrestrial Time | TAI + 32.184s | Geocentric ephemerides |
13//! | UT1 | Universal Time 1 | Earth rotation | Sidereal time, telescope pointing |
14//! | GPS | GPS Time | Atomic (no leap seconds) | Satellite navigation |
15//! | TCG | Geocentric Coordinate Time | Relativistic (Earth center) | Precise geocentric dynamics |
16//! | TCB | Barycentric Coordinate Time | Relativistic (solar system) | Solar system dynamics |
17//! | TDB | Barycentric Dynamical Time | TCB rescaled | Solar system ephemerides |
18//!
19//!
20//! # Fixed vs Variable Offsets
21//!
22//! Some conversions use constant offsets:
23//!
24//! - **TAI <-> TT**:  Fixed 32.184 seconds
25//! - **TAI <-> GPS**: Fixed 19.0 seconds
26//! - **TT <-> TCG**:  Secular rate 6.969290134e-10 (IAU 2000)
27//! - **TCG <-> TCB**: Secular rate 1.550519768e-8 (IAU 2006)
28//!
29//! Others require external data that changes over time:
30//!
31//! - **UTC <-> TAI**: Leap second table (currently 37 seconds as of 2017)
32//! - **UT1 <-> TAI**: IERS Earth Orientation Parameters (changes daily)
33//! - **UT1 <-> TT**:  Delta-T from historical tables or predictions
34//! - **TT <-> TDB**:  Location-dependent, ~1.66ms annual oscillation
35//!
36//! # Trait Pattern
37//!
38//! Each target scale has a conversion trait:
39//!
40//! - [`ToTAI`]: Convert to International Atomic Time
41//! - [`ToTT`]:  Convert to Terrestrial Time
42//! - [`ToGPS`]: Convert to GPS Time
43//! - [`ToUTC`]: Convert to Coordinated Universal Time
44//! - [`ToUT1`]: Convert to Universal Time 1
45//! - [`ToTCG`]: Convert to Geocentric Coordinate Time
46//!
47//! Additional traits handle conversions requiring parameters:
48//!
49//! - [`ToUT1WithOffset`], [`ToTAIWithOffset`]: UT1 <-> TAI with IERS offset
50//! - [`ToTTWithDeltaT`], [`ToUT1WithDeltaT`]:  UT1 <-> TT with historical Delta-T
51//! - [`ToTDB`], [`ToTTFromTDB`]:               TT <-> TDB with observer location
52//! - [`ToTCB`], [`ToTCGFromTCB`]:              TCG <-> TCB relativistic conversions
53//!
54//! # Usage
55//!
56//! Simple fixed-offset conversions work directly:
57//!
58//! ```
59//! use celestial_time::scales::{TAI, TT, GPS};
60//! use celestial_time::scales::conversions::{ToTAI, ToTT};
61//! use celestial_time::julian::JulianDate;
62//!
63//! let tai = TAI::from_julian_date(JulianDate::new(2451545.0, 0.0));
64//! let tt = tai.to_tt().unwrap();   // TAI + 32.184s
65//! ```
66//!
67//! Conversions requiring external data take parameters:
68//!
69//! ```
70//! use celestial_time::scales::{TAI, UT1};
71//! use celestial_time::scales::conversions::{ToUT1WithOffset, ToTAIWithOffset};
72//! use celestial_time::julian::JulianDate;
73//!
74//! // UT1-TAI offset from IERS Bulletin A
75//! let ut1_tai_offset = -37.0;  // seconds
76//!
77//! let tai = TAI::from_julian_date(JulianDate::new(2451545.0, 0.0));
78//! let ut1 = tai.to_ut1_with_offset(ut1_tai_offset).unwrap();
79//! let back = ut1.to_tai_with_offset(ut1_tai_offset).unwrap();
80//! ```
81//!
82//! # Precision Notes
83//!
84//! All conversions preserve precision by applying offsets to the smaller-magnitude
85//! component of the two-part Julian Date. Round-trip conversions maintain
86//! sub-nanosecond accuracy for fixed-offset scales.
87
88pub mod gps_tai;
89pub mod tai_tt;
90pub mod tcb_tdb;
91pub mod tcg_tcb;
92pub mod tt_tcg;
93pub mod tt_tdb;
94pub mod ut1_tai;
95pub mod utc_tai;
96pub mod utc_ut1;
97
98pub use tcb_tdb::*;
99pub use tcg_tcb::*;
100pub use tt_tdb::*;
101pub use ut1_tai::*;
102pub use utc_tai::*;
103pub use utc_ut1::*;
104
105use crate::scales::{GPS, TAI, TCG, TT, UT1, UTC};
106use crate::TimeResult;
107
108/// Convert a time scale to GPS Time.
109///
110/// GPS Time runs at the same rate as TAI but with a fixed offset of -19 seconds
111/// (GPS = TAI - 19s). It does not include leap seconds, making it continuous
112/// since its epoch of January 6, 1980.
113///
114/// Implemented for: GPS (identity), TAI
115pub trait ToGPS {
116    /// Convert to GPS Time.
117    fn to_gps(&self) -> TimeResult<GPS>;
118}
119
120/// Convert a time scale to International Atomic Time (TAI).
121///
122/// TAI is the fundamental atomic time scale, maintained by a weighted average of
123/// atomic clocks worldwide. It serves as the reference for most other time scales.
124///
125/// Implemented for: TAI (identity), UTC, TT, GPS, TCG
126///
127/// For UT1 → TAI, use [`ToTAIWithOffset`] which requires the IERS UT1-TAI offset.
128pub trait ToTAI {
129    /// Convert to TAI.
130    fn to_tai(&self) -> TimeResult<TAI>;
131}
132
133/// Convert a time scale to Terrestrial Time (TT).
134///
135/// TT is the time scale for geocentric ephemerides and Earth-based observations.
136/// It differs from TAI by exactly 32.184 seconds (TT = TAI + 32.184s), a value
137/// chosen for continuity with the older ET (Ephemeris Time) scale.
138///
139/// Implemented for: TT (identity), TAI, TCG
140///
141/// For TDB → TT, use [`ToTTFromTDB`] which requires observer location.
142/// For UT1 → TT, use [`ToTTWithDeltaT`] which requires Delta-T.
143pub trait ToTT {
144    /// Convert to Terrestrial Time.
145    fn to_tt(&self) -> TimeResult<TT>;
146}
147
148/// Convert a time scale to Geocentric Coordinate Time (TCG).
149///
150/// TCG is the proper time for a clock at the geocenter, accounting for
151/// gravitational time dilation. It runs faster than TT by a rate of
152/// approximately 6.969290134e-10 (about 22 ms/year).
153///
154/// Implemented for: TCG (identity), TT
155///
156/// For TCB → TCG, use [`ToTCGFromTCB`].
157pub trait ToTCG {
158    /// Convert to Geocentric Coordinate Time.
159    fn to_tcg(&self) -> TimeResult<TCG>;
160}
161
162/// Convert a time scale to Coordinated Universal Time (UTC).
163///
164/// UTC is the basis for civil timekeeping. It tracks TAI but is adjusted by
165/// leap seconds to stay within 0.9 seconds of UT1 (Earth rotation time).
166/// Leap seconds are inserted (or theoretically removed) based on IERS
167/// announcements.
168///
169/// Implemented for: UTC (identity), TAI, TT
170///
171/// Note: This conversion requires the leap second table in this crate,
172/// which must be updated when new leap seconds are announced.
173pub trait ToUTC {
174    /// Convert to Coordinated Universal Time.
175    fn to_utc(&self) -> TimeResult<UTC>;
176}
177
178/// Convert a time scale to Universal Time 1 (UT1).
179///
180/// UT1 is tied to Earth's actual rotation angle. Unlike atomic time scales,
181/// it varies unpredictably due to tidal friction, core-mantle coupling, and
182/// atmospheric effects. The difference UT1-UTC (DUT1) is kept within 0.9s
183/// by leap second adjustments.
184///
185/// Implemented for: UT1 (identity)
186///
187/// For TAI → UT1, use [`ToUT1WithOffset`] with the IERS UT1-TAI offset.
188/// For TT → UT1, use [`ToUT1WithDeltaT`] with Delta-T.
189pub trait ToUT1 {
190    /// Convert to Universal Time 1.
191    fn to_ut1(&self) -> TimeResult<UT1>;
192}