mktime() failure vs 31-DEC-1969 23:59:59 GMT

Paul Eggert eggert at twinsun.com
Mon Feb 19 23:33:56 UTC 1996


   From: tomp at zk3.dec.com
   Date: Mon, 19 Feb 96 11:18:47 -0500

   Is it a requirement (standards, etc) that localtime() work as an inverse
   of mktime().

As far as I know, neither Posix nor the C Standard requires that
mktime be the inverse of localtime; but the standards are so loose
that mere conformance to the standard allows lots of bizarre behaviors
that any reasonable person would call a bug.

For example, as far as I can tell, neither standard requires that
mktime work on times in the next millenium.  The same loopholes that
allow mktime implementations to mishandle times before the Epoch, also
allow them to mishandle times after the Epoch.

When filing bug reports against standards as loose as these,
we must appeal to common sense as well as to the letter of the standards;
otherwise we'll never make any progress.

   > Solaris 2.5 has other problems in this area; see Sun bug 1229958
   > (``ctime, localtime functions slow and incorrect'').

   Where can this be found?

At http://sunsolve1.sun.com, but that report is not publicly available
unless you have a Sun support contract.  However, I sent the following
info to Sun about that bug; this might might give you a flavor of the
report.  I don't think the bug is fixed in Solaris 2.5.

	SunOS 4.1.4 ctime runs 6 times faster than the Solaris 2.4
	version on my Sparc ELCs.  Perhaps you could replace the
	Solaris version of the time code with the SunOS 4.1.4 version.
	This will fix the bug, and also give much better performance.

	Or you could substitute the public domain time code (see
	<ftp://elsie.nci.nih.gov/pub/tzcode95d.tar.gz>); it's also
	much faster than the Solaris 2.4 code, and it doesn't have the
	bug....

	Here is another test program to illustrate the bug:

	#include <limits.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <time.h>

	#define	TIME_T_MIN LONG_MIN
	#define	TIME_T_MAX LONG_MAX

	char *zones_to_try[] = {"US/Pacific", "GMT0", "Hongkong"};
	time_t times_to_try[] =	{
	  TIME_T_MIN, TIME_T_MIN + 8*60*60,
	  TIME_T_MIN / 2,
	  0,
	  TIME_T_MAX / 2,
	  TIME_T_MAX - 8*60*60,	TIME_T_MAX
	};

	int main()
	{
	  int i, j;
	  for (i = 0; i	< sizeof (zones_to_try)	/ sizeof (*zones_to_try); i++) {
	    char buf[100];
	    sprintf (buf, "TZ=%s", zones_to_try[i]);
	    putenv (buf);
	    tzset ();
	    for	(j = 0;	j < sizeof (times_to_try) / sizeof (*times_to_try); j++) {
	      printf ("%8lx\t%.24s\t%s\n",
		      times_to_try[j],
		      ctime (&times_to_try[j]),
		      zones_to_try[i]);
	    }
	  }
	  return 0;
	}

Under Solaris 2.4 this program outputs the following lines.
The lines marked `*' are incorrect.

	80000000	Mon Jan	18 20:14:08 2038	US/Pacific *
	80007080	Fri Dec	13 21:45:52 1901	US/Pacific *
	c0000000	Mon Dec	23 02:22:56 1935	US/Pacific
	       0	Wed Dec	31 16:00:00 1969	US/Pacific
	3fffffff	Sat Jan	10 05:37:03 2004	US/Pacific
	7fff8f7f	Mon Jan	18 11:14:07 2038	US/Pacific
	7fffffff	Mon Jan	18 19:14:07 2038	US/Pacific
	80000000	Fri Dec	13 20:45:52 1901	GMT0
	80007080	Sat Dec	14 04:45:52 1901	GMT0
	c0000000	Mon Dec	23 10:22:56 1935	GMT0
	       0	Thu Jan	 1 00:00:00 1970	GMT0
	3fffffff	Sat Jan	10 13:37:03 2004	GMT0
	7fff8f7f	Mon Jan	18 19:14:07 2038	GMT0
	7fffffff	Tue Jan	19 03:14:07 2038	GMT0
	80000000	Sat Dec	14 04:22:28 1901	Hongkong *
	80007080	Sat Dec	14 12:22:28 1901	Hongkong *
	c0000000	Mon Dec	23 18:22:56 1935	Hongkong
	       0	Thu Jan	 1 08:00:00 1970	Hongkong
	3fffffff	Sat Jan	10 21:37:03 2004	Hongkong
	7fff8f7f	Tue Jan	19 03:14:07 2038	Hongkong
	7fffffff	Sat Dec	14 04:45:51 1901	Hongkong *

The starred lines should read as follows, respectively:

	80000000	Fri Dec	13 12:45:52 1901	US/Pacific
	80007080	Fri Dec	13 20:45:52 1901	US/Pacific

	80000000	Sat Dec	14 04:45:52 1901	Hongkong
	80007080	Sat Dec	14 12:45:52 1901	Hongkong

	7fffffff	Tue Jan	19 11:14:07 2038	Hongkong



More information about the tz mailing list