Using ubuntu 12.04 LTS Using tz 2012 j code/data Tested each timezone mentioned in zone.tab, by zdump-ing each one. Observed that each timezone had two lines that reported NULL, then a bunch of nice-looking pairs-of-lines, then two lines that reported "NULL" I understand that this could be caused if you are using a 64 bit ubuntu on a 32-bit machine.... ...I may have !!! migrated to a 32-bit ubuntu on a 32-bit machine... The lines at the earliest/latest transition for each timezone are no longer "NULL"-containing (they mention 1901 and 2038, which I understand) What is breaking my heart is "Why did the lines drop off the gmtoff value, now ending with the isdst value?" Saw somewhere that tm_gmtoff is a GNU extension that may not be visible... Please "illuminate" Thanks, Jim
Date: Wed, 30 Jan 2013 20:46:04 +0000 From: "Marvel, Jim (CPCOE)" <Jim.Marvel@honeywell.com> Message-ID: <D18226FFAC100147AC344F846CCD2F0C26916216@az18ex3006.global.ds.honeywell.com> | What is breaking my heart is "Why did the lines drop off the gmtoff value, = | now ending with the isdst value?" You have to talk to whoever built the version of zdump that you're using (and as we don't distribute binaries, only sources, it wasn't us.). If that was you (you compiled it yourself) then you need to look carefully at the Makefile for instructions on how to use the gmtoff stuff if it is available on your system. If you got the binary as part of some system or other, then you need to ask the system builders why they chose to exclude it. | Saw somewhere that tm_gmtoff is a GNU extension that may not be visible... It was a BSD extension (that glibc copied, I presume). These days it exists most places, but there are probably stiff a few archaic systems that don't have it. kre
Date: Thu, 31 Jan 2013 06:36:22 +0700 From: Robert Elz <kre@munnari.oz.au> Message-ID: <6086.1359588982@eos.noi.kre.to> | If you got the binary as part of some system or other, then you need to | ask the system builders why they chose to exclude it. It turns out that the most likely cause of this, is that zdump.c does not #include "private.h", and that (at least on some systems) private.h is where the relevant #defines tend to be placed (rather than in CFLAGS in the Makefile). Paul (or Arthur) - any reason you can think of that zdump.c should not include private.h? kre
Paul (or Arthur) - any reason you can think of that zdump.c should not include private.h?
A comment from the top of zdump.c: /* ** This code has been made independent of the rest of the time ** conversion package to increase confidence in the verification it provides. ** You can use this code to help in verifying other implementations. */ --ado On Thu, Jan 31, 2013 at 10:04 AM, Robert Elz <kre@munnari.oz.au> wrote:
Date: Thu, 31 Jan 2013 06:36:22 +0700 From: Robert Elz <kre@munnari.oz.au> Message-ID: <6086.1359588982@eos.noi.kre.to>
| If you got the binary as part of some system or other, then you need to | ask the system builders why they chose to exclude it.
It turns out that the most likely cause of this, is that zdump.c does not #include "private.h", and that (at least on some systems) private.h is where the relevant #defines tend to be placed (rather than in CFLAGS in the Makefile).
Paul (or Arthur) - any reason you can think of that zdump.c should not include private.h?
kre
On 01/31/13 07:04, Robert Elz wrote:
(at least on some systems) private.h is where the relevant #defines tend to be placed (rather than in CFLAGS in the Makefile).
That sounds like a mistake; TM_GMTOFF should not be defined in private.h, since it's a property of struct tm, a public interface, rather than something private to the tz code. The usual way to handle this problem is to have a separate 'configure' script that determines which TM_GMTOFF is appropriate for the current system. We could head in that direction if there's interest, though it would complicate building a bit.
On 2013-01-30 at 20:46 +0000, Marvel, Jim (CPCOE) wrote:
Using ubuntu 12.04 LTS Using tz 2012 j code/data
Tested each timezone mentioned in zone.tab, by zdump-ing each one. Observed that each timezone had two lines that reported NULL, then a bunch of nice-looking pairs-of-lines, then two lines that reported "NULL"
I understand that this could be caused if you are using a 64 bit ubuntu on a 32-bit machine.... ...I may have !!! migrated to a 32-bit ubuntu on a 32-bit machine...
It happens on any platform where time_t is 64-bit but regular ints are 32-bit, which is what most things have settled on. It happens, AFAICT, because gmtime()/localtime() can't handle extreme 64-bit values; it's triggered by the attempt to print the time on the lowest time value and one day later, and one day before max time value and max time, per the man-page. Which is why you see these even if you enter a year range with a start that comes after the end. % ./zdump -c 2017,2010 -v America/New_York America/New_York -9223372036854775808 = NULL America/New_York -9223372036854689408 = NULL America/New_York 9223372036854689407 = NULL America/New_York 9223372036854775807 = NULL The long number is from gmtime() failing, so the number is printed as raw. Then my_localtime() is called to supply what comes after the "="; "tmp = localtime(tp);" results in NULL from the failure, all the decoding logic is skipped, and the NULL is returned; that's passed to dumptime(), which detects the NULL, prints "NULL" and returns. For the negative case, localtime.c:timesub() returns at line 1472 in current git; with an added fprintf(): ----------------------------8< cut here >8------------------------------ while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { int newy; register time_t tdelta; register int idelta; register int leapdays; tdelta = tdays / DAYSPERLYEAR; idelta = tdelta; if (tdelta - idelta >= 1 || idelta - tdelta >= 1) { fprintf(stderr, "frobnozz out a tdelta=%ld idelta=%d\n", tdelta, idelta); return NULL; } ----------------------------8< cut here >8------------------------------ result is then: ----------------------------8< cut here >8------------------------------ frobnozz out a tdelta=-291672107014 idelta=385669114 ----------------------------8< cut here >8------------------------------ The positive case is from localtime.c:localsub() returning at line 1281 in current git; with an added fprintf(): ----------------------------8< cut here >8------------------------------ if (result == tmp) { register time_t newy; newy = tmp->tm_year; if (t < sp->ats[0]) newy -= icycles * YEARSPERREPEAT; else newy += icycles * YEARSPERREPEAT; tmp->tm_year = newy; if (tmp->tm_year != newy) { fprintf(stderr, "frobnozz b out 4 result=%p tmp=%p tmp->tm_year=%d newy=%ld newy-as-int=%d\n", result, tmp, tmp->tm_year, newy, newy); return NULL; } } ----------------------------8< cut here >8------------------------------ result is then: ----------------------------8< cut here >8------------------------------ frobnozz b out 4 result=0x513180 tmp=0x513180 tmp->tm_year=219248568 newy=292277024696 newy-as-int=219248568 ----------------------------8< cut here >8------------------------------ I'm not familiar enough with all the architecture-size testing going around and what the correct approach for this code-base is, but I can at least do the above and isolate where things are failing right now. Hopefully of use to someone? -Phil
Date: Wed, 30 Jan 2013 23:26:16 -0500 From: Phil Pennock <tz-list+phil.pennock@spodhuis.org> Message-ID: <20130131042616.GA69672@redoubt.spodhuis.org> | It happens, AFAICT, because gmtime()/localtime() can't handle extreme | 64-bit values; It isn't that the code cannot handle the values, but because the struct tm data structure cannot represent the result (tm_year doesn't have enough bits). Changing the definition of struct tm is the only way to fix this - but that's a major change to a data structure that has existed in unix for a very very long time (code assumes that %d printf format can print the tm_year value, for example). What's more, aside from zdump, there is very little practical use for times from years outside the range of +/- 2 billion (and a few) to ever get printed in asctime() format (or manipulated as struct tm's). Astronomers, and others, may occasionally want to manipulate times that far away, but they don't really care whether we would call the day they select Tuesday or Wednesday, (etc). Given that, the changes that struct tm will be altered, any time in the next half billion years or so, seems very very slight to me. Which suggests that the right thing to do isn't to worry about localtime() sometimes returning NULL, but rather handle it better in zdump(), and have it perhaps print "some time so long ago we cannot represent it" (or similar, and with a similar message for big positive times). kre
On 2013-01-31 at 14:20 +0700, Robert Elz wrote:
Given that, the changes that struct tm will be altered, any time in the next half billion years or so, seems very very slight to me. Which suggests that the right thing to do isn't to worry about localtime() sometimes returning NULL, but rather handle it better in zdump(), and have it perhaps print "some time so long ago we cannot represent it" (or similar, and with a similar message for big positive times).
Or, change the specification for zdump, since anything relying on the currently specified behaviour is already broken? """ For this purposes of this dump, the lowest and highest possible time values will be bound by time_t if time_t is 32-bit. If time_t is 64-bit or float, then they will be bound by the representable values of the type of tm_year in a struct tm. """ If nothing else, after people stop laughing at the years, it might nudge people to think about the Y10K problem and how they parse years. ;) Who knows, 2% of all date-handling code out there might become more robust. -Phil
participants (5)
-
Arthur David Olson -
Marvel, Jim (CPCOE) -
Paul Eggert -
Phil Pennock -
Robert Elz