[tz] zoneinfo vs zoneinfo-leaps

John Haxby john.haxby at oracle.com
Tue Nov 17 15:58:51 UTC 2015

On 16/11/15 22:17, Guy Harris wrote:
> On Nov 16, 2015, at 2:07 PM, John Haxby <john.haxby at oracle.com> wrote:
>> > Also Posix specifically says that there are 86400 seconds in a day, every day, without exception.   It allows for the time 23:59:60
> It does?
> If there are 86400 seconds in every day, then every day begins at 00:00:00 and ends at 23:59:59, which is followed by 00:00:00 of the next day.  No room for 23:59:60 there.

It does, and you can have 23:59:60.

This, obliquely, says that the number of seconds in a day is 86400:


and this says that there can be 61 seconds in a minute:


Which is nice. The upshot is that 1435708799 is ambiguous: you can't
tell whether it was 23:59:59 or 23:59:60 (it was both).

On Linux, adjtimex(2) returns TIME_OOP if you're in the middle of a
leapsecond so that you can tell the difference between the first and
second times through 1435708799:

#include <time.h>
#include <sys/timex.h>

struct tm *gmtimestamp_r(struct tm *tm, long *ns)
    struct timespec ts1, ts2;
    clock_gettime(CLOCK_REALTIME, &ts1);
    if (ts1.tv_sec % 86400 == 86399) {
        struct timex tx = { .modes = 0 };
        int status = adjtimex(&tx);
        clock_gettime(CLOCK_REALTIME, &ts2);
        if (ns)
            *ns = ts2.tv_nsec;
        gmtime_r(&ts2.tv_sec, tm);
        if (status == TIME_OOP && ts1.tv_sec == ts2.tv_sec)
            /* we're in a leap second */
    } else {
        if (ns)
            *ns = ts1.tv_sec;
        gmtime_r(&ts1.tv_sec, tm);
    return tm;

Other platforms that allow ntp to tell the kernel a leap second is on
its way provide similar system calls.  Posix doesn't mention adjtimex(2)
or indeed anything that will tell you if you're in a leap second.

You can have *endless* fun with leap seconds :)  Well, OK, you can bore
people to death.


More information about the tz mailing list