The really annoying part is that "leap smearing" (where people decided to just mush the leap second across about day) has made CLOCK_MONOTONIC unclear in this regard, since some leap smearing approaches affect that as well. Which destroyed any assumption a developer could make about CLOCK_MONOTONIC, since you won't know if leap smearing is in use :(.

(And depending on the leap smearing implementation, it also smears CLOCK_TAI, jumps it to opposite polarity at the actual time of leap second, and then smears it again. The leap smearing people really made a mess of this.)

From a correctness perspective, the only good choice is to go all-in on TAI.

[Ed./P.S.:] "just ignore leap seconds" - that's going all-in on TAI. At this point it's probably easier to redefine UNIX timestamps as TAI based after 2035 ("abolishing leap seconds"), and introduce a new CLOCK_SOLAR_EARTH that accumulates leap seconds and can be used if/where necessary. The main issue is to create a proper delineation between the two clocks, which we just don't have at this point. Way too many systems where it's just not clear what they use.

And note that leap seconds are earth specific too. You'll have entirely different requirements on e.g. Mars.

> made CLOCK_MONOTONIC unclear in this regard

I don't understand what you mean. Doesn't smearing still mean the clock only goes forward? It's still steadily incrementing. The only difference is that a second is slightly longer/shorter than you expect, but you already have to account for that if you're doing the kind of physics experiment where it would matter.

If you have one event per millisecond then you get 86,401,000 events on a day you smear, and that’s inconsistent with the 86,400,000 you get on days either side.

Well CLOCK_MONOTONIC was a bad name for anything that's supposed to do more than be... monotonic, with mild accuracy, so I'm not surprised things became unclear.

But it is just a basic system clock. Being the wrong speed by 15 parts per million shouldn't throw off your data collection. Lots of clocks are more inaccurate by accident.

I don't think I understand.. can you please dumb it down even more?

I'd figured that UNIX time just counts actual seconds and that leap seconds and similar calendar shenanigans would be a problem of mapping epoch to the correct date, so that if normally epoch X maps to date D then both epoch X and X+1 map to date D.

Am i to understand that leap seconds "stretch" a epoch unit ? so that some epoch second "lasted longer".

Unix time does not count elapsed seconds in real time since 1970-01-01T00:00:00, this is a common misconception.

Unix time assumes a fixed number of seconds per day. 86400. If a leap second is inserted, either end of June or end of December, the day is 86401 seconds long.

There are different implementations for how your Unix time will behave 24 hours before to 24 hours after the leap second. A timestamp might just repeat during the leap second or the system changes the length of a second in a time range around the leap second introduction to make up the difference. This is called smearing.

A simple example is the elapsed time between these two timestamps:

    2016-12-31 23:59:50
    2017-01-01 00:00:10
Unix time differs by 20 seconds (assuming the system/library doesn't use smearing). But actually elapsed time is 21 seconds, since

    2016-12-31 23:59:60
was the last added leap second. This timestamp cannot be represented by Unix time (again assuming no smearing, with smearing you could).

> I'd figured that UNIX time just counts actual seconds

It doesn't. UNIX time is 1:1 with what your clock reads, you can convert between 2026-07-10 00:12:25 UTC and 1783642345 by simple math (note how the last digit is the same; but the leap second offset is 37s, that wouldn't align. The TAI timestamp for the same moment in time is 1783642382.)

> and that leap seconds and similar calendar shenanigans would be a problem of mapping epoch to the correct date, so that if normally epoch X maps to date D then both epoch X and X+1 map to date D.

It's the other way around, if you need to get the exact seconds between two UNIX timestamps (or calendar date/time), you need to check if there were any leap second changes between the two.

Counting actual seconds is TAI [https://en.wikipedia.org/wiki/International_Atomic_Time], that one is really just "number of Caesium hyperfine transitions since X", and now the mapping to a calendar date/time for display is a bit involved.

The seconds to calendar date conversion doesn't actually need to know about leap seconds. At the seconds representation level, the same number is repeated twice (or the smearing trategy happens).

So the times before and after leap second get converted the the same date regardless of whether you know about the leap second or not. Edge case is that once second occuring twice. You might have seen that 23:59:60 seconds timestamp somewhere.

I think for the stretch of time where a leap second is smeared, the epoch second would drift by a tiny fraction for each second or etc? So you'd have some chunk of UTC time where each second lasts something like 1.0005 epoch seconds, maybe? This would make converting from unix time to UTC need extra arbitrary handling for display, at least.

> I think for the stretch of time where a leap second is smeared, the epoch second would drift by a tiny fraction for each second or etc? So you'd have some chunk of UTC time where each second lasts something like 1.0005 epoch seconds, maybe?

Yes, 1.0000116s (or 0.9999884s), and to be clear it was never intended like that. It got started after a bunch of bugs in leap second handling caused issues & some people thought it would be better to just stretch/compress time for a period around leap seconds, for docs refer to e.g.: https://developers.google.com/time/smear

Personally speaking - it's a great way of just pushing the problem around, further complicating an already complex situation. 11.6µs is very measurable on a modern system.

> This would make converting from unix time to UTC need extra arbitrary handling for display, at least.

Except you need to know that leap smearing has been applied… which of course noone records. Most systems can't even signal it, much less store. If you need that level of precision, you better make sure none of your systems uses it or you're just screwed.

If you're relying on system time for subsecond precision, you're already screwed on every other day that doesn't have leap seconds.

> 11.6µs is very measurable on a modern system.

11.6µs is very measurable.

Clock skew of 11.6 PPM is much more subtle.

After reading all that, maybe we should just have some bugs in our code and stop making up new things