Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
/home/runner/work/vulcan/vulcan/include/vulcan/time/Epoch.hpp

Unified time representation for aerospace applications.

Unified time representation for aerospace applications Epoch stores time internally as TAI seconds since J2000.0 TT. This representation is:

  • Continuous (no leap seconds in TAI)
  • High precision (sub-microsecond)
  • Efficient for arithmetic

Provides accessors for all time scales (UTC, TAI, TT, GPS, TDB).

Template Parameters
ScalarNumeric (double) or symbolic (casadi::MX) type
// Numeric mode
auto epoch = NumericEpoch::from_utc(2024, 7, 15, 12, 30, 0.0);
std::cout << epoch.to_iso_string() << std::endl;
std::cout << "JD TT: " << epoch.jd_tt() << std::endl;
// Symbolic mode
auto t_sym = janus::sym("t");
auto sym_epoch = SymbolicEpoch::from_tai_seconds(t_sym);
auto centuries = sym_epoch.centuries_tt();
#pragma once
#include <iomanip>
#include <janus/janus.hpp>
#include <sstream>
#include <string>
namespace vulcan::time {
template <typename Scalar> class Epoch {
public:
// =========================================================================
// Constructors
// =========================================================================
Epoch() : m_tai_sec(Scalar(0.0)), m_delta_at(37) {}
explicit Epoch(const Scalar &tai_seconds, int delta_at = 37)
: m_tai_sec(tai_seconds), m_delta_at(delta_at) {}
// =========================================================================
// Factory Methods (Static Construction)
// =========================================================================
static Epoch from_tai_seconds(const Scalar &tai_sec, int delta_at = 37) {
return Epoch(tai_sec, delta_at);
}
static Epoch from_jd_tai(const Scalar &jd_tai, int delta_at = 37) {
Scalar tai_sec = jd_to_j2000_seconds(jd_tai);
return Epoch(tai_sec, delta_at);
}
static Epoch from_jd_tt(const Scalar &jd_tt, int delta_at = 37) {
Scalar jd_tai = tt_to_tai(jd_tt);
}
static Epoch from_jd_gps(const Scalar &jd_gps, int delta_at = 37) {
}
static Epoch from_utc(int year, int month, int day, int hour = 0,
int min = 0, double sec = 0.0)
requires std::is_floating_point_v<Scalar>
{
double utc_jd = calendar_to_jd(year, month, day, hour, min, sec);
double tai_jd = utc_to_tai(utc_jd, delta_at);
double tai_sec = jd_to_j2000_seconds(tai_jd);
return Epoch(tai_sec, delta_at);
}
static Epoch from_gps_week(int week, const Scalar &seconds_of_week,
int delta_at = 37) {
Scalar gps_sec_since_epoch =
static_cast<double>(week) * constants::time::SECONDS_PER_WEEK +
seconds_of_week;
// GPS epoch is 1980-01-06 00:00:00 UTC
// In TAI seconds since J2000.0:
// GPS epoch JD = 2444244.5
// J2000.0 JD = 2451545.0
// Delta = -7300.5 days = -630763200 seconds
constexpr double GPS_EPOCH_TAI_SEC =
Scalar tai_sec = GPS_EPOCH_TAI_SEC + gps_sec_since_epoch;
return Epoch(tai_sec, delta_at);
}
// =========================================================================
// Time Scale Accessors (Julian Dates)
// =========================================================================
[[nodiscard]] Scalar jd_tai() const {
return j2000_seconds_to_jd(m_tai_sec);
}
[[nodiscard]] Scalar jd_tt() const { return tai_to_tt(jd_tai()); }
[[nodiscard]] Scalar jd_gps() const { return tai_to_gps(jd_tai()); }
[[nodiscard]] Scalar jd_utc() const {
return tai_to_utc(jd_tai(), m_delta_at);
}
[[nodiscard]] Scalar jd_tdb() const { return tt_to_tdb(jd_tt()); }
[[nodiscard]] Scalar mjd_tt() const { return jd_to_mjd(jd_tt()); }
// =========================================================================
// Time Scale Accessors (Seconds)
// =========================================================================
[[nodiscard]] const Scalar &tai_seconds() const { return m_tai_sec; }
[[nodiscard]] Scalar tt_seconds() const {
return m_tai_sec + constants::time::TT_TAI_OFFSET;
}
[[nodiscard]] Scalar centuries_tt() const {
}
// =========================================================================
// GPS Time Accessors
// =========================================================================
[[nodiscard]] int gps_week() const
requires std::is_floating_point_v<Scalar>
{
Scalar gps_jd = jd_gps();
double days_since_gps_epoch = gps_jd - constants::time::JD_GPS_EPOCH;
return static_cast<int>(std::floor(days_since_gps_epoch / 7.0));
}
[[nodiscard]] Scalar gps_seconds_of_week() const {
Scalar gps_jd = jd_gps();
Scalar days_since_gps_epoch = gps_jd - constants::time::JD_GPS_EPOCH;
// fmod for symbolic
if constexpr (std::is_floating_point_v<Scalar>) {
double weeks =
std::floor(static_cast<double>(days_since_gps_epoch) / 7.0);
double days_into_week = days_since_gps_epoch - weeks * 7.0;
return days_into_week * constants::time::SECONDS_PER_DAY;
} else {
// Symbolic: use janus::fmod
Scalar days_into_week =
janus::fmod(days_since_gps_epoch, Scalar(7.0));
return days_into_week * constants::time::SECONDS_PER_DAY;
}
}
// =========================================================================
// Leap Second Access
// =========================================================================
[[nodiscard]] int delta_at() const { return m_delta_at; }
void set_delta_at(int delta_at) { m_delta_at = delta_at; }
// =========================================================================
// Arithmetic Operators
// =========================================================================
Epoch operator+(const Scalar &seconds) const {
return Epoch(m_tai_sec + seconds, m_delta_at);
}
Epoch operator-(const Scalar &seconds) const {
return Epoch(m_tai_sec - seconds, m_delta_at);
}
Scalar operator-(const Epoch &other) const {
return m_tai_sec - other.m_tai_sec;
}
Epoch &operator+=(const Scalar &seconds) {
m_tai_sec = m_tai_sec + seconds;
return *this;
}
Epoch &operator-=(const Scalar &seconds) {
m_tai_sec = m_tai_sec - seconds;
return *this;
}
// =========================================================================
// String Conversion (Numeric Only)
// =========================================================================
[[nodiscard]] std::string to_iso_string() const
requires std::is_floating_point_v<Scalar>
{
double utc_jd = jd_utc();
auto [year, month, day, hour, min, sec] = jd_to_calendar(utc_jd);
std::ostringstream oss;
oss << std::setfill('0') << std::setw(4) << year << '-' << std::setw(2)
<< month << '-' << std::setw(2) << day << 'T' << std::setw(2)
<< hour << ':' << std::setw(2) << min << ':' << std::setw(2)
<< static_cast<int>(sec);
// Add fractional seconds if significant
double frac = sec - std::floor(sec);
if (frac > 1e-6) {
oss << '.' << std::setw(3) << static_cast<int>(frac * 1000);
}
oss << 'Z';
return oss.str();
}
[[nodiscard]] std::tuple<int, int, int, int, int, double>
requires std::is_floating_point_v<Scalar>
{
double utc_jd = jd_utc();
return jd_to_calendar(utc_jd);
}
private:
Scalar m_tai_sec;
int m_delta_at;
};
// =============================================================================
// Type Aliases
// =============================================================================
using NumericEpoch = Epoch<double>;
using SymbolicEpoch = Epoch<janus::SymbolicScalar>;
} // namespace vulcan::time
static Epoch from_gps_week(int week, const Scalar &seconds_of_week, int delta_at=37)
Create Epoch from GPS week and seconds.
Definition Epoch.hpp:117
Epoch()
Default constructor (J2000.0 epoch).
Definition Epoch.hpp:49
Epoch operator-(const Scalar &seconds) const
Subtract duration in seconds.
Definition Epoch.hpp:261
static Epoch from_jd_tai(const Scalar &jd_tai, int delta_at=37)
Create Epoch from TAI Julian Date.
Definition Epoch.hpp:75
Scalar jd_tai() const
Get Julian Date in TAI scale.
Definition Epoch.hpp:142
std::string to_iso_string() const
Convert to ISO 8601 string in UTC.
Definition Epoch.hpp:295
const Scalar & tai_seconds() const
Get TAI seconds since J2000.0.
Definition Epoch.hpp:180
Scalar tt_seconds() const
Get TT seconds since J2000.0.
Definition Epoch.hpp:185
Epoch & operator-=(const Scalar &seconds)
Subtract duration in seconds (in-place).
Definition Epoch.hpp:283
Scalar mjd_tt() const
Get Modified Julian Date in TT scale.
Definition Epoch.hpp:171
Scalar jd_tt() const
Get Julian Date in TT scale.
Definition Epoch.hpp:149
Scalar jd_tdb() const
Get Julian Date in TDB scale.
Definition Epoch.hpp:166
Scalar jd_utc() const
Get Julian Date in UTC scale (using stored delta_at).
Definition Epoch.hpp:159
Scalar jd_gps() const
Get Julian Date in GPS scale.
Definition Epoch.hpp:154
Epoch & operator+=(const Scalar &seconds)
Add duration in seconds (in-place).
Definition Epoch.hpp:275
Scalar gps_seconds_of_week() const
Get seconds within the GPS week.
Definition Epoch.hpp:216
void set_delta_at(int delta_at)
Set the TAI - UTC offset.
Definition Epoch.hpp:245
std::tuple< int, int, int, int, int, double > to_utc_calendar() const
Convert to calendar components in UTC.
Definition Epoch.hpp:321
int gps_week() const
Get GPS week number.
Definition Epoch.hpp:205
Scalar centuries_tt() const
Get Julian centuries since J2000.0 in TT scale.
Definition Epoch.hpp:194
Epoch operator+(const Scalar &seconds) const
Add duration in seconds.
Definition Epoch.hpp:254
static Epoch from_jd_gps(const Scalar &jd_gps, int delta_at=37)
Create Epoch from GPS Julian Date.
Definition Epoch.hpp:91
int delta_at() const
Get the stored TAI - UTC offset.
Definition Epoch.hpp:240
static Epoch from_jd_tt(const Scalar &jd_tt, int delta_at=37)
Create Epoch from TT Julian Date.
Definition Epoch.hpp:83
static Epoch from_utc(int year, int month, int day, int hour=0, int min=0, double sec=0.0)
Create Epoch from UTC calendar (numeric only).
Definition Epoch.hpp:103
static Epoch from_tai_seconds(const Scalar &tai_sec, int delta_at=37)
Create Epoch from TAI seconds since J2000.0.
Definition Epoch.hpp:68
constexpr double JD_GPS_EPOCH
Julian Date of GPS epoch (1980-01-06 00:00:00 UTC).
Definition TimeConstants.hpp:19
constexpr double SECONDS_PER_WEEK
Seconds per week (for GPS).
Definition TimeConstants.hpp:57
constexpr double SECONDS_PER_DAY
Seconds per day.
Definition TimeConstants.hpp:45
constexpr double SECONDS_PER_CENTURY
Seconds per Julian century.
Definition TimeConstants.hpp:48
constexpr double JD_J2000
Julian Date of J2000.0 epoch (2000-01-01 12:00:00 TT).
Definition TimeConstants.hpp:10
constexpr double TT_TAI_OFFSET
TT - TAI offset [s] (exact, by definition).
Definition TimeConstants.hpp:32
constexpr double TAI_GPS_OFFSET
TAI - GPS offset [s].
Definition TimeConstants.hpp:38
Definition Epoch.hpp:12
constexpr Scalar gps_to_tai(const Scalar &gps_jd)
Convert GPS Julian Date to TAI Julian Date.
Definition TimeScales.hpp:69
int leap_seconds_at_utc(double utc_jd)
Get TAI - UTC offset for a given UTC Julian Date.
Definition LeapSeconds.hpp:93
constexpr Scalar utc_to_tai(const Scalar &utc_jd, int delta_at)
Convert UTC Julian Date to TAI Julian Date (templated).
Definition TimeScales.hpp:89
Epoch< double > NumericEpoch
Numeric epoch (double-precision).
Definition Epoch.hpp:338
std::tuple< int, int, int, int, int, double > jd_to_calendar(double jd)
Convert Julian Date to calendar date/time (numeric only).
Definition JulianDate.hpp:46
constexpr Scalar tt_to_tai(const Scalar &tt_jd)
Convert TT Julian Date to TAI Julian Date.
Definition TimeScales.hpp:45
constexpr Scalar j2000_seconds_to_jd(const Scalar &sec)
Convert seconds since J2000.0 to Julian Date.
Definition JulianDate.hpp:132
constexpr Scalar tai_to_utc(const Scalar &tai_jd, int delta_at)
Convert TAI Julian Date to UTC Julian Date (templated).
Definition TimeScales.hpp:103
Scalar tt_to_tdb(const Scalar &tt_jd)
Convert TT Julian Date to TDB Julian Date.
Definition TimeScales.hpp:188
constexpr Scalar jd_to_j2000_seconds(const Scalar &jd)
Convert Julian Date to seconds since J2000.0.
Definition JulianDate.hpp:124
constexpr Scalar jd_to_mjd(const Scalar &jd)
Convert Julian Date to Modified Julian Date.
Definition JulianDate.hpp:103
constexpr Scalar tai_to_tt(const Scalar &tai_jd)
Convert TAI Julian Date to TT Julian Date.
Definition TimeScales.hpp:36
Epoch< janus::SymbolicScalar > SymbolicEpoch
Symbolic epoch (CasADi MX).
Definition Epoch.hpp:341
double calendar_to_jd(int year, int month, int day, int hour=0, int min=0, double sec=0.0)
Convert calendar date/time to Julian Date.
Definition JulianDate.hpp:24
constexpr Scalar tai_to_gps(const Scalar &tai_jd)
Convert TAI Julian Date to GPS Julian Date.
Definition TimeScales.hpp:60