Thursday, March 03, 2016

[sqfzcxay] Understanding the "right" time zone database

On January 1, 1970, two counters started at 0, incrementing at 1 per second. The "right" counter, as in "doing it right (correctly)", incremented unconditionally at 1 per second.

The "POSIX" counter incremented by 1 per second, but was held back every time a leap second occurred. That is, at a leap second, the counter held the same value for 2 seconds. This kept the counter exactly in sync with the UTC day by a constant conversion of 86,400 counter-increments per day. The UTC day is the basis for the common civilian calendar. It is the length of the average interval of time from noon to noon, even as the earth gradually spins slower (causing the need for leap seconds to be added).

The POSIX counter is by far the most widely deployed counter on Linux computer systems, synonymous with "Unix time". NTP distributes the POSIX counter (plus a constant offset), complete with the weirdness of holding back the counter at each leap second.

Because the POSIX counter has been held back, the right counter will have incremented further than POSIX at any given (recent) point in time. This can be seen by artificially specifying the time zone to the 'date' utility:

$ date -d 'TZ="posix/UTC" 2001-09-09 01:46:40' +'%s'
1000000000
$ date -d 'TZ="right/UTC" 2001-09-09 01:46:40' +'%s'
1000000022

At the point in time "Sun Sep 9 01:46:40 UTC 2001" (this time point is specified UTC, so is unambiguous), the POSIX counter had incremented 1,000,000,000 ticks, while the right counter had incremented 1,000,000,022 ticks, with the additional 22 ticks corresponding to the 22 leap seconds that had been added since January 1, 1970.

Incidentally, the time zone specifier "right/UTC" might seem like an oxymoron, because what the right counter is doing, ignoring leap seconds, is the opposite of what UTC does. One can interpret "right/UTC" as a conversion from "right" to "UTC".

Another incidental thought: What distinguishes UTC from TAI is that UTC adds leap seconds. TAI is similar in spirit as the right counter, though is expressed differently.

The same computation can be done in reverse:

$ TZ=posix/UTC date -d '@1000000000'
Sun Sep 9 01:46:40 UTC 2001
$ TZ=right/UTC date -d '@1000000022'
Sun Sep 9 01:46:40 UTC 2001

Given that the right counter has advanced further than the POSIX counter, then for a given counter value, the right counter corresponds to a date earlier in time. This confused me for a while, inspiring researching and writing this post.

$ TZ=posix/UTC date -d '@1000000000'
Sun Sep 9 01:46:40 UTC 2001
$ TZ=right/UTC date -d '@1000000000'
Sun Sep 9 01:46:18 UTC 2001

That the right counter translates to an earlier time applies to the current counter value as well. Below, we omit the "posix/" prefix to TZ because the system is configured (as most are) to default to POSIX.

$ TZ=UTC date ; TZ=right/UTC date
Thu Mar 3 22:52:58 UTC 2016
Thu Mar 3 22:52:32 UTC 2016

Of course, taking the value of the POSIX counter (which this computer is configured to count, being as it is synchronized with NTP) and reinterpreting it as a right counter value is a highly bogus operation, and therefore returns the incorrect time.

The terms "right counter" and "POSIX counter" are non-standard, invented for this exposition. The names are from the subdirectories of the Time Zone Database (zoneinfo). The "posix" subdirectory is what most people use, translating the POSIX counter to local time in various time zones around the world. The "right" subdirectory is for the very rare cases of a computer configured to use a right counter, perhaps a computer synchronized with a GPS signal (GPS satellites broadcast time, but do not count leap seconds) or directly hooked up to an atomic clock instead of using NTP.

No comments :