Skip to main content

tempoch_core/
lib.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2// Copyright (C) 2026 Vallés Puig, Ramon
3
4//! Typed astronomical time primitives.
5//!
6//! The central type is [`Time<S>`], where `S` is a [`Scale`] marker
7//! (`TT`, `TAI`, `UTC`, `UT1`, `TDB`, `TCG`, `TCB`).
8//!
9//! `tempoch` makes a few explicit modeling decisions:
10//!
11//! - [`Time<S>`] is an instant on a scale-specific axis, not a bare scalar.
12//! - Time arithmetic follows affine rules: instant minus instant yields a
13//!   duration; shifting an instant by a duration yields another instant.
14//! - Internal storage is a compensated `(hi, lo)` pair of J2000-based seconds
15//!   so large epoch values can retain small corrections and sub-second detail.
16//! - `JD`, `MJD`, `J2000s`, `Unix`, and `GPS` are conversion targets,
17//!   not independent storage models.
18//! - `UTC` keeps special civil semantics: it is stored as a continuous instant
19//!   and interpreted through the active UTC-TAI table when civil labels are
20//!   needed.
21//!
22//! The old format-generic storage model has been replaced with explicit
23//! constructors and accessors:
24//!
25//! - built-in coordinate scales expose J2000-second, JD, and MJD
26//!   constructors/accessors
27//! - `UTC` exposes both raw instant-axis helpers and civil/transport APIs
28//!   (`chrono`, POSIX)
29//! - `TAI` exposes GPS transport helpers
30//! - unified conversion targets are available through `time.to::<Target>()`,
31//!   `time.try_to::<Target>()`, and `time.to_with::<Target>(&ctx)`
32//!
33//! See [`constats`] for typed epoch and offset constants.
34
35mod civil;
36pub mod constats;
37mod context;
38mod data;
39mod delta_t;
40pub(crate) mod encoding;
41pub mod eop;
42pub mod error;
43pub mod ext;
44pub(crate) mod generated;
45mod interval;
46pub mod representation;
47pub mod scalar;
48mod scale;
49mod sealed;
50mod target;
51mod time;
52
53#[cfg(feature = "serde")]
54#[path = "serde.rs"]
55mod serde_impl;
56#[cfg(feature = "serde")]
57pub mod tagged;
58
59pub use constats::{
60    GPS_EPOCH_JD_TAI, GPS_EPOCH_JD_UTC, GPS_EPOCH_TAI_MINUS_UTC, UTC_DEFINED_FROM_MJD,
61};
62pub use context::TimeContext;
63#[cfg(feature = "runtime-data-fetch")]
64pub use data::active::{
65    fetch_latest_time_data, refresh_runtime_time_data, update_runtime_time_data,
66};
67pub use delta_t::{delta_t_seconds, delta_t_seconds_extrapolated, DELTA_T_PREDICTION_HORIZON_MJD};
68pub use error::{ConversionError, TimeDataError};
69pub use ext::TimeInstant;
70pub use generated::{
71    EOP_END_MJD, EOP_OBSERVED_END_MJD, EOP_START_MJD, MODERN_DELTA_T_OBSERVED_END_MJD,
72};
73pub use interval::{
74    complement_within, Interval, InvalidIntervalError, InvalidPeriodError, Period, PeriodListError,
75};
76pub use representation::{
77    EncodedTime, GpsTime, InfallibleRepresentationForScale, J2000Seconds, J2000s, JulianDate,
78    ModifiedJulianDate, RepresentationForScale, TimeRepresentation, Unix, UnixTime, GPS, J2000_TT,
79    JD, JULIAN_YEAR_DAYS, MJD,
80};
81pub use scalar::{
82    scalar_add_days, scalar_difference_in_days, time_tt_from_scalar, time_tt_to_scalar, ScaleKind,
83};
84pub use scale::{ContinuousScale, CoordinateScale, Scale, TAI, TCB, TCG, TDB, TT, UT1, UTC};
85pub use target::{ContextConversionTarget, ConversionTarget, InfallibleConversionTarget};
86pub use time::Time;
87
88#[cfg(test)]
89mod size_tests {
90    use super::*;
91    #[test]
92    fn time_uses_compensated_pair_storage() {
93        assert_eq!(core::mem::size_of::<Time<TT>>(), 16);
94        assert_eq!(core::mem::size_of::<Time<TAI>>(), 16);
95        assert_eq!(core::mem::size_of::<Time<TDB>>(), 16);
96        assert_eq!(core::mem::size_of::<Time<TCG>>(), 16);
97        assert_eq!(core::mem::size_of::<Time<TCB>>(), 16);
98        assert_eq!(core::mem::size_of::<Time<UT1>>(), 16);
99        assert_eq!(core::mem::size_of::<Time<UTC>>(), 16);
100    }
101}