krz/moonrise

Night-sky companion for iPhone, Apple Watch and Vision Pro: what's up tonight, the Moon, planets, launches and missions, and a Library of the solar system. SwiftUI app with a Cloudflare Workers backend. astronomy cloudflare-workers ios night-sky space swiftui visionos watchos

Packages/MoonriseKit/Sources/SkyEngine/DeltaT.swift

40 lines · 2041 bytes

3 symbols in this file
 1import CAstronomy
 2import Foundation
 3
 4/// ΔT = TT − UT1, seconds. Measured and predicted IERS values from 2020, with the difference from
 5/// Astronomy Engine's Espenak–Meeus polynomial fading to zero by 2010 and by 2050, so other eras are unchanged.
 6enum DeltaT {
 7    /// Decimal year and 32.184 s + (TAI − UTC = 37 s) − (UT1 − UTC), from IERS finals2000A as of
 8    /// Bulletin A of 15 October 2026. Later entries are its predictions.
 9    static let table: [(year: Double, seconds: Double)] = [
10        (2020.0, 69.361), (2021.0, 69.359), (2022.0, 69.295), (2023.0, 69.204), (2024.0, 69.175), (2025.0, 69.138),
11        (2026.0, 69.110), (2026.789, 69.221), (2027.0, 69.308), (2027.584, 69.382), (2027.748, 69.371),
12    ]
13    static let fadeFrom = 2010.0, fadeTo = 2050.0
14
15    /// `ut`: days since J2000, as Astronomy Engine passes it.
16    static func seconds(ut: Double) -> Double {
17        let model = Astronomy_DeltaT_EspenakMeeus(ut)
18        // The polynomial's own year scale.
19        let year = 2000 + (ut - 14) / 365.24217
20        guard year > fadeFrom, year < fadeTo else { return model }
21        let first = table[0], last = table[table.count - 1]
22        if year < first.year {
23            return model + (first.seconds - polynomial(first.year)) * (year - fadeFrom) / (first.year - fadeFrom)
24        }
25        if year > last.year {
26            return model + (last.seconds - polynomial(last.year)) * (fadeTo - year) / (fadeTo - last.year)
27        }
28        let i = table.firstIndex { $0.year >= year }!
29        guard i > 0 else { return first.seconds }
30        let a = table[i - 1], b = table[i]
31        return a.seconds + (b.seconds - a.seconds) * (year - a.year) / (b.year - a.year)
32    }
33
34    static func polynomial(_ year: Double) -> Double {
35        Astronomy_DeltaT_EspenakMeeus((year - 2000) * 365.24217 + 14)
36    }
37
38    /// Astronomy Engine reads ΔT through a global function pointer; `SkyEngine.time` touches this first.
39    static let installed: Void = Astronomy_SetDeltaTFunction { DeltaT.seconds(ut: $0) }
40}