[tz] TAI as a time zone?

Guy Harris guy at alum.mit.edu
Sun Sep 15 09:52:16 UTC 2013

```On Sep 15, 2013, at 12:36 AM, DataPacRat <datapacrat at gmail.com> wrote:

> On Sun, Sep 15, 2013 at 12:16 AM, Paul Eggert <eggert at cs.ucla.edu> wrote:
>> On 09/14/2013 08:15 PM, DataPacRat wrote:
>>> Would it be feasible to include International Atomic Time (TAI) and/or
>>> GPS time (which differs from TAI by a fixed number of seconds) in the
>>> tz database as a time zone separate from UTC?
>>
>> It should be easy to do for the "right" subdirectory,
>> which supports proper UTC with leap seconds,
>> but I'm not sure how well it'd work for the "posix"
>> subdirectory, which lacks leap seconds.  To find out
>> for sure, someone should try it and see what happens.
>
> I'm afraid that I don't yet know enough about the subdirectories to
> comment, but I do know that the standard for POSIX time includes leap
> seconds - adding one at the appropriate :60 when one's added, or
> jumping from :58 to :00 should one ever be subtracted.

That's "seconds-since-the-Epoch" from my e-mail.  It "includes" leap seconds in the sense of "trying its best to hide their existence" - the formula for "seconds-since-the-Epoch" in the POSIX standard is

tm_sec + tm_min*60 + tm_hour*3600 + tm_yday*86400 +
(tm_year-70)*31536000 + ((tm_year-69)/4)*86400 -
((tm_year-1)/100)*86400 + ((tm_year+299)/400)*86400

which gives the same value 2012/06/30 23:59:60:

60 + 59*60 + 23*3600 + 182*86400 + 42*31536000 + 10*86400 - 1*86400 + 1*86400 = 1341187200

and 2012/07/01 00:00:00:

0 + 0*60 + 0*3600 + 183*86400 + 42*31536000 + 10*86400 - 1*86400 + 1*86400 = 1341187200

which means that, when a leap second is added, the POSIX clock *doesn't* advance for that second (whether the clock just stops for a second or is slowed down until the second is lost).

> A variant which ignores leap seconds and matches TAI is "non-conforming".

That's "seconds that have elapsed since the Epoch", which is perhaps better described as "counting seconds that elapse, including leap seconds", so what it ignores is the distinction between leap seconds and ordinary seconds.

The TZ code is capable of handling "seconds that have elapsed since the Epoch" in the sense that it can convert those values to the corresponding UTC labels, even if that means, for example, setting tm_sec to 60.  That's done if the "leapseconds" source file is used by zic (with the -L flag); in systems that have separate "right" and "posix" subdirectories for sic-compiled files, "right" contains files compiled with "-L leapseconds" and "posix" contains files compiled without "-L leapseconds".

When used with files compiled without "-L leapseconds", the TZ code's gmtime() will turn "seconds-since-the-Epoch" values into "struct tm" values corresponding to one of the UTC labels for the "seconds-since-the-Epoch" value in question.  With positive leap seconds, there are two (or more) UTC labels for some "seconds-since-the-Epoch" values, and it'll return the label that has tm_sec < 60; with negative leap seconds, there may be some "seconds-since-the-Epoch" values that are invalid, and I don't know what it'll return for them.
```