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]

A patch for mktime.c and tz*.c.


Hi,

Paul's change looks ok. But I still don't like guessing unless we
don't have a choice. For glibc 2, there is no need to guess with
my patch. I'd like to see a clean approach in glibc 2 and let other
packages guess. Here is a patch to do the right thing for glibc 2.

Thanks.


-- 
H.J. Lu (hjl@gnu.org)
---
Fri Nov  6 07:04:58 1998  H.J. Lu  <hjl@gnu.org>

	* time/mktime.c (__mktime_internal): For glibc 2, handle
	the case where tm_isdst is different from __daylight != 0
	using __daylight.

	* time/tzfile.c (__tzfile_read): Set __daylight to the
	difference between DST and STD.
	(__tzfile_compute): Likewise.
	* time/tzset.c (tz_compute): Likewise.

Index: time/mktime.c
===================================================================
RCS file: /home/work/cvs/gnu/glibc/time/mktime.c,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 mktime.c
--- mktime.c	1998/11/06 15:31:19	1.1.1.15
+++ mktime.c	1998/11/06 16:06:33
@@ -334,10 +334,19 @@ __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 defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
+    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))))
+#else
     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
+#endif
+      /* 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
@@ -351,7 +360,31 @@ __mktime_internal (tp, convert, offset)
   /* If we have a match, check whether tm.tm_isdst has the requested
      value, if any.  */
   if (dt == 0 && isdst != tm.tm_isdst && 0 <= isdst && 0 <= tm.tm_isdst)
+#if defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2
     {
+      /* 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.  */
+      int dst_diff = ((isdst != 0) - (tm.tm_isdst != 0)) * __daylight;
+      time_t ot = t - dst_diff;
+      while (--remaining_probes != 0)
+	{
+	  struct tm otm;
+	  dt = ydhms_tm_diff (year, yday, hour, min, sec,
+			      ranged_convert (convert, &ot, &otm));
+	  if (dt == dst_diff)
+	    {
+	      t = ot;
+	      tm = otm;
+	      break;
+	    }
+	  if ((ot += dt) == t)
+	    break;  /* Avoid a redundant probe.  */
+	}
+    }
+#else
+    {
       /* tm.tm_isdst has the wrong value.  Look for a neighboring
 	 time with the right value, and use its UTC offset.
 	 Heuristic: probe the previous three calendar quarters (approximately),
@@ -379,6 +412,7 @@ __mktime_internal (tp, convert, offset)
 	    }
 	}
     }
+#endif
 
   *offset = t - t0;
 
Index: time/tzfile.c
===================================================================
RCS file: /home/work/cvs/gnu/glibc/time/tzfile.c,v
retrieving revision 1.1.1.13
diff -u -p -r1.1.1.13 tzfile.c
--- tzfile.c	1998/10/26 15:33:26	1.1.1.13
+++ tzfile.c	1998/11/04 04:57:16
@@ -298,7 +298,7 @@ __tzfile_read (const char *file)
 	}
     }
 
-  __daylight = rule_stdoff != rule_dstoff;
+  __daylight = rule_dstoff - rule_stdoff;
   __timezone = -rule_stdoff;
 
   __use_tzfile = 1;
@@ -436,7 +436,7 @@ __tzfile_compute (time_t timer, int use_
   if (use_localtime)
     {
       struct ttinfo *info = find_transition (timer);
-      __daylight = rule_stdoff != rule_dstoff;
+      __daylight = rule_dstoff - rule_stdoff;
       __timezone = -rule_stdoff;
       __tzname[1] = NULL;
       for (i = 0; i < num_types; ++i)
Index: time/tzset.c
===================================================================
RCS file: /home/work/cvs/gnu/glibc/time/tzset.c,v
retrieving revision 1.1.1.17
diff -u -p -r1.1.1.17 tzset.c
--- tzset.c	1998/11/03 15:06:28	1.1.1.17
+++ tzset.c	1998/11/04 04:57:16
@@ -527,7 +527,7 @@ tz_compute (tm)
       && ! compute_change (&tz_rules[1], 1900 + tm->tm_year + 1))
     return 0;
 
-  __daylight = tz_rules[0].offset != tz_rules[1].offset;
+  __daylight = tz_rules[1].offset - tz_rules[0].offset;
   __timezone = -tz_rules[0].offset;
   __tzname[0] = (char *) tz_rules[0].name;
   __tzname[1] = (char *) tz_rules[1].name;


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