zoneinfo vs zoneinfo-leaps
Maybe this is a FAQ but I haven't found the answer. Having studied up the tzfile(5) format and written some code to produce these files, I'm wondering why the files in zoneinfo-leaps include the leap records AND adjust the transition times by the appropriate number of leap seconds. This seems redundant to me. If the file includes the leap second records, why not let the consumer adjust the transitions? -- Kenneth Murchison Principal Systems Software Engineer Carnegie Mellon University
Ken Murchison <murch@andrew.cmu.edu> writes:
Having studied up the tzfile(5) format and written some code to produce these files, I'm wondering why the files in zoneinfo-leaps include the leap records AND adjust the transition times by the appropriate number of leap seconds. This seems redundant to me. If the file includes the leap second records, why not let the consumer adjust the transitions?
Because the values are meant to be time_t timestamps, and for these files they're intended for a notional system in whose time_t 946684822 rather than 946684800 represents a date of 2000-01-01 00:00:00 UTC..
On 16 Nov 2015, at 21:42, Random832 <random832@fastmail.com> wrote:
Ken Murchison <murch@andrew.cmu.edu <mailto:murch@andrew.cmu.edu>> writes:
Having studied up the tzfile(5) format and written some code to produce these files, I'm wondering why the files in zoneinfo-leaps include the leap records AND adjust the transition times by the appropriate number of leap seconds. This seems redundant to me. If the file includes the leap second records, why not let the consumer adjust the transitions?
Because the values are meant to be time_t timestamps, and for these files they're intended for a notional system in whose time_t 946684822 rather than 946684800 represents a date of 2000-01-01 00:00:00 UTC..
As I’m sure a good many people reading this are aware … Also Posix specifically says that there are 86400 seconds in a day, every day, without exception. It allows for the time 23:59:60 by saying that the time in seconds is /approximately/ the time since midnight at the start of 1970 … It’s a mess, but it’s a well-intentioned mess. t + 86400 is this time tomorrow. For those few people who are prepared to do arithmetic “properly” (tomorrow might be t + 86399 or t + 86401) the timezone files including leap seconds are available. That’s not a posix system though … you pays your money, you takes your choice. jch
On Mon 2015-11-16T22:07:19 +0000, John Haxby hath writ:
t + 86400 is this time tomorrow.
Except on the day of the daylight/standard transition, when any code making that assumption fails. -- Steve Allen <sla@ucolick.org> WGS-84 (GPS) UCO/Lick Observatory--ISB Natural Sciences II, Room 165 Lat +36.99855 1156 High Street Voice: +1 831 459 3046 Lng -122.06015 Santa Cruz, CA 95064 http://www.ucolick.org/~sla/ Hgt +250 m
On Nov 16, 2015, at 2:07 PM, John Haxby <john.haxby@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.
by saying that the time in seconds is /approximately/ the time since midnight at the start of 1970 …
It’s a mess, but it’s a well-intentioned mess. t + 86400 is this time tomorrow. For those few people who are prepared to do arithmetic “properly” (tomorrow might be t + 86399 or t + 86401)
Where "properly" means "break the time_t down into year/month/day/hour/minute/second, add 1 to the day, carry into the month if that makes the day number bigger than the number of days in the month in question, carry into the year if carrying into the month makes it go from 11 to 12, and then convert that back into a time_t".
On 16/11/15 22:17, Guy Harris wrote:
On Nov 16, 2015, at 2:07 PM, John Haxby <john.haxby@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_... and this says that there can be 61 seconds in a minute: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html 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 */ tm->tm_sec++; } 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. jch
On Nov 17, 2015, at 7:58 AM, John Haxby <john.haxby@oracle.com> wrote:
On 16/11/15 22:17, Guy Harris wrote:
On Nov 16, 2015, at 2:07 PM, John Haxby <john.haxby@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_...
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 http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_... 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.
On Nov 17, 2015, at 10:55 AM, Guy Harris <guy@alum.mit.edu> wrote:
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.
Well, no, they wouldn't, as that's California time for that value, not UTC. However, I also doubt they'd return 2015-06-30 23:59:60 UTC for it.
On Mon, Nov 16, 2015 at 3:48 PM, Ken Murchison <murch@andrew.cmu.edu> wrote:
Maybe this is a FAQ but I haven't found the answer.
Having studied up the tzfile(5) format and written some code to produce these files, I'm wondering why the files in zoneinfo-leaps include the leap records AND adjust the transition times by the appropriate number of leap seconds. This seems redundant to me. If the file includes the leap second records, why not let the consumer adjust the transitions?
Because even after you have found the prevailing offset using the adjusted transition times you still need to break down the resultant "local" seconds count into the YMDhms fields, and that is most easily done using an 86400-seconds-per-day value. That is, it helps to undo the adjustment. You also need the leap records to determine the magnitude of the tm_sec field during leaps (see the "hit" variable, which probably shouldn't be a bool BTW). Finally, the leap records are also used to implement the time2posix() and posix2time() functions for translating to/from Posix timestamps.
Bradley White <bww@acm.org> writes:
Because ...
You also need the leap records to determine the magnitude of the tm_sec field during leaps (see the "hit" variable, which probably shouldn't be a bool BTW).
I think the question was the opposite - not why the leap records exist, but why they're not the _only_ difference between a leap tzfile and a non-leap one.
On Mon, Nov 16, 2015 at 11:20 PM, Random832 <random832@fastmail.com> wrote:
Bradley White <bww@acm.org> writes:
Because ...
You also need the leap records to determine the magnitude of the tm_sec field during leaps (see the "hit" variable, which probably shouldn't be a bool BTW).
I think the question was the opposite - not why the leap records exist, but why they're not the _only_ difference between a leap tzfile and a non-leap one.
That may be a possibility, but in general it is preferable to do things at zic time over tzfile read time.
On 2015-11-16 13:48, Ken Murchison wrote:
Maybe this is a FAQ but I haven't found the answer.
Having studied up the tzfile(5) format and written some code to produce these files, I'm wondering why the files in zoneinfo-leaps include the leap records AND adjust the transition times by the appropriate number of leap seconds. This seems redundant to me. If the file includes the leap second records, why not let the consumer adjust the transitions?
If you zdump say 1970-1980 posix/Universal vs right/Universal or posix/Europe/London vs right/Europe/London and look at the output, you will see that the latter shows additional transitions for UT with non-zero seconds, zone transition times with :59:60 labels, and the following :00:00 time labels every time there is a leap second. So the UT time scale here appears to be TAI - 10 seconds from 1 Jan 1972 (as TAI was defined to be 10 seconds ahead of UTC then). See http://www.madore.org/~david/computers/unix-leap-seconds.html#tai-minus-10 zdump extract: right/Universal Sat Jul 1 00:00:00 1972 UT = Fri Jun 30 23:59:60 1972 UTC isdst=0 gmtoff=0 right/Universal Sat Jul 1 00:00:01 1972 UT = Sat Jul 1 00:00:00 1972 UTC isdst=0 gmtoff=0 right/Universal Mon Jan 1 00:00:01 1973 UT = Sun Dec 31 23:59:60 1972 UTC isdst=0 gmtoff=0 right/Universal Mon Jan 1 00:00:02 1973 UT = Mon Jan 1 00:00:00 1973 UTC isdst=0 gmtoff=0 right/Universal Tue Jan 1 00:00:02 1974 UT = Mon Dec 31 23:59:60 1973 UTC isdst=0 gmtoff=0 right/Universal Tue Jan 1 00:00:03 1974 UT = Tue Jan 1 00:00:00 1974 UTC isdst=0 gmtoff=0 right/Universal Wed Jan 1 00:00:03 1975 UT = Tue Dec 31 23:59:60 1974 UTC isdst=0 gmtoff=0 right/Universal Wed Jan 1 00:00:04 1975 UT = Wed Jan 1 00:00:00 1975 UTC isdst=0 gmtoff=0 right/Universal Thu Jan 1 00:00:04 1976 UT = Wed Dec 31 23:59:60 1975 UTC isdst=0 gmtoff=0 right/Universal Thu Jan 1 00:00:05 1976 UT = Thu Jan 1 00:00:00 1976 UTC isdst=0 gmtoff=0 right/Universal Sat Jan 1 00:00:05 1977 UT = Fri Dec 31 23:59:60 1976 UTC isdst=0 gmtoff=0 right/Universal Sat Jan 1 00:00:06 1977 UT = Sat Jan 1 00:00:00 1977 UTC isdst=0 gmtoff=0 right/Universal Sun Jan 1 00:00:06 1978 UT = Sat Dec 31 23:59:60 1977 UTC isdst=0 gmtoff=0 right/Universal Sun Jan 1 00:00:07 1978 UT = Sun Jan 1 00:00:00 1978 UTC isdst=0 gmtoff=0 right/Universal Mon Jan 1 00:00:07 1979 UT = Sun Dec 31 23:59:60 1978 UTC isdst=0 gmtoff=0 right/Universal Mon Jan 1 00:00:08 1979 UT = Mon Jan 1 00:00:00 1979 UTC isdst=0 gmtoff=0 Subtract another 9 seconds from that UT time scale from 1980 onwards to get the GPS time scale (TAI - 19) which started from 6 Jan 1980. Prior to 1972, UTC leap (milli-)second adjustments were: 1961-Jan-01 +1.42282s 1961-Aug-01 -0.05s 1962-Jan-01 +0.47304s 1963-Nov-01 +0.1s 1964-Jan-01 +1.29427s 1964-Apr-01 +0.1s 1964-Sep-01 +0.1s 1965-Jan-01 +0.1s 1965-Mar-01 +0.1s 1965-Jul-01 +0.1s 1965-Sep-01 +0.1s 1966-Jan-01 +0.47304s 1968-Feb-01 -0.1s 1972-Jan-01 +5.78683s So handling time could be worse than our current leap second discontinuity every couple of years. Time is understood by lawyers and politicians to be mean solar time plus or minus legal adjustments, like DST and leap seconds. If the ITU-R disconnects their time from earth rotation, we just might have to get more familiar with astronomical time calculations, or maybe we can forget about all this and just use LMT everywhere, keeping tz data around for purely historical dates and times when zones were standard! -- Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
participants (7)
-
Bradley White -
Brian Inglis -
Guy Harris -
John Haxby -
Ken Murchison -
Random832 -
Steve Allen