Does Anyone Know What Time It Is?

(https://creativecommons.org/licenses/by-sa/3.0/deed.en)

Time on your computer is wrong. If you’re trying to take a picture of your favorite Starlink satellite, or the International Space Station, your time will be 9 to 27 seconds off, because your Windows, Linux, or Mac, machine doesn’t represent leap seconds. Even worse, your computer likely completely loses a second when a new leap second is added, so at times a timestamp on transactions that actually occurred on two different times will be recorded at the same time.

Further complicating the problem of finding a satellite or planet, is the tables that give the ephemeris of those objects are given in Terrestrial Time (TT). If you track satellites, you can use Space Command’s website https://www.space-track.org/. Your computer, though, probably uses Network Time Protocol (NTP), which uses the Internet Time Service (ITS), which reports Coordinated Universal Time (UTC) as seconds since 1900 (even though UTC didn’t exist in 1900). Andrew Tenenbaum or Grace Hopper or someone else said “The wonderful thing about standards is there so many to choose from”.

So even though ITS and NTP provide UTC, your computer can’t directly use leap seconds. Instead the major time implementations in Windows, Linux, and Mac, smear the time to assign the same timestamp to two different times. If you really want to get confused, use GPS time. GPS time also does not have leap seconds, but it counts the total seconds since the GPS system started. The GPS signal does contain the current offset between UTC and GPS time. Internationally, a set of over 450 atomic clocks combine to maintain International Atomic Time (TAI).

UTC is based on TAI so it trails TAI by the number of accumulated leap seconds, and an additional 10 seconds. The additional 10 seconds comes from the definition of UTC in 1972 when the accumulated adjustments from UT and UTC had already accumulated to 10 seconds (1 January 1972 00:00:00 UTC = 1 January 1972 00:00:10 TAI exactly). Likewise, due to accumulated differences between ephemeris time and TT, TT is defined as 32.184 seconds ahead of TAI.

UTC = TAI – leap seconds – 10 seconds.

 TT = 32.184 s + TAI

The man pages for the time() function on a MacBook state the function returns UTC seconds without the leap seconds. This holds true for almost all Linux and Windows machines too.

Given your computer time is UTC without leap seconds, approximate TT with this equation:

TT = 32.184 s + 10 s + computer time = 42.184 s + computer time

An international organization, International Earth Rotation and Reference Systems Services (IERS), periodically meets and decides if a leap second is needed to UTC within 0.9 seconds of the Earth rotation time UT1 (so far we’ve mentioned UTC, TT, UT1, TAI, and GPS time standards). So called civil time, is related to your local day time. Leap seconds keep the time kept by atomic clocks, roughly in sync with Earth rotation, so lunch time stays roughly at noon, or morning actually occurs in the morning. Leap seconds are needed because the Earth’s rotation is slowing down. Recently, though, the Earth rotation is speeding up, so a leap second hasn’t been needed since 2016. Even though the international standard for UTC allows for the addition of negative leap seconds, it has never been done. I think the prospect of adding a negative leap second has prompted the international organizations to elect to abandon leap seconds by 2035 — so you only need to worry about leap seconds between 1972 and 2035.

So far the equations given here ignore general relativity, where even an atomic clock defined second varies by where the clock is in a gravitational field. For TT this factor is on the order of 10^-10 seconds per day. Over thousands of years the factor accumulates to milliseconds. Only if you need better precision than that should you bother with the more accurate equations. Recall the non-realtime clocks on a typical desktop have a resolution of milliseconds, not microseconds nor nanoseconds.

This leaves us with the problem of determining the elapsed time between two dates, so we need to find the number of leap seconds added so far for each date.

Here is my attempt to return leap seconds given a time_t value:

#include <array>


auto leapSeconds(const time_t t) -> int {
    static const std::array<time_t, 27> leapSecondDates = {
        1483239600,
        1435719600,
        1341111600,
        1230778800,
        1136084400,
        915159600,
        867726000,
        820465200,
        773031600,
        741495600,
        709959600,
        662698800,
        631162800,
        568004400,
        489034800,
        425876400,
        394340400,
        362804400,
        315543600,
        284007600,
        252471600,
        220935600,
        189313200,
        157777200,
        126241200,
        94705200,
        78807600
    };
    constexpr auto lenLeapSecondDates = static_cast<int>(leapSecondDates.size());
    if (t >= leapSecondDates[0]) return lenLeapSecondDates;
    if (t < leapSecondDates.back()) return 0;

    // Leap second dates are the second past the time the leap second was added.
    // Leap second dates are sorted from the most recent to the earlier ones.
    // Find the leap second date just before the specified time.
    int left = 0;
    int right = leapSecondDates.size() - 1;

    while (left < right && t != leapSecondDates[right]) {
        if (const auto mid = (left + right)/2; leapSecondDates[mid] <= t) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return lenLeapSecondDates - right;
}

Resources

https://geometrian.com/resources/timestds

https://github.com/gsdayton98/leap_seconds.git