FW: tz interface problems

Paul Eggert 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
   file?

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,
e.g. ftp://elsie.nci.nih.gov/pub/leapseconds
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.  */

#include <time.h>

#define div(a, b) ((a) / (b) - ((a) % (b) < 0))
#define TM_YEAR_ORIGIN 1900

/* Yield A - B, measured in seconds.  */
time_t
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;
  time_t difference_in_days
    = (difference_in_years * 365
       + (intervening_leap_days + difference_in_day_of_year));
  return (((((difference_in_days * 24
	      + (a->tm_hour - b->tm_hour))
	     * 60)
	    + (a->tm_min - b->tm_min))
	   * 60)
	  + (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.  */
long
gmtoff (t)
     time_t t;
{
  struct tm gmt, *gmtp, *ltp;
  if (! (gmtp = gmtime (&t)))
    return 0;
  gmt = *gmtp;
  if (! (ltp = localtime (&t)))
    return 0;
  return difftm (ltp, &gmt);
}



More information about the tz mailing list