Thread: AW: AW: Re: tinterval - operator problems on AIX
> > On AIX mktime(3) leaves tm_isdst at -1 if it does not have timezone > > info for that particular year and returns -1. > > The following code then makes savings time out of the -1. > > tz = (tm->tm_isdst ? (timezone - 3600) : timezone); > > Hmm. That description is consistant with what I see in the Linux man > page. So I should check for (tm->tm_isdst > 0) rather than > checking for non-zero? It is obviously not possible to determine tm_isdst with mktime for a negative time_t. Thus with above fix PST works, but PDT is then busted :-( localtime does convert a negative time_t correctly including dst. Is there another way to determine tm_isdst ? Andreas
> > > On AIX mktime(3) leaves tm_isdst at -1 if it does not have timezone > > > info for that particular year and returns -1. > > > The following code then makes savings time out of the -1. > > > tz = (tm->tm_isdst ? (timezone - 3600) : timezone); > > Hmm. That description is consistant with what I see in the Linux man > > page. So I should check for (tm->tm_isdst > 0) rather than > > checking for non-zero? > It is obviously not possible to determine tm_isdst with mktime for a > negative time_t. Thus with above fix PST works, but PDT is then busted :-( Obvious to AIX only? My conclusion is that the AIX timezone database is damaged or missing for pre-1970 dates, but that other systems bothered to get it at least somewhat right. Is there another issue here that I'm missing? > localtime does convert a negative time_t correctly including dst. > Is there another way to determine tm_isdst ? Yes. Replace AIX with Linux or something else, then recompile Postgres ;) Seriously, not that I know of. The problem is that there is no API for accessing time zone info other than the localtime()/mktime() kinds of calls, so we are stuck using that (or stuck repackaging something like zinc into Postgres directly, which afaik is not anything we would be interested in doing). - Thomas
Zeugswetter Andreas SB writes:> Try the attachment with negative values, and tell us whether mktime> returns anything otherthat -1. Do you have an idea how else we> could determine daylight savings time ? mktime always returns -1 for tm's that might expect to return a negative number. In those cases the tm is not normalized and tm_isdst is set to -1. When mktime returns zero or positive then tm is normalized and tm_isdst is set to 0 or 1. localtime sets all the fields of tm correctly, including tm_isdst, for all values of time_t, including negative ones. When I say correctly, there is the usual limitation that the rules to specify when DST is in force cannot express a variation from year to year. (You can specify e.g. the last Sunday in a month.) My observations were consistent across AIX 4.1.5, 4.2.1, and 4.3.3. If you have a time_t, then you can use localtime to determine DST. If you have a tm then you cannot work out DST for dates before the epoch. One workaround would be to add 4*n to tm_year and subtract (365*4+1) *24*60*60*n from the time_t returned. (All leap years are multiples of 4 in the range 1901 to 2038. If tm_wday is wanted, that will need to be adjusted as well.) But don't you do time interval arithmetic using PostgreSQL date types rather than accepting the limitations of POSIX/UNIX? -- Pete Forman -./\.- Disclaimer: This post is originated WesternGeco -./\.- by myself and does not represent pete.forman@westerngeco.com -./\.- opinion of Schlumberger, Baker http://www.crosswinds.net/~petef -./\.- Hughes or their divisions.
Pete Forman writes:> One workaround would be to add 4*n to tm_year and subtract (365*4+1)> *24*60*60*n from the time_t returned. (All leap years are multiples> of 4 in the range 1901 to 2038. If tm_wday is wanted, that will need> to be adjustedas well.) FWIW, that should be to add 28*n to tm_year and subtract (365*4+1)*7 *24*60*60*n from the time_t returned. That calculates tm_wday correctly. Also I should have been more explicit that this applies only to AIX and IRIX. Those return -1 from mktime(year < 1970) and do not allow DST rules to vary from year to year. Linux and Solaris have more capable date libraries. -- Pete Forman http://www.bedford.waii.com/wsdev/petef/PeteF_links.html WesternGeco http://www.crosswinds.net/~petef Manton Lane, Bedford, mailto:pete.forman@westerngeco.com MK41 7PA, UK tel:+44-1234-224798 fax:+44-1234-224804
> FWIW, that should be to add 28*n to tm_year and subtract (365*4+1)*7 > *24*60*60*n from the time_t returned. That calculates tm_wday > correctly. > Also I should have been more explicit that this applies only to AIX > and IRIX. Those return -1 from mktime(year < 1970) and do not allow > DST rules to vary from year to year. Linux and Solaris have more > capable date libraries. Oh, so AIX and IRIX have just one-line time zone databases? Yuck. How about having some #if BROKEN_TIMEZONE_DATABASE code which uses both mktime() and localtime() to derive the correct time zone? That is, call mktime to get a time_t, then call localtime() to get the time zone info, but only on platforms which do not get a complete result from just the call to mktime(). In fact, we *could* check for tm->tm_isdst coming back "-1" for every platform, then call localtime() to make a last stab at getting a good value. Comments? - Thomas