Re: [LEAPSECS] Mechanism to provide tai-utc.dat locally

From: Keith Winstein <keithw_at_MIT.EDU>
Date: Mon, 25 Dec 2006 15:42:12 -0500 (EST)

On Mon, 25 Dec 2006, M. Warner Losh wrote:

> In message: <Pine.LNX.4.62L.0612250202060.30384_at_vinegar-pot.mit.edu>
> Keith Winstein <keithw_at_MIT.EDU> writes:
> : If your users have an up-to-date GNU libc, they can get the value of
> : TAI-UTC at any point since 1970 using C library functions. Here's a sample
> : C program that shows how to do it.
>
> The problem with this approach is that it fails to work for long
> running programs that need to know about leapseconds. The zonefiles
> aren't re-read when they change,

This can be forced by calling tzset(). Here's a routine that exhibits the
desired behavior -- if you call it repeatedly within a long-running
process and then change the contents of zoneinfo/right/UTC (e.g., by
copying posix/UTC on top of it to erase all the leap seconds), the routine
changes its output as expected.

> and even if they were, updating the zonefiles to keep them up to date
> presents some interesting challanges.

Well, I agree. Changing the contents of a zoneinfo file precisely while
another process is reading it might give some sort of invalid or erronious
result. And GNU libc / tzdata is a pretty heavyweight way of distributing
leap-second updates (and it takes a while to be updated, and plenty of
systems don't use GNU libc).

Also, all of these mechanisms (whether there's a table in a file, or in
DNS, or in the zoneinfo database) still only answer part of the problem.
Even if a program is able to calculate TAI-UTC for arbitrary points in the
past and near future, what should a library do when a program asks to
convert between UTC and TAI for some instant further than six months in
the future?

   - Signal an exception?
   - Assume there will be no future leap seconds and return that answer,
     even though the same "function" may give a different answer when
     called later with the same arguments?
   - Somehow try to encapsulate the uncertainty by returning a union of
     possible results (bounded on the low end by the "no-future-leapseconds"
     answer and, on the high end, by the "leapsec-every-six-months," or
     "every-three-months," or "every-month" answer)?

Anyway, here is the routine that updates when zoneinfo files are changed
on disk, even during a long-running process:

=====
double taiutc( time_t unix_time )
{
   time_t elapsed_time;
   struct tm my_tm;
   char *tz;
   char old_tz[ 128 ];
   double taiutc;

   /* Save timezone. N.B. this is not thread-safe */
   tz = getenv( "TZ" );
   old_tz[ 127 ] = '\0';
   if ( tz ) strncpy( old_tz, tz, 127 );

   /* Do calculation -- elapsed time minus unix time = # leapsecs since '70 */
   setenv( "TZ", "posix/UTC", 1 ); tzset();
   localtime_r( &unix_time, &my_tm );
   setenv( "TZ", "right/UTC", 1 ); tzset();
   elapsed_time = mktime( &my_tm );
   taiutc = 10 + difftime( elapsed_time, unix_time );

   /* Restore timezone */
   if ( tz ) setenv( "TZ", old_tz, 1 );
   else unsetenv( "TZ" );
   tzset();

   return taiutc;
}
=====

Cheers,
Keith
Received on Mon Dec 25 2006 - 12:42:37 PST

This archive was generated by hypermail 2.3.0 : Sat Sep 04 2010 - 09:44:55 PDT