[tz] zoneinfo vs zoneinfo-leaps

Guy Harris guy at alum.mit.edu
Tue Nov 17 18:55:30 UTC 2015

On Nov 17, 2015, at 7:58 AM, John Haxby <john.haxby at oracle.com> wrote:

> 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:
> http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15
> and this says that there can be 61 seconds in a minute:
> http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html

To be precise, what it say is "the ISO C standard was specifically set up to allow UTC-style labels with leap seconds, so we allow that".  (Doug Gwyn pushed for that in the C standard, for precisely that purpose.  C89 and C90 allow for two leap seconds, so tm_sec can go up to 61; C99 only allows for one, so it can go up to 60.)

I.e., mktime() has to be able to be handled a struct tm with tm_sec = 60, although it has to handle it as per


so it has to, for example, treat { .tm_year=115, .tm_mon=5, .tm_mday=30, .tm_hour=23, .tm_min=59, .tm_sec=60 } the same as { .tm_year=115, .tm_mon=6, .tm_mday=1, .tm_hour=0, .tm_min=0, .tm_sec=0 }.

Tue Jun 30 16:59:59 2015

gmtime() and localtime(), however, don't need to ever return it.

> 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).

Or, rather, a time_t value of 1435708800 could either be 2015-06-30 23:59:59 UTC or 2015-07-01 00:00:00 UTC.

Sadly, without external information, you can't tell which it is.

> 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:

Which is only usable external information if the leap second is in progress.  If you want to know after the fact, well, you're out of luck, and I doubt that any POSIX-compliant gmtime() will return June 30, 2015, 16:59:60 for that value.

More information about the tz mailing list