FW: tz interface problems
eggert at twinsun.com
Fri May 22 01:55:29 UTC 1998
From: D. J. Bernstein[SMTP:djb at cr.yp.to]
Sent: Monday, May 18, 1998 3:32 AM
1. Check out the dates produced by sendmail on one host:
Mon, 18 May 1998 16:36:37 +0930
Mon, 18 May 1998 16:36:38 +0930
Mon, 18 May 1998 16:36:39 +0929
Mon, 18 May 1998 16:36:40 +0929
The problem, of course, is that sendmail is figuring out the offset by
comparing the hours and minutes shown by localtime() and gmtime().
That method should be reliable, so long as you pass the same timestamp
to both localtime and gmtime. Can you give more details about the problem?
Do you have a routine that, given a time, returns the offset?
There's not one in the tz packages, but one is commonly included in GNU code.
I'll enclose a copy at the end of this message. Of course the Right Way
to do it is to use tm_gmtoff, but this isn't blessed by the standards.
How difficult would it be for you to get leap-second data from another
With the tz code, the leapsecond data is already gotten from a
separate file called `leapseconds'.
Or do you mean distribute the leapsecond data in a separate file,
as opposed to having people untar it?
That shouldn't be hard to arrange -- ado would know for sure.
But first I'd like to make sure that this is what you want.
Anyway, here's the offset-returning routine.
/* This code is derived from FSF copyrighted code, so the GPL applies. */
#define div(a, b) ((a) / (b) - ((a) % (b) < 0))
#define TM_YEAR_ORIGIN 1900
/* Yield A - B, measured in seconds. */
difftm (a, b)
struct tm const *a;
struct tm const *b;
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
int ac = div (ay, 100);
int bc = div (by, 100);
int difference_in_day_of_year = a->tm_yday - b->tm_yday;
int intervening_leap_days = (((ay >> 2) - (by >> 2))
- (ac - bc)
+ ((ac >> 2) - (bc >> 2)));
time_t difference_in_years = ay - by;
= (difference_in_years * 365
+ (intervening_leap_days + difference_in_day_of_year));
return (((((difference_in_days * 24
+ (a->tm_hour - b->tm_hour))
+ (a->tm_min - b->tm_min))
+ (a->tm_sec - b->tm_sec));
/* Yield the number of seconds that local time is ahead of GMT at
time T, or 0 if this is not known. */
struct tm gmt, *gmtp, *ltp;
if (! (gmtp = gmtime (&t)))
gmt = *gmtp;
if (! (ltp = localtime (&t)))
return difftm (ltp, &gmt);
More information about the tz