DELTA_T_HYBRID_MODEL - TheDaniel166/moira GitHub Wiki
Moira — Delta T Model
Version: 2.0
Date: 2026-04-25
Status: Complete — all phases implemented and verified
Surfaces: moira/julian.py:delta_t() · moira/delta_t_physical.py:delta_t_hybrid()
1. Doctrine
Moira's ΔT engine applies a single governing principle across all epochs:
Highest-authority source per epoch. Where observations exist, observations govern. Where they end, owned physics governs.
This is not a fallback cascade. It is an epistemic priority queue. The layers do not compete — they are ordered by the nature of available knowledge at each epoch, and the ordering is never arbitrary.
| Epoch | Source | Authority class |
|---|---|---|
| 2026+ | delta_t_hybrid() — Moira physical model |
Owned |
| 2015–2026 | IERS Bulletin B/A annual means | Direct observation |
| 1955–2015 | USNO 5-year observed table | Direct observation |
| ~720–1955 | SMH 2016 (Stephenson-Morrison-Hohenkerk) | Primary authority |
| 1600–1900 | Espenak & Meeus historical anchor | Secondary anchor |
| 1900–1955 | 5-year pre-modern anchor table | Secondary anchor |
| All other | Morrison & Stephenson (2004) + DE441 tidal | Primary polynomials |
The future era is the only epoch where no external observation or authority
exists. Moira owns it outright: the model is calibrated against IERS LOD
observations, anchored at the observed IERS total at the reference epoch
(2026.0), and continuous across the observational boundary. The prior
convention quadratic (69.3 + 0.04·t + 0.001·t²) was an arbitrary smooth
curve that diverged from observed reality by ~130 s at 2100. It has been
replaced entirely.
Historical context
The physical model replaced a simple quadratic future extrapolation that had been the default since the Espenak/Meeus era. By 2050 the old formula diverged from JPL Horizons by 30–50 seconds; by 2100 by ~130 seconds — creating artificial apparent-position errors of 3–120 arcseconds for fast bodies. The goal was not to replace IERS observations (which remain the highest authority for the observed era) but to replace the convention guess for the unobserved future with a physically-grounded and calibrated model.
2. Physical Model Architecture
Delta T is driven by changes in Earth's rotation rate (LOD — Length of Day). The dominant contributors are:
ΔT(t) = ΔT_tidal(t) + ΔT_GIA(t) + ΔT_core(t) + ΔT_cryo(t) + ΔT_residual(t)
| Component | Physical driver | Data source | Era coverage |
|---|---|---|---|
| ΔT_tidal | Lunar/solar tidal braking | Celestial mechanics | All epochs |
| ΔT_GIA | Glacial isostatic adjustment | ICE-6G / Caron 2018 | Post-LGM |
| ΔT_core | Core-mantle angular momentum | Gillet et al. core flow | 1840–present |
| ΔT_cryo | Cryosphere/hydrosphere mass | GRACE/GRACE-FO mascons | 2002–present |
| ΔT_residual | Everything else | Fit to IERS measured table | 1955–present |
For future extrapolation (post-2026), only ΔT_tidal and ΔT_GIA provide a deterministic secular baseline. ΔT_core and ΔT_cryo remain visible physical terms. The remaining unknowable part is modeled as stochastic LOD variability: Brownian rotation-rate noise integrated forward into a Delta T probability distribution.
3. Implementation Phases
Phase 1 — Tidal + GIA secular trend (Foundation)
Goal: Replace the long-range parabolic fallback with a physically-grounded secular trend. This is the baseline that all other components are added to.
Tidal braking:
The lunar tidal torque produces a secular increase in LOD of approximately +2.3 ms/century, equivalent to a parabolic Delta T trend:
ΔT_tidal(y) = c_tidal · ((y - 1820) / 100)²
where c_tidal is determined by the lunar secular acceleration ṅ.
The current best value is ṅ = -25.858 ± 0.003 arcsec/cy² (Chapront,
Chapront-Touze & Francou 2002), which gives c_tidal ≈ 31.0 s/cy².
This is already embedded in the Espenak/Meeus -20 + 32·u² formula.
The improvement here is to use the Chapront value rather than the older
Morrison & Stephenson estimate.
GIA contribution:
Published GIA models give the rotation rate contribution directly as a LOD change. From Caron et al. (2018, Geophysical Research Letters):
dLOD_GIA ≈ -0.6 ms/century (acceleration, counteracts tidal braking)
This translates to:
ΔT_GIA(y) = c_GIA · ((y - 2000) / 100)²
where c_GIA ≈ -3.0 s/cy² (negative, opposing the tidal term).
Reference epoch unification:
The standard tidal formula uses 1820 as its reference epoch (the Morrison &
Stephenson convention). The Caron GIA contribution is naturally expressed
relative to 2000 (the center of the modern ice-loss record). Before combining
them, both must be re-expressed relative to the same epoch — REFERENCE_YEAR
— so that they can be summed into a single parabolic coefficient.
The general form of each component is:
ΔT_tidal(y) = c_tidal · ((y − 1820) / 100)²
ΔT_GIA(y) = c_GIA · ((y − 2000) / 100)²
Expanding both around REFERENCE_YEAR (= 2026) and collecting terms:
ΔT_tidal(y) = c_tidal · ((y − 2026 + 206) / 100)²
= c_tidal · (t + 2.06)² where t = (y − 2026) / 100
= c_tidal · (t² + 4.12·t + 4.2436)
ΔT_GIA(y) = c_GIA · ((y − 2026 + 26) / 100)²
= c_GIA · (t + 0.26)²
= c_GIA · (t² + 0.52·t + 0.0676)
The constant offsets are absorbed into REFERENCE_LOD via the continuity
constraint. The linear terms are different: they are a present-day LOD slope,
not a value offset, and a scalar anchor cannot absorb them algebraically.
Moira's physical secular branch therefore uses the published tidal and GIA
coefficients as curvature terms only. The current slope at REFERENCE_YEAR
is treated as a measured boundary condition rather than as the slope implied
by extending the 1820/2000 parabolas unchanged into the present.
secular_trend(y) = REFERENCE_LOD + (c_tidal + c_GIA) · t²
= REFERENCE_LOD + (31.0 − 3.0) · t²
= REFERENCE_LOD + 28.0 · t²
This is why the combined coefficient in secular_trend() is simply the sum
of TIDAL_COEFF and GIA_COEFF: the function is a curvature model anchored
at the measured-era handoff. It is not the full shifted 1820/2000 parabola
with its linear term preserved.
Implementation:
# moira/delta_t_physical.py
TIDAL_COEFF = 31.0 # s/cy² — Chapront 2002 lunar secular acceleration
GIA_COEFF = -3.0 # s/cy² — Caron 2018 GIA rotation contribution
# Curvature terms anchored at REFERENCE_YEAR;
# constant offsets absorbed into REFERENCE_LOD.
REFERENCE_LOD = 69.3 # s — see continuity constraint note below
REFERENCE_YEAR = 2026.0 # yr — last confirmed IERS Bulletin B year
def secular_trend(year: float) -> float:
"""
Physics-based secular Delta T trend from tidal braking + GIA.
Anchored to REFERENCE_LOD at REFERENCE_YEAR by continuity constraint.
The coefficients carry curvature only. The present-day slope is an
explicit boundary-condition policy and is not inherited from the
historical 1820/2000 parabola slopes.
"""
t = (year - REFERENCE_YEAR) / 100.0
return REFERENCE_LOD + (TIDAL_COEFF + GIA_COEFF) * t**2
The 2026 anchor is a continuity constraint, not a free parameter.
This point deserves explicit statement because the constant 69.3 looks like
a tuned value. It is not. It is the last confirmed IERS Bulletin A measured
Delta T at the boundary between the table-driven regime and the future
extrapolation regime. Its role is purely to enforce C0 continuity — that is,
to guarantee the physical model produces the same value as the measured table
at the handoff point.
Concretely: the secular trend formula has two genuine free parameters,
TIDAL_COEFF and GIA_COEFF, both of which are set from published physical
literature and must not be adjusted to improve the fit. REFERENCE_LOD is
derived, not fitted:
REFERENCE_LOD ≡ IERS_measured(REFERENCE_YEAR)
− core_delta_t(REFERENCE_YEAR)
− cryo_delta_t(REFERENCE_YEAR)
− residual_spline(REFERENCE_YEAR)
It is the value the secular trend must take at REFERENCE_YEAR such that
the full assembled model secular + core + cryo + residual exactly equals
the IERS measured value at that point. Any other value would introduce a
step discontinuity in Delta T at the measured/extrapolated boundary, which
would propagate directly as a discontinuous jump in apparent planetary
positions at that epoch.
REFERENCE_YEAR is itself not fixed at 2026.0 permanently. It is defined
as the last year for which a confirmed IERS Bulletin A or B value is
available at build time. As new Bulletin A predictions are confirmed by
Bulletin B, REFERENCE_YEAR advances and REFERENCE_LOD is recomputed
from the updated measurement. The advance procedure is:
# scripts/update_reference_anchor.py
# Run when new IERS Bulletin B values become available.
# Recomputes REFERENCE_LOD and writes updated constants to delta_t_physical.py.
This means the anchor stays current automatically as IERS measurements accumulate, without any manual tuning of the model.
Validation: Compare against SMH 2016 table for 1800–2026. The secular trend should match within the known decade-scale fluctuation envelope (~±5 s).
Deliverables:
moira/delta_t_physical.py— module skeleton +secular_trend()tests/unit/test_delta_t_physical.py— secular trend unit testsscripts/validate_secular_trend.py— plot vs SMH 2016 table
Effort: 1 week
Phase 2 — GRACE/GRACE-FO cryosphere component
Goal: Derive the cryosphere/hydrosphere contribution to Delta T from satellite gravity data (2002–present) and project it forward.
Physics:
Changes in surface mass distribution alter Earth's moments of inertia, specifically the axial moment I_33. The rotation rate change is:
Δω/ω = -ΔI_33 / C
where C is Earth's polar moment of inertia (~8.04 × 10³⁷ kg·m²).
ΔI_33 is related to the degree-2 zonal Stokes coefficient J2 by:
ΔI_33 = -√5 · M_E · R_E² · ΔJ2
GRACE/GRACE-FO mascon solutions give ΔJ2 directly as a monthly time series.
The LOD change from this is:
ΔLOD_cryo(t) = -LOD_0 · Δω(t) / ω_0
= LOD_0 · ΔI_33(t) / C
Integrating LOD over time gives the Delta T contribution.
LOD-to-Delta-T integration and integration constant:
The GRACE series is a discrete monthly table of LOD anomalies
ΔLOD(t_i) in milliseconds, not a continuous rate. The Delta T
contribution is the cumulative integral:
ΔT_cryo(y) = Σ ΔLOD(t_i) · Δt_i / 86400 [seconds]
where Δt_i is the interval in days between successive monthly epochs
and the division by 86400 converts milliseconds of LOD into seconds of
Delta T accumulated per day.
The integration constant — the value at which cryo_delta_t is set to
zero — is defined as the mean ΔLOD over the first 12 months of the GRACE
record (2002 April–2003 March). This choice is deliberate: it removes
the arbitrary absolute offset of the GRACE J2 series (which is referenced
to a pre-GRACE background model, not to zero ice anomaly) while preserving
the trend and interannual variability. It means cryo_delta_t(2002.5) ≡ 0
by construction, and all values are LOD anomalies relative to that baseline.
The full series is pre-integrated once by fetch_grace_j2.py and stored
as a cumulative sum in grace_lod_contribution.txt. At runtime,
cryo_delta_t(year) performs linear interpolation on this pre-integrated
table — it does not re-integrate at call time.
Data source:
JPL GRACE Tellus RL06 mascon solution — public, no registration required:
https://podaac.jpl.nasa.gov/dataset/TELLUS_GRAC-GRFO_MASCON_CRI_GRID_RL06.1_V3
Monthly grids 2002-04 to present, 0.5° resolution.
The degree-2 zonal term ΔJ2 can also be read directly from the published GRACE technical notes (TN-13, TN-14) without processing the full mascon grid. This is the preferred approach for implementation simplicity.
Implementation:
# scripts/fetch_grace_j2.py
# Downloads GRACE/GRACE-FO TN-14 J2 time series and converts to LOD contribution
# moira/delta_t_physical.py
def _load_grace_lod_series() -> tuple[tuple[float, float], ...]:
"""
Load pre-processed GRACE/GRACE-FO LOD contribution series.
File: moira/data/grace_lod_contribution.txt
Format: decimal_year lod_contribution_seconds
Generated by: scripts/fetch_grace_j2.py
"""
...
def cryo_delta_t(year: float) -> float:
"""
Cryosphere/hydrosphere contribution to Delta T from GRACE J2 series.
Returns 0.0 outside the GRACE coverage window (pre-2002).
For post-coverage extrapolation, uses the linear trend of the last
5 years of available data.
"""
...
Key numbers (approximate, from published literature):
The GRACE record shows ΔJ2 trending at approximately −3.0 × 10⁻¹¹/year driven primarily by Greenland and Antarctic ice loss. This translates to:
dLOD_cryo ≈ +0.012 ms/year (growing)
Over a 70-year future window (2026–2100), this accumulates to:
ΔT_cryo(2100) ≈ +0.5 s above the 2026 baseline
This is small but measurable and currently unmodeled in any ephemeris system.
GRACE/GRACE-FO data gap (2017-10 to 2018-06):
GRACE ceased science operations in October 2017; GRACE-FO began returning data in June 2018. This leaves an ~11-month gap in the J2 series that falls squarely within the residual spline's fit window (1962–2023). It must be handled explicitly — silently interpolating across it would introduce a false LOD trend of ~0.1 ms/year in the residual.
The gap is bridged by linear interpolation between the last confirmed
GRACE monthly value (2017-09) and the first confirmed GRACE-FO monthly
value (2018-07), using the slope of the 12 months immediately preceding
the gap. A flag column in grace_lod_contribution.txt marks all
gap-interpolated months so they can be excluded from regression
diagnostics. The bridged values are used in the pre-integrated series
but are not treated as measured data in the CV diagnostic — the
leave-one-out score is computed only over non-flagged months.
Deliverables:
scripts/fetch_grace_j2.py— downloads and processes GRACE TN-14moira/data/grace_lod_contribution.txt— pre-processed LOD seriesdelta_t_physical.cryo_delta_t()— interpolation + trend extrapolation- Unit tests verifying the J2-to-LOD conversion formula
Effort: 2 weeks
Phase 3 — Core-mantle angular momentum component
Goal: Add the decade-scale LOD fluctuations driven by core-mantle angular momentum exchange, using published core flow models.
Physics:
The solid Earth (mantle + crust) and the fluid outer core exchange angular momentum, producing LOD variations of ±2–4 ms on decadal timescales. These are the dominant source of the irregular "wiggles" in the measured Delta T curve that a pure secular + cryosphere model cannot reproduce.
The connection is through the geomagnetic torque:
dL_core/dt + Γ_cmb = 0 (angular momentum conservation)
where Γ_cmb is the torque at the core-mantle boundary.
Core surface flow is inferred from the geomagnetic secular variation (rate of change of the magnetic field) via the frozen-flux approximation.
Data source:
Gillet et al. (2019, JGR) — published core angular momentum time series 1840–2019, reconstructed from geomagnetic field models. Available as supplementary data from the paper.
For the modern era (2014–present), the Swarm satellite mission provides the geomagnetic secular variation at unprecedented resolution.
This phase does not require implementing core flow inversion. It consumes the published Gillet et al. angular momentum series directly as a table.
Implementation:
# moira/data/core_angular_momentum.txt
# From Gillet et al. (2019) Table S1
# Format: decimal_year delta_lod_ms
def _load_core_lod_series() -> tuple[tuple[float, float], ...]:
...
def core_delta_t(year: float) -> float:
"""
Core-mantle angular momentum contribution to Delta T.
Coverage: 1840–2019 from Gillet et al. (2019).
Outside coverage: returns 0.0 (absorbed into residual).
No future extrapolation — core fluctuations are not predictable.
"""
...
Current implementation note: the source IERS EOP C04 annual LOD proxy is
linearly detrended before integration. The secular tidal/GIA drift belongs to
secular_trend(); core_delta_t() carries the residual core-mantle
fluctuation component.
Note on future extrapolation:
Core-mantle fluctuations are genuinely unpredictable beyond a few years. For future Delta T (post-2026), this component is frozen at the terminal measured core value rather than extrapolating the trend. The recent-window standard deviation is used for uncertainty.
The choice of 10 years is grounded in the decorrelation timescale of core
surface flow. Geomagnetic secular variation studies (Gillet et al. 2010,
2019; Christensen & Tilgner 2004) consistently show that core flow features
have an autocorrelation timescale of roughly 5–15 years — meaning that
the angular momentum state of the core at any given year carries essentially
no predictive information about the core state more than ~10–15 years later.
This is a consequence of the advective turnover time of the outer core
(roughly 500 years divided by the magnetic Reynolds number, giving ~10 years
for the dominant flow structures). Beyond that window, the core angular
momentum performs a random walk constrained by the geometry of the
core-mantle boundary, not a trend that can be extrapolated. Moira therefore
linearly detrends the source LOD proxy before integration and freezes the
future-era core term at the terminal measured value. This preserves C0
continuity at the measured-to-future boundary while keeping secular drift in
secular_trend() rather than duplicating it inside core_delta_t().
Deliverables:
moira/data/core_angular_momentum.txt— Gillet et al. 2019 tabledelta_t_physical.core_delta_t()— table interpolation- Unit tests verifying the LOD-to-Delta-T integration
- Comparison plot vs measured IERS LOD series 1962–present
Effort: 2 weeks
Phase 4 — Residual fitting and model assembly
Goal: Combine all components, fit the residual against the IERS measured
table, and produce the final delta_t_hybrid() function.
Model structure:
def delta_t_hybrid(year: float) -> float:
"""
Physics-based hybrid Delta T model.
For 1840–2026: secular + core + cryo components, residual-corrected
against IERS measured table.
For 2026+: owned secular baseline (_future_secular_baseline) from tidal
dissipation and GIA integrated from their own reference epochs,
plus frozen core terminal value and GRACE trend. No conventional
forecast bridge. Uncertainty is carried by DeltaTDistribution.
For pre-1840: delegates to SMH 2016 table (unchanged — the physical
components do not extend this far back reliably).
"""
if year < 1840.0:
return _smh2016_lookup(year)
base = secular_trend(year)
core = core_delta_t(year) # 0.0 outside Gillet coverage
cryo = cryo_delta_t(year) # 0.0 outside GRACE coverage
if year <= 2026.0:
residual = _fit_residual(year) # spline fit to IERS measured − model
return base + core + cryo + residual
# Future: deterministic tidal/GIA baseline + visible physical terms.
core_terminal = _core_terminal_value()
return _future_secular_baseline(year) + core_terminal + cryo
Era coverage and the 1840–1962 regime:
The model has three distinct operating regimes that differ in which components are active:
| Era | secular | core | cryo | residual | Notes |
|---|---|---|---|---|---|
| pre-1840 | — | — | — | — | Full SMH 2016 delegation |
| 1840–1962 | ✓ | ✓ | — | — | No GRACE; no IERS residual calibration |
| 1962–2002 | ✓ | ✓ | — | ✓ | IERS calibrated; no GRACE |
| 2002–2026 | ✓ | ✓ | ✓ | ✓ | All components active |
| 2026+ | ✓ | mean | trend | — | Future extrapolation |
The 1840–1962 regime is the least well-characterised. cryo_delta_t
returns 0.0 here (no GRACE coverage, and pre-2002 ice-loss rates were
small enough that the omission introduces < 0.05 s error). The residual
spline also returns 0.0 here — the fit window begins at 1962 and the
ext=1 flag on UnivariateSpline enforces zero outside the knot range.
This means the 1840–1962 model is secular + core only, with no
empirical correction. The validation check for this era is therefore
a comparison against the SMH 2016 table, not the IERS measured table.
The target is agreement within ±2 s across 1840–1962, which is consistent
with the known residual amplitude of the Gillet core series relative to
the SMH 2016 reconstruction. If the comparison reveals a systematic
offset larger than 2 s, the likely cause is a bias in the integration
constant of the Gillet series, which should be corrected in
fetch_grace_j2.py rather than by introducing a new free parameter.
Residual fitting procedure:
The residual is the difference between the IERS measured Delta T and the sum of the three physical components. It captures everything the physical model does not explicitly model: atmospheric and oceanic angular momentum (AAM/OAM), small unmodeled GIA terms, instrument noise in the IERS table, and any systematic bias in the Gillet core series. Because it is absorbing genuine geophysical signal as well as noise, it must be treated carefully — an interpolating spline would overfit the noise; a polynomial would underfit the real AAM signal.
Step 1 — Compute the raw residual series:
residual(y) = IERS_measured(y) − secular_trend(y) − core_delta_t(y) − cryo_delta_t(y)
Evaluated at every annual IERS Bulletin B annual-mean epoch from 1962.5 to the last confirmed measurement year (currently ~2024). IERS Bulletin A predictions (2025–2026) are excluded from the fit to avoid introducing forecasted values into the calibration.
Definition of "confirmed": A year is considered confirmed when its
final annual Delta T value has appeared in IERS Bulletin B, which publishes
definitive UT1−UTC values with a latency of approximately 35 days. In
practice this means the fit window lags the current date by roughly
one month. The cut point is determined programmatically by
update_reference_anchor.py, which reads the Bulletin B table and
identifies the last year for which a full 12-month average is available.
Bulletin A weekly predictions — which carry formal uncertainties of
±0.0025 s for the current week growing to ±0.030 s at 90 days — are
never used as calibration data, only as the source for REFERENCE_LOD
at REFERENCE_YEAR when that year has not yet been confirmed by Bulletin B.
Step 2 — Annual residual fit with boundary taper:
The raw annual residual contains genuine interannual AAM/OAM signal at the 0.1–0.3 s level riding on top of longer-period geophysical signal. Moira fits the annual residuals directly and controls roughness through the smoothing factor and knot cap rather than by applying a pre-smoothing moving average.
Step 3 — Smoothing spline with fixed knot placement:
A smoothing spline (not an interpolating spline) is used.
scipy.interpolate.UnivariateSpline with explicit smoothing factor s:
from scipy.interpolate import UnivariateSpline
spline = UnivariateSpline(
years_fit, # annual-mean points 1962.5–2024.5
residual_fit, # annual residual after boundary taper
k=3, # cubic
s=s_factor, # tuned smoothing factor with bounded knot count
ext=1, # return 0.0 outside the knot range (no extrapolation)
)
The smoothing factor is initialized below N so annual residual structure
remains visible without exact interpolation. If the automatic knot count
exceeds ~20 over the measured window, s is increased until it falls back
to that range.
Knot placement is not fixed manually — it is solver-determined from the smoothing constraint. Manual knot placement would require knowledge of where the geophysical signal changes character, which is not available a priori. The smoothing parameter approach is more honest: it sets a resolution floor and lets the data determine where variation occurs.
Step 4 — Zero-derivative boundary condition at 2026:
The spline must not extrapolate beyond 2026. The ext=1 parameter in
UnivariateSpline enforces this by returning 0.0 outside the data range,
which is equivalent to assuming the residual contribution is zero in the
future. This is the correct assumption: the future model already absorbs the
mean recent residual implicitly through the continuity constraint
REFERENCE_LOD ≡ IERS_measured(REFERENCE_YEAR) − core − cryo − residual
at REFERENCE_YEAR (see Phase 1 for the full derivation).
To avoid a discontinuity in the first derivative at 2026, the annual residual series is tapered to zero over the final 3 years (2021–2023) using a cosine window:
taper = 0.5 * (1 + cos(π × (y − 2021) / 3)) for y in [2021, 2024)
residual_fit_tapered(y) = residual_fit(y) × taper
This enforces a smooth handoff to zero rather than an abrupt drop, which is important because any kink at 2026 would propagate as a discontinuity in apparent planetary positions at that epoch boundary.
Step 5 — Overfitting diagnostic:
After fitting, compute an interior leave-one-out cross-validation score on the non-boundary annual-mean epochs:
cv_rms = sqrt(mean((residual_fit(y_i) − spline_without_i(y_i))²
for interior annual-mean points y_i))
If cv_rms > 0.5 s, the smoothing factor is too small (overfitting).
If the in-sample RMS exceeds 0.5 s, the smoothing factor is too large
(underfitting — the spline is not tracking real geophysical signal).
The operational target is cv_rms < 0.5 s.
This diagnostic is run automatically in scripts/validate_delta_t_hybrid.py
and its result is reported in the validation output alongside the in-sample
RMS so the fit quality is always visible.
Validation targets:
- RMS residual against IERS measured table < 0.5 s (1962–2026)
- Max residual < 2.0 s anywhere in 1962–2026
- Future projection (2026–2100) compared against the conventional Morrison/Stephenson/Espenak long-term forecast
Deliverables:
delta_t_physical.delta_t_hybrid()— assembled model (implemented)delta_t_physical.delta_t_hybrid_uncertainty(year)— returns ±1σ estimate per section 8 (implemented)delta_t_physical.DeltaTBreakdown/delta_t_breakdown(year)— per-component breakdown dataclass (implemented)delta_t_physical.DeltaTDistribution/delta_t_distribution(year)— normal approximation PDF (mean, sigma, pdf(), interval()) (implemented)delta_t_physical._future_secular_baseline(year)— owned future deterministic trend from tidal/GIA at their own reference epochs (implemented)delta_t_physical._future_stochastic_delta_t_sigma(year)— integrated Brownian LOD noise:sigma = (JULIAN_YEAR/1000) * sigma_LOD * sqrt(T³/3)(implemented)delta_t_physical._fitted_residual_spline()— smoothing spline fit per section 4 procedure, returning the spline plus named diagnostics (cv_rms,in_sample_rms,knot_count) (implemented)scripts/validate_delta_t_hybrid.py— full comparison against IERS and the conventional long-term forecast; reports CV score, knot count, and the stochastic future envelope- Updated
julian.py— add hybrid model as opt-in path alongside currentdelta_t()function (not replacing it — parallel implementation first)
Effort: 2 weeks
Phase 5 — Integration and validation
Goal: Wire the hybrid model into the engine, validate against the Horizons apparent-position suite, and update the documentation.
Integration strategy:
The hybrid model is added as a parallel path, not a replacement:
# julian.py
def ut_to_tt(
jd_ut: float,
year: float | None = None,
model: str = "smh2016", # "smh2016" | "hybrid"
) -> float:
...
Default remains "smh2016" so no existing test breaks. The hybrid model
can be selected explicitly for research use or future-facing calculations.
Validation against Horizons:
Run the existing test_horizons_planet_apparent.py suite with both models.
For 1900–2026 the results should be within measurement noise of each other.
Document any differences.
For future epochs (2050, 2100), generate predicted positions under both
models and document the divergence envelope — this becomes the new section 6
of VALIDATION_ASTRONOMY.md.
Deliverables:
julian.pyupdated withmodelparameter onut_to_tttests/integration/test_delta_t_hybrid.py— comparison against IERS table- Updated
VALIDATION_ASTRONOMY.mdsection 6 with three-model comparison - Updated
BEYOND_SWISS_EPHEMERIS.md— physics-based Delta T as a differentiating capability scripts/update_reference_anchor.py— defined procedure below
update_reference_anchor.py — trigger, threshold, and validation:
This script is the maintenance entry point for keeping REFERENCE_LOD and
REFERENCE_YEAR current as IERS measurements accumulate. Its behavior must
be precisely defined to avoid silent model drift.
Trigger: Manual execution only. It is not run automatically in CI because updating a physical constant requires human review. The expected cadence is once per year, after the January IERS Bulletin B confirms the previous year's annual mean Delta T.
Procedure:
- Download the latest IERS Bulletin B finals2000A.all from
https://datacenter.iers.org/data/csv/finals2000A.all.csv - Identify the last calendar year Y for which all 12 monthly UT1−UTC values are confirmed (Bulletin B flag, not Bulletin A)
- Compute the annual mean:
ΔT_confirmed = 32.184 + mean(TAI−UT1, year Y) - Recompute
REFERENCE_LODfrom the continuity constraint equation using the currentcore_delta_t(Y),cryo_delta_t(Y), andresidual_spline(Y)values - Write the updated constants to
delta_t_physical.py - Run the full unit and integration test suite before committing
Drift threshold: If the new REFERENCE_LOD differs from the current
value by more than 0.5 s, the script aborts with an explicit warning
rather than silently updating. A shift larger than 0.5 s in a single year
indicates either an error in the Bulletin B parse, an anomalous IERS
measurement, or a systematic offset in one of the physical components that
needs investigation. This is not a failure that should be automatically
absorbed — it requires a human decision about whether to update the
component models or accept the shift.
Test: tests/unit/test_delta_t_physical.py includes a test that
reconstructs REFERENCE_LOD from the continuity constraint equation and
asserts it matches the stored constant to within 0.01 s. This test will
fail if the constants are updated inconsistently — for example if
REFERENCE_YEAR is advanced without recomputing REFERENCE_LOD.
Effort: 1 week
4. Data Dependencies
| Data | Source | License | Size | Fetch method |
|---|---|---|---|---|
| GRACE/GRACE-FO TN-14 J2 series | NASA PO.DAAC | Public domain | ~50 KB | HTTP download |
| Gillet et al. 2019 core AM table | JGR supplementary | CC-BY | ~10 KB | Manual download + commit |
| ICE-6G GIA rotation rate | Peltier et al. 2015 | Published table | ~1 KB | Hardcoded constant |
| IERS measured Delta T 1962–present | IERS Bulletin B | Public domain | ~5 KB | Already in repo |
| SMH 2016 HPIERS table | HMNAO | Public domain | ~30 KB | Already in repo |
All data is either already in the repo or freely downloadable without registration. No commercial data sources are required.
5. File Manifest
moira/
delta_t_physical.py — new module (Phases 1–4)
delta_t_uncertainty.py — uncertainty components per section 8
julian.py — add model= parameter to ut_to_tt (Phase 5)
data/
grace_lod_contribution.txt — generated by fetch_grace_j2.py (Phase 2)
core_angular_momentum.txt — Gillet et al. 2019 table (Phase 3)
scripts/
fetch_grace_j2.py — download + process GRACE TN-14 (Phase 2)
validate_secular_trend.py — Phase 1 validation plot
validate_delta_t_hybrid.py — Phase 4 full comparison
update_reference_anchor.py — recompute REFERENCE_LOD when new IERS Bulletin B arrives
tests/
unit/
test_delta_t_physical.py — unit tests for all components
integration/
test_delta_t_hybrid.py — comparison against IERS measured table
moira/docs/
DELTA_T_HYBRID_MODEL.md — this document
VALIDATION_ASTRONOMY.md — section 6 updated (Phase 5)
BEYOND_SWISS_EPHEMERIS.md — physics-based Delta T entry added (Phase 5)
6. Timeline
| Phase | Content | Effort | Dependency |
|---|---|---|---|
| 1 | Secular trend (tidal + GIA) | 1 week | None |
| 2 | GRACE cryosphere component | 2 weeks | Phase 1 |
| 3 | Core angular momentum component | 2 weeks | Phase 1 |
| 4 | Residual fitting + model assembly | 2 weeks | Phases 2 + 3 |
| 5 | Integration + validation | 1 week | Phase 4 |
Total: ~8 weeks
Phases 2 and 3 can run in parallel once Phase 1 is complete.
7. Success Criteria
| Criterion | Target |
|---|---|
| RMS residual vs IERS 1962–2026 | < 0.5 s |
| Max residual vs IERS 1962–2026 | < 2.0 s |
| Future divergence from Horizons-frozen by 2100 | Documented, not minimized |
| No regression in existing Horizons apparent-position suite | All 120 cases pass |
| No regression in ERFA suite | All 84 cases pass |
| Hybrid model documented with explicit source citations | Yes |
| Uncertainty estimate available at each epoch | Yes — per section 8 |
| Uncertainty dominated by core-mantle term documented explicitly | Yes |
8. Uncertainty Model
delta_t_hybrid_uncertainty(year) returns a ±1σ estimate in seconds. This
section defines how that estimate is constructed for each component and how
the components are combined into a total.
8.1 Tidal uncertainty
Source: Uncertainty in the lunar secular acceleration ṅ.
The Chapront et al. (2002) value is ṅ = −25.858 ± 0.003 arcsec/cy².
The tidal Delta T coefficient is proportional to ṅ, so the fractional
uncertainty propagates directly:
σ_tidal(y) = |secular_trend(y) − secular_trend_at_reference| × (0.003 / 25.858)
≈ TIDAL_COEFF × t² × 0.000116
where t = (year − 2026) / 100.
Magnitude: By 2100 (t = 0.74), σ_tidal ≈ 0.002 s. Negligible.
8.2 GIA model uncertainty
Source: Spread across published GIA models (ICE-6G, ANU, Caron 2018).
The GIA rotation contribution ranges from approximately −0.5 to −0.7 ms/century across models, reflecting uncertainty in ice sheet history and mantle viscosity. This translates to an uncertainty in GIA_COEFF of roughly ±0.5 s/cy².
σ_GIA(y) = 0.5 × t²
Magnitude: By 2100 (t = 0.74), σ_GIA ≈ 0.27 s. Small but not negligible at century timescales.
The implementation uses the Caron (2018) central value and treats the inter-model spread as the ±1σ bound. This is conservative — the spread includes older models that predate the best current ice sheet reconstructions.
8.3 GRACE J2 measurement and trend uncertainty
Source: Two distinct contributions:
Measurement uncertainty (2002–present): The GRACE/GRACE-FO TN-14 J2 series carries formal measurement uncertainties of approximately ±0.5 × 10⁻¹¹ per monthly epoch. Converting to LOD:
σ_cryo_measured ≈ 0.003 s (during GRACE coverage window)
Negligible for apparent-position work.
Trend extrapolation uncertainty (post-GRACE): The cryosphere LOD trend is estimated from a linear fit to the last 5 years of available GRACE-FO data. The uncertainty on this trend is taken as the ±1σ of the linear regression:
σ_trend ≈ ±0.002 ms/year (from regression residuals)
Accumulated over a forward projection of Δt years:
σ_cryo_projected(year) = σ_trend × (year − grace_end) [seconds]
Magnitude: By 2100 with grace_end ≈ 2026, σ_cryo_projected ≈ 0.15 s. Modest but explicitly propagated rather than ignored.
8.4 Core-mantle unpredictability
Source: Genuine physical unpredictability of core flow fluctuations beyond a few years.
This remains a physical uncertainty source for future Delta T. Core-mantle angular momentum exchange produces LOD variations of ±2–4 ms on decadal timescales. These fluctuations are not forecastable beyond the current geomagnetic secular variation window (~5 years ahead).
For the future extrapolation the core component is frozen at the terminal measured value (see Phase 3). The ±1σ uncertainty is taken as the standard deviation of the recent decorrelation window:
core_values_last_10y = [core_delta_t(y) for y in recent_years]
σ_core_future = std(core_values_last_10y) # typically 1–2 s
This is not a measurement uncertainty — it is an honest statement that decade-scale Earth rotation fluctuations of this magnitude will occur but their sign and timing cannot be predicted.
Magnitude: σ_core_future ≈ 1–2 s. This is no longer the dominant long-range term once integrated stochastic LOD variance is admitted.
For the historical era (within the Gillet coverage window), the core component is directly observed rather than extrapolated. Its uncertainty is the formal uncertainty of the Gillet et al. angular momentum inversion, approximately ±0.3 s.
8.5 Integrated stochastic LOD process (Ornstein-Uhlenbeck)
Source: LOD variability that is unpredictable but physically bounded by mean-reversion.
The LOD anomaly is modeled as an Ornstein-Uhlenbeck (O-U) process rather than a Brownian random walk. The O-U process captures two key physical features:
- Short-term positive autocorrelation: Core fluid dynamics have memory on ~10-year timescales, so consecutive LOD values are correlated.
- Long-term mean reversion: Earth’s rotation cannot drift arbitrarily far from equilibrium. The O-U drag term prevents the uncertainty cone from expanding without bound.
The SDE for the LOD anomaly $x(t)$:
$$dx_t = -\theta, x_t, dt + \sigma, dW_t$$
where:
- $\theta$ =
_LOD_OU_REVERSION_RATE= 0.1/year ($\tau = 10$ yr — core-mantle decorrelation timescale, Gillet et al. 2010, 2022; Christensen & Tilgner 2004) - $\sigma$ =
_LOD_RANDOM_WALK_SIGMA_MS_PER_DAY_SQRT_YEAR= 0.2379 ms/day/√year (calibrated from IERS EOP C04 annual-mean LOD series 1962–2026; see Calibration below) - $\mu = 0$ (zero long-term mean anomaly, $x_0 = 0$ at
REFERENCE_YEAR)
Exact variance of $\Delta T$ under O-U LOD:
Delta T is the time integral of LOD anomaly, $\Delta T(T) = (J/1000)\int_0^T x(t),dt$. For $x_0=0$ the variance is:
$$\text{Var}[\Delta T(T)] = \left(\frac{J}{1000}\right)^{!2}\frac{\sigma^2}{2\theta^3} \Bigl[2\theta T - 2(1-e^{-\theta T}) - (1-e^{-\theta T})^2\Bigr]$$
where $J$ = JULIAN_YEAR (365.25 days/yr) and $T$ is the forecast horizon in
years. The square bracket is always non-negative.
Limiting behavior:
| Regime | Bracket limit | Growth |
|---|---|---|
| $\theta T \ll 1$ (short horizon) | $\frac{2}{3}(\theta T)^3$ | $\sigma_{\Delta T} \propto T^{3/2}$ — recovers Brownian exactly |
| $\theta T \gg 1$ (long horizon) | $2\theta T - 3$ | $\sigma_{\Delta T} \propto T^{1/2}$ — bounded diffusion |
Comparison: Brownian vs O-U ($\theta = 0.1$/yr):
| Epoch | Brownian $\sigma_{\text{LOD}}$ | O-U $\sigma_{\text{LOD}}$ |
|---|---|---|
| 2050 | ~5.7 s | ~2.9 s |
| 2075 | ~16.6 s | ~5.1 s |
| 2100 | ~30.9 s | ~6.7 s |
The O-U model produces a substantially narrower uncertainty cone. The conventional 2100 forecast (202.7 s) is now ~3.7σ from the Moira mean (177.9 s) rather than ~0.8σ under the Brownian model. The O-U result is the more honest statement: Earth rotation cannot drift indefinitely, so the tidal+GIA secular baseline is a precise long-range prediction, not an uncertain guess.
Calibration of $\sigma$ from IERS EOP C04 data:
The diffusion coefficient is calibrated using the first-difference method
against the IERS EOP C04 annual-mean LOD series (1962.5–2026.5, N=65;
moira/data/core_angular_momentum.txt). First differences of consecutive
annual-mean LOD values are trend-invariant — they eliminate any linear or
quadratic secular drift without needing to specify which trend to remove.
For an O-U process sampled at $\Delta t = 1$ yr:
$$\text{RMS}(\Delta x) = \sigma \sqrt{\frac{1 - e^{-\theta}}{\theta}} \qquad\Rightarrow\qquad \sigma = \frac{\text{RMS}(\Delta x)}{\sqrt{(1-e^{-\theta})/\theta}}$$
From the IERS data: $\text{RMS}(\Delta x) = 0.2321$ ms/day, correction $= \sqrt{(1-e^{-0.1})/0.1} = 0.9756$, giving $\sigma = 0.2379$ ms/day/√year.
Three independent estimates converge:
| Method | $\sigma$ (ms/day/√yr) |
|---|---|
| First-difference (trend-invariant) | 0.2379 |
| OLS-detrend stationary variance | 0.2341 |
| Previous empirical estimate | 0.2300 |
All three agree to within 3.4%, confirming the calibration. The stationary LOD std implied is $\sigma/\sqrt{2\theta} = 0.2379/\sqrt{0.2} = 0.532$ ms/day, consistent with the directly measured OLS-detrend std of 0.524 ms/day.
Choice of $\theta$: The data-derived lag-1 autocorrelation gives $\tau \approx 6.2$ yr, but this likely reflects quasi-periodic core torsional waves (Gillet et al. 2013) rather than diffusive decorrelation. The literature value $\tau = 10$ yr ($\theta = 0.1$/yr) from geomagnetic secular-variation studies (Gillet et al. 2010, 2022; Christensen & Tilgner 2004) is used, as it better matches the observed stationary variance and represents the physically appropriate diffusive scale for long-range forecasting.
Authority: Exact analytic result for the integral of a zero-mean O-U process starting from zero. See Gardiner (2004) Handbook of Stochastic Methods §4.4; Ricciardi & Sacerdote (1979).
Implementation: _future_stochastic_delta_t_sigma(year) using
_LOD_OU_REVERSION_RATE (θ) and _LOD_RANDOM_WALK_SIGMA_MS_PER_DAY_SQRT_YEAR (σ)
in moira/delta_t_physical.py.
8.6 Residual spline uncertainty
Source: Uncertainty in the smoothing spline fit to
IERS_measured − (secular + core + cryo) over 1962–2023.
Three distinct contributions:
Within the coverage window (1962–2023): The spline tracks annual residuals directly with a target in-sample RMS < 0.2 s. The dominant uncertainty here is the finite knot budget and leave-one-out cross-validation residual, not a pre-smoothing lag.
At the taper boundary (2021–2024): The cosine taper forces the residual to zero over the final 3 years of the fit window. If the true residual is non-zero at 2024, this introduces a deliberate bias of up to ~residual(2024) × 0.5 s at that epoch. This is the correct trade-off: a smooth handoff to zero is preferable to a spline that has a large derivative at the boundary and would extrapolate badly.
Beyond 2026: The spline returns exactly 0.0 (ext=1). The uncertainty is the RMS of the residual series over the fit window, taken as a flat ±1σ estimate for all future epochs:
σ_residual(year > 2026) = rms(residual_fit, 1962–2023)
Expected to be < 0.4 s based on the cross-validation target band.
Overfitting guard:
If the leave-one-out cross-validation score exceeds 0.4 s, the smoothing
factor is increased and the fit is rerun. This is enforced automatically
in validate_delta_t_hybrid.py and the final CV score is stored alongside
the spline coefficients so the fit quality is reproducible.
8.7 Total uncertainty assembly
The six components are treated as independent (the physical drivers are genuinely uncorrelated on the relevant timescales) and combined in quadrature:
def delta_t_hybrid_uncertainty(year: float) -> float:
"""
±1σ uncertainty on delta_t_hybrid(year), in seconds.
Components are combined in quadrature (independent sources).
Dominant long-range term is the integrated stochastic LOD process.
"""
σ_tidal = _tidal_uncertainty(year)
σ_GIA = _gia_uncertainty(year)
σ_cryo = _cryo_uncertainty(year)
σ_core = _core_uncertainty(year)
σ_residual = _residual_uncertainty(year)
σ_lod = _future_stochastic_delta_t_sigma(year)
return math.sqrt(
σ_tidal**2 + σ_GIA**2 + σ_cryo**2 + σ_core**2
+ σ_residual**2 + σ_lod**2
)
Representative totals:
| Epoch | σ_tidal | σ_GIA | σ_cryo | σ_core | σ_residual | σ_LOD stochastic | σ_total |
|---|---|---|---|---|---|---|---|
| 2026 (anchor) | 0.00 s | 0.00 s | 0.003 s | 0.30 s | 0.01 s | 0.0 s | ~0.3 s |
| 2050 | 0.001 s | 0.08 s | 0.06 s | 1.5 s | 0.4 s | ~2.9 s | ~3.2 s |
| 2075 | 0.001 s | 0.17 s | 0.10 s | 1.5 s | 0.4 s | ~5.1 s | ~5.4 s |
| 2100 | 0.002 s | 0.27 s | 0.15 s | 1.5 s | 0.4 s | ~6.7 s | ~6.8 s |
At short horizons (a few decades) $\sigma_{\text{core}}$ dominates. At century timescales $\sigma_{\text{LOD}}$ grows to dominate, but its growth is sub-cubic: the O-U mean-reversion limits it to ~$T^{1/2}$ at long horizons rather than the $T^{3/2}$ of a Brownian walk.
In arcseconds (for reference): A 6.8 s $\Delta T$ uncertainty at 2100 translates to approximately:
- Moon: ~3.7″
- Sun: ~0.28″
- Mercury (near max elongation): ~0.6″
- Outer planets: smaller, but not zero
This is the honest long-range policy envelope for any Earth-rotation-based timescale model without a primary long-term UT1 oracle.
9. What This Does Not Solve
-
Ancient Delta T uncertainty (pre-700 BCE): The irreducible uncertainty from chaotic Earth rotation fluctuations is ~±30 minutes at 500 BCE. No physical model can reduce this — it requires eclipse records that do not exist. The SMH 2016 table remains the best available answer for ancient dates.
-
The 1840 lower boundary: The hybrid model delegates to SMH 2016 for all dates before 1840.0. This boundary is set by the start of the Gillet et al. (2019) core angular momentum series, which is the earliest date for which a geomagnetic-field-based core flow reconstruction is available with sufficient resolution to contribute meaningfully. Using 1840 rather than 1955 (IERS measurements) or 1962 (residual spline start) is a deliberate choice: it maximises the era over which the physical model replaces the empirical SMH 2016 polynomial, even though in the 1840–1962 window only
secular + coreare active. Using 1962 as the boundary would mean the hybrid model offers no improvement over SMH 2016 for the entire 19th century, which is the era where the two approaches differ most. -
The Horizons comparison discrepancy: The 0.576" worst-case error in the current Horizons validation suite is primarily a Delta T convention difference between Moira and Horizons, not a model deficiency. The hybrid model will not eliminate this — Horizons uses its own internal Delta T that will never exactly match any external model.
-
Sub-arcsecond future accuracy: Even the best physical model cannot predict future Earth rotation fluctuations at the sub-arcsecond level. The improvement is in the secular trend and the justified uncertainty quantification, not in achieving Horizons-level agreement for 2100.
10. References
All physical constants and model choices in this document are traceable to the following publications. DOIs are provided for unambiguous identification.
Tidal braking — lunar secular acceleration:
Chapront, J., Chapront-Touzé, M., & Francou, G. (2002). A new determination of lunar orbital parameters, precession constant and tidal acceleration from LLR measurements. Astronomy & Astrophysics, 387, 700–709. https://doi.org/10.1051/0004-6361:20020420
GIA rotation contribution:
Caron, L., Ivins, E. R., Larour, E., Adhikari, S., Nilsson, J., & Blewitt, G. (2018). GIA model statistics for GRACE hydrology, cryosphere, and ocean science. Geophysical Research Letters, 45(5), 2203–2212. https://doi.org/10.1002/2017GL076338
Peltier, W. R., Argus, D. F., & Drummond, R. (2015). Space geodesy constrains ice age terminal deglaciation: The global ICE-6G_C (VM5a) model. Journal of Geophysical Research: Solid Earth, 120(1), 450–487. https://doi.org/10.1002/2014JB011176
Core angular momentum series:
Gillet, N., Jault, D., & Finlay, C. C. (2015). Planetary gyre, time-dependent eddies, torsional waves, and equatorial jets at the Earth's core surface. Journal of Geophysical Research: Solid Earth, 120(6), 3991–4013. https://doi.org/10.1002/2014JB011786
Gillet, N., Gerick, F., Jault, D., Schwaiger, T., Aubert, J., & Istas, M. (2022). Satellite magnetic data reveal interannual waves in Earth's core. Proceedings of the National Academy of Sciences, 119(13), e2115258119. https://doi.org/10.1073/pnas.2115258119
(The 2019 JGR paper cited in the text refers to the series of papers from
the Gillet group; the 2022 PNAS paper is the most recent version of the
angular momentum reconstruction and should be checked for updated tables
before committing core_angular_momentum.txt.)
Core flow decorrelation timescale:
Christensen, U. R., & Tilgner, A. (2004). Power requirement of the geodynamo from ohmic losses in numerical and laboratory dynamos. Nature, 429, 169–171. https://doi.org/10.1038/nature02508
Gillet, N., Jault, D., Canet, E., & Fournier, A. (2010). Fast torsional waves and strong magnetic field within the Earth's core. Nature, 465, 74–77. https://doi.org/10.1038/nature09010
GRACE/GRACE-FO J2 technical notes:
Loomis, B. D., Rachlin, K. E., & Luthcke, S. B. (2019). Improved Earth oblateness rate reveals increased ice sheet losses and mass-driven sea level rise. Geophysical Research Letters, 46(12), 6910–6917. https://doi.org/10.1029/2019GL082929
Sun, Y., Riva, R., & Ditmar, P. (2016). Optimizing estimates of annual variations and trends in geocenter motion and J2 from a combination of GRACE data and geophysical models. Journal of Geophysical Research: Solid Earth, 121(11), 8352–8370. https://doi.org/10.1002/2016JB013073
GRACE-FO TN-14 technical note (degree-1 and C20/C30 replacements): https://podaac.jpl.nasa.gov/gravity/gracefo-documentation
SMH 2016 Delta T model:
Stephenson, F. R., Morrison, L. V., & Hohenkerk, C. Y. (2016). Measurement of the Earth's rotation: 720 BC to AD 2015. Proceedings of the Royal Society A, 472, 20160404. https://doi.org/10.1098/rspa.2016.0404
IERS conventions and Bulletin B:
Petit, G., & Luzum, B. (Eds.) (2010). IERS Conventions (2010). IERS Technical Note No. 36. Verlag des Bundesamts für Kartographie und Geodäsie. https://www.iers.org/IERS/EN/Publications/TechnicalNotes/tn36.html
IERS Bulletin B (monthly, definitive UT1−UTC): https://www.iers.org/IERS/EN/Publications/Bulletins/bulletins.html