This is the mail archive of the
libc-hacker@sourceware.cygnus.com
mailing list for the glibc project.
Re: A revised time patch (fwd)
- To: libc-hacker@cygnus.com (GNU C Library)
- Subject: Re: A revised time patch (fwd)
- From: hjl@lucon.org (H.J. Lu)
- Date: Mon, 2 Nov 1998 07:44:15 -0800 (PST)
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;
}