This is the mail archive of the libc-hacker@sourceware.cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: A revised time patch (fwd)


I am not sure if this was sent out or not. Sorry if you got it twice.

-- 
H.J. Lu (hjl@gnu.org)
> 
> hjl@lucon.org (H.J. Lu) writes:
> 
> > Fri Oct 30 17:48:48 1998  H.J. Lu  <hjl@gnu.org>
> > 
> > 	* time/mktime.c (__mktime_internal): Handle the case where
> > 	tm_isdst is different from __daylight != 0 correctly.
> > 
> > 	* time/tzfile (__tzfile_read): Set __daylight to the difference
> > 	between DST and STD.
> > 	(__tzfile_compute): Likewise.
> > 	* time/tzset.c (tz_compute): Likewise.
> 
> Can you please give me examples of this as well?
> 

Here is the testcase. My previous patch to time/mktime.c is incomplete.
Please use this one. BTW, __mktime_internal mishandles the cases
where tm_isdst is different from __daylight != 0. Basically when 
tm_isdst == 0/__daylight != 0 and tm_isdst == 1/__daylight == 0, we 
should check

dt == __daylight * ((isdst != 0) - (tm.tm_isdst != 0))

instead of dt == 0.

Thanks.


H.J.
-----
Index: mktime.c
===================================================================
RCS file: /home/work/cvs/gnu/glibc/time/mktime.c,v
retrieving revision 1.1.1.13
diff -u -p -r1.1.1.13 mktime.c
--- mktime.c	1998/10/17 02:11:00	1.1.1.13
+++ mktime.c	1998/11/02 03:49:28
@@ -334,10 +334,13 @@ __mktime_internal (tp, convert, offset)
        (dt = ydhms_tm_diff (year, yday, hour, min, sec,
 			    ranged_convert (convert, &t, &tm)));
        t1 = t2, t2 = t, t += dt)
-    if (t == t1 && t != t2
-	&& (isdst < 0 || tm.tm_isdst < 0
-	    || (isdst != 0) != (tm.tm_isdst != 0)))
-      /* We can't possibly find a match, as we are oscillating
+    if ((0 <= isdst && 0 <= tm.tm_isdst
+	 && dt == __daylight * ((isdst != 0) - (tm.tm_isdst != 0)))
+	|| (t == t1 && t != t2
+	    && (isdst < 0 || tm.tm_isdst < 0
+		|| (isdst != 0) != (tm.tm_isdst != 0))))
+      /* We find a match due to difference between STD and DST. Or
+	 we can't possibly find a match, as we are oscillating
 	 between two values.  The requested time probably falls
 	 within a spring-forward gap of size DT.  Follow the common
 	 practice in this case, which is to return a time that is DT
@@ -352,19 +355,20 @@ __mktime_internal (tp, convert, offset)
      value, if any.  */
   if (dt == 0 && 0 <= isdst && 0 <= tm.tm_isdst)
     {
-      int dst_diff = (isdst != 0) - (tm.tm_isdst != 0);
+      int dst_diff = ((isdst != 0) - (tm.tm_isdst != 0)) * __daylight;
       if (dst_diff)
 	{
-	  /* Move two hours in the direction indicated by the disagreement,
-	     probe some more, and switch to a new time if found.
-	     The largest known fallback due to daylight savings is two hours:
-	     once, in Newfoundland, 1988-10-30 02:00 -> 00:00.  */
-	  time_t ot = t - 2 * 60 * 60 * dst_diff;
+	  /* Move __daylight seconds in the direction indicated by the
+	     disagreement, probe some more, and switch to a new time
+	     if found. The fallback due to daylight savings is stored
+	     in __daylight.  */
+	  time_t ot = t - dst_diff;
 	  while (--remaining_probes != 0)
 	    {
 	      struct tm otm;
-	      if (! (dt = ydhms_tm_diff (year, yday, hour, min, sec,
-					 ranged_convert (convert, &ot, &otm))))
+	      dt = ydhms_tm_diff (year, yday, hour, min, sec,
+				  ranged_convert (convert, &ot, &otm));
+	      if (dt == dst_diff)
 		{
 		  t = ot;
 		  tm = otm;
-----
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>

static
int
test (struct tm *xp, time_t expected)
{
  time_t t;

  t = mktime (xp);
  printf ("min: %d\n", xp->tm_min);
  printf ("hour: %d\n", xp->tm_hour);
  printf ("isdst: %d\n", xp->tm_isdst);
  printf ("%u\n", t);
  printf ("%s", ctime (&t));
  if (t != expected)
    return -1;
  else
    return 0;
}

static
int
set_tz(char *tzval)
{
  char *tz;
  static char buf[256];

  strcpy(buf, "TZ=");
  strcat(buf, tzval);
  putenv(buf);
  tz = getenv("TZ");
  if (tz == NULL || strcmp(tz, tzval) != 0)
    return -1;
  else
    return 0;
}

main (int argc, char **argv)
{
  struct tm x;
  time_t expected;
  int failed = 0;

  if (set_tz ("GMT0BST,J81,J300"))
    {
      printf ("Failed to set TZ to GMT0BST,J81,J300\n");
      return 1;
    }

  x.tm_sec = 59;
  x.tm_min = 59;
  x.tm_hour = 0;
  x.tm_mday = 27;
  x.tm_mon = 9;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 0;
  expected = 593917199;

  if (test (&x, expected))
    {
      printf ("mktime failed test 1\n");
      failed++;
    }

  x.tm_sec = 21;
  x.tm_min = 0;
  x.tm_hour = 2;
  x.tm_mday = 27;
  x.tm_mon = 9;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 1;
  expected = 593917221;

  if (test (&x, expected))
    {
      printf ("mktime failed test 2\n");
      failed++;
    }

  x.tm_sec = 21;
  x.tm_min = 0;
  x.tm_hour = 2;
  x.tm_mday = 22;
  x.tm_mon = 2;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 0;
  expected = 574999221;

  if (test (&x, expected))
    {
      printf ("mktime failed test 3\n");
      failed++;
    }

  if (set_tz ("GMT0BST-2,J81,J300"))
    {
      printf ("Failed to set TZ to GMT0BST,J81,J300\n");
      return 1;
    }

  x.tm_sec = 59;
  x.tm_min = 59;
  x.tm_hour = 23;
  x.tm_mday = 26;
  x.tm_mon = 9;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 0;
  expected = 593913599;

  if (test (&x, expected))
    {
      printf ("mktime failed test 4\n");
      failed++;
    }

  x.tm_sec = 21;
  x.tm_min = 0;
  x.tm_hour = 2;
  x.tm_mday = 22;
  x.tm_mon = 2;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 0;
  expected = 574999221;

  if (test (&x, expected))
    {
      printf ("mktime failed test 5\n");
      failed++;
    }

  x.tm_sec = 21;
  x.tm_min = 0;
  x.tm_hour = 2;
  x.tm_mday = 27;
  x.tm_mon = 9;
  x.tm_year = 88;
  x.tm_wday = -1;
  x.tm_yday = -1;
  x.tm_isdst = 1;
  expected = 593913621;

  if (test (&x, expected))
    {
      printf ("mktime failed test 6\n");
      failed++;
    }

  return failed;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]