diff --git a/CHANGELOG.md b/CHANGELOG.md index d3f920d..7b97678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Time scale conversion functions in FFI (`tempoch_jd_to_tt`, `tempoch_tt_to_jd`, `tempoch_jd_to_mjd`, `tempoch_mjd_to_jd`, `tempoch_jd_to_tai`, `tempoch_tai_to_jd`, `tempoch_jd_to_tdb`, `tempoch_tdb_to_jd`, `tempoch_jd_to_tcg`, `tempoch_tcg_to_jd`, `tempoch_jd_to_tcb`, `tempoch_tcb_to_jd`, `tempoch_jd_to_gps`, `tempoch_gps_to_jd`, `tempoch_jd_to_jde`, `tempoch_jde_to_jd`, `tempoch_jd_to_unix`, `tempoch_unix_to_jd`, `tempoch_jd_add_days`, `tempoch_jd_difference`, `tempoch_jd_difference_qty`, `tempoch_jd_add_qty`). +- `TempochScale` enum in FFI to enumerate all supported time scales. + +### Changed + +- Improved formatting and consistency in FFI time conversion implementations. + ## [0.3.0 - 2026-02-19] ### Added diff --git a/tempoch-ffi/include/tempoch_ffi.h b/tempoch-ffi/include/tempoch_ffi.h index db6e225..226c213 100644 --- a/tempoch-ffi/include/tempoch_ffi.h +++ b/tempoch-ffi/include/tempoch_ffi.h @@ -33,6 +33,29 @@ enum tempoch_status_t typedef int32_t tempoch_status_t; #endif // __cplusplus +// Scale label for the `tempoch_jd_to_scale()` / `tempoch_scale_to_jd()` dispatch. +// +enum TempochScale +#ifdef __cplusplus + : int32_t +#endif // __cplusplus + { + TEMPOCH_SCALE_JD = 0, + TEMPOCH_SCALE_MJD = 1, + TEMPOCH_SCALE_TDB = 2, + TEMPOCH_SCALE_TT = 3, + TEMPOCH_SCALE_TAI = 4, + TEMPOCH_SCALE_TCG = 5, + TEMPOCH_SCALE_TCB = 6, + TEMPOCH_SCALE_GPS = 7, + TEMPOCH_SCALE_UT = 8, + TEMPOCH_SCALE_JDE = 9, + TEMPOCH_SCALE_UNIX_TIME = 10, +}; +#ifndef __cplusplus +typedef int32_t TempochScale; +#endif // __cplusplus + // A time period in Modified Julian Date, suitable for C interop. typedef struct tempoch_period_mjd_t { double start_mjd; @@ -160,6 +183,75 @@ tempoch_status_t tempoch_period_mjd_intersection(struct tempoch_period_mjd_t a, // Compute the duration of a period as a `QttyQuantity` in days. qtty_quantity_t tempoch_period_mjd_duration_qty(struct tempoch_period_mjd_t period); +// Convert a Julian Date (TT) to TDB (Barycentric Dynamical Time). + double tempoch_jd_to_tdb(double jd); + +// Convert TDB back to Julian Date (TT). + double tempoch_tdb_to_jd(double tdb); + +// Convert a Julian Date (TT) to TT (Terrestrial Time). Identity—included for completeness. + double tempoch_jd_to_tt(double jd); + +// Convert TT back to Julian Date (TT). Identity. + double tempoch_tt_to_jd(double tt); + +// Convert a Julian Date (TT) to TAI (International Atomic Time). + double tempoch_jd_to_tai(double jd); + +// Convert TAI back to Julian Date (TT). + double tempoch_tai_to_jd(double tai); + +// Convert a Julian Date (TT) to TCG (Geocentric Coordinate Time). + double tempoch_jd_to_tcg(double jd); + +// Convert TCG back to Julian Date (TT). + double tempoch_tcg_to_jd(double tcg); + +// Convert a Julian Date (TT) to TCB (Barycentric Coordinate Time). + double tempoch_jd_to_tcb(double jd); + +// Convert TCB back to Julian Date (TT). + double tempoch_tcb_to_jd(double tcb); + +// Convert a Julian Date (TT) to GPS Time. + double tempoch_jd_to_gps(double jd); + +// Convert GPS Time back to Julian Date (TT). + double tempoch_gps_to_jd(double gps); + +// Convert a Julian Date (TT) to UT (Universal Time UT1). + double tempoch_jd_to_ut(double jd); + +// Convert UT back to Julian Date (TT). + double tempoch_ut_to_jd(double ut); + +// Convert a Julian Date (TT) to JDE (Julian Ephemeris Day — semantic alias of JD(TT)). + double tempoch_jd_to_jde(double jd); + +// Convert JDE back to Julian Date (TT). + double tempoch_jde_to_jd(double jde); + +// Convert a Julian Date (TT) to Unix Time (seconds since 1970-01-01T00:00:00 UTC, ignoring leap seconds). + +double tempoch_jd_to_unix(double jd); + +// Convert Unix Time back to Julian Date (TT). + double tempoch_unix_to_jd(double unix); + +// Return ΔT = TT − UT1 in seconds for a given Julian Date. +// +// Uses the piecewise polynomial/tabular model from tempoch-core. + double tempoch_delta_t_seconds(double jd); + +// Generic JD → any scale dispatch. +// +// Returns the value in the target time scale. Prefer the individual functions +// (`tempoch_jd_to_tdb`, etc.) when the target scale is known at compile time. + double tempoch_jd_to_scale(double jd, TempochScale scale); + +// Generic any scale → JD dispatch. + double tempoch_scale_to_jd(double value, TempochScale scale); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/tempoch-ffi/src/time.rs b/tempoch-ffi/src/time.rs index 4bdad8c..2487181 100644 --- a/tempoch-ffi/src/time.rs +++ b/tempoch-ffi/src/time.rs @@ -9,7 +9,10 @@ use crate::error::TempochStatus; use chrono::{DateTime, NaiveDate, Utc}; use qtty::Days; use qtty_ffi::{QttyQuantity, UnitId}; -use tempoch::{JulianDate, ModifiedJulianDate, TimeInstant, JD, MJD}; +use tempoch::{ + JulianDate, ModifiedJulianDate, Time, TimeInstant, UniversalTime, GPS, JD, JDE, MJD, TAI, TCB, + TCG, TDB, TT, UT, +}; // ═══════════════════════════════════════════════════════════════════════════ // C-repr types @@ -307,6 +310,185 @@ pub extern "C" fn tempoch_period_mjd_duration_qty(period: crate::TempochPeriodMj QttyQuantity::new(period.end_mjd - period.start_mjd, UnitId::Day) } +// ═══════════════════════════════════════════════════════════════════════════ +// Time scale conversions (JD ↔ TDB, TT, TAI, TCG, TCB, GPS, UT, JDE, UnixTime) +// ═══════════════════════════════════════════════════════════════════════════ + +/// Convert a Julian Date (TT) to TDB (Barycentric Dynamical Time). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_tdb(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert TDB back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_tdb_to_jd(tdb: f64) -> f64 { + Time::::new(tdb).to::().value() +} + +/// Convert a Julian Date (TT) to TT (Terrestrial Time). Identity—included for completeness. +#[no_mangle] +pub extern "C" fn tempoch_jd_to_tt(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert TT back to Julian Date (TT). Identity. +#[no_mangle] +pub extern "C" fn tempoch_tt_to_jd(tt: f64) -> f64 { + Time::::new(tt).to::().value() +} + +/// Convert a Julian Date (TT) to TAI (International Atomic Time). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_tai(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert TAI back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_tai_to_jd(tai: f64) -> f64 { + Time::::new(tai).to::().value() +} + +/// Convert a Julian Date (TT) to TCG (Geocentric Coordinate Time). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_tcg(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert TCG back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_tcg_to_jd(tcg: f64) -> f64 { + Time::::new(tcg).to::().value() +} + +/// Convert a Julian Date (TT) to TCB (Barycentric Coordinate Time). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_tcb(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert TCB back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_tcb_to_jd(tcb: f64) -> f64 { + Time::::new(tcb).to::().value() +} + +/// Convert a Julian Date (TT) to GPS Time. +#[no_mangle] +pub extern "C" fn tempoch_jd_to_gps(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert GPS Time back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_gps_to_jd(gps: f64) -> f64 { + Time::::new(gps).to::().value() +} + +/// Convert a Julian Date (TT) to UT (Universal Time UT1). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_ut(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert UT back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_ut_to_jd(ut: f64) -> f64 { + Time::::new(ut).to::().value() +} + +/// Convert a Julian Date (TT) to JDE (Julian Ephemeris Day — semantic alias of JD(TT)). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_jde(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert JDE back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_jde_to_jd(jde: f64) -> f64 { + Time::::new(jde).to::().value() +} + +/// Convert a Julian Date (TT) to Unix Time (seconds since 1970-01-01T00:00:00 UTC, ignoring leap seconds). +#[no_mangle] +pub extern "C" fn tempoch_jd_to_unix(jd: f64) -> f64 { + JulianDate::new(jd).to::().value() +} + +/// Convert Unix Time back to Julian Date (TT). +#[no_mangle] +pub extern "C" fn tempoch_unix_to_jd(unix: f64) -> f64 { + Time::::new(unix).to::().value() +} + +/// Return ΔT = TT − UT1 in seconds for a given Julian Date. +/// +/// Uses the piecewise polynomial/tabular model from tempoch-core. +#[no_mangle] +pub extern "C" fn tempoch_delta_t_seconds(jd: f64) -> f64 { + let ut: UniversalTime = JulianDate::new(jd).to::(); + ut.delta_t().value() +} + +/// Scale label for the `tempoch_jd_to_scale()` / `tempoch_scale_to_jd()` dispatch. +/// +/// cbindgen:prefix-with-name +#[repr(i32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TempochScale { + JD = 0, + MJD = 1, + TDB = 2, + TT = 3, + TAI = 4, + TCG = 5, + TCB = 6, + GPS = 7, + UT = 8, + JDE = 9, + UnixTime = 10, +} + +/// Generic JD → any scale dispatch. +/// +/// Returns the value in the target time scale. Prefer the individual functions +/// (`tempoch_jd_to_tdb`, etc.) when the target scale is known at compile time. +#[no_mangle] +pub extern "C" fn tempoch_jd_to_scale(jd: f64, scale: TempochScale) -> f64 { + match scale { + TempochScale::JD => jd, + TempochScale::MJD => tempoch_jd_to_mjd(jd), + TempochScale::TDB => tempoch_jd_to_tdb(jd), + TempochScale::TT => tempoch_jd_to_tt(jd), + TempochScale::TAI => tempoch_jd_to_tai(jd), + TempochScale::TCG => tempoch_jd_to_tcg(jd), + TempochScale::TCB => tempoch_jd_to_tcb(jd), + TempochScale::GPS => tempoch_jd_to_gps(jd), + TempochScale::UT => tempoch_jd_to_ut(jd), + TempochScale::JDE => tempoch_jd_to_jde(jd), + TempochScale::UnixTime => tempoch_jd_to_unix(jd), + } +} + +/// Generic any scale → JD dispatch. +#[no_mangle] +pub extern "C" fn tempoch_scale_to_jd(value: f64, scale: TempochScale) -> f64 { + match scale { + TempochScale::JD => value, + TempochScale::MJD => tempoch_mjd_to_jd(value), + TempochScale::TDB => tempoch_tdb_to_jd(value), + TempochScale::TT => tempoch_tt_to_jd(value), + TempochScale::TAI => tempoch_tai_to_jd(value), + TempochScale::TCG => tempoch_tcg_to_jd(value), + TempochScale::TCB => tempoch_tcb_to_jd(value), + TempochScale::GPS => tempoch_gps_to_jd(value), + TempochScale::UT => tempoch_ut_to_jd(value), + TempochScale::JDE => tempoch_jde_to_jd(value), + TempochScale::UnixTime => tempoch_unix_to_jd(value), + } +} + #[cfg(test)] mod tests { use super::*;