A patch for mktime.c and tz*.c.
H.J. Lu
hjl@lucon.org
Fri Nov 6 11:10:00 GMT 1998
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;
More information about the Libc-hacker
mailing list