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

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix TZ env var handling


Hi!

Setting
TZ=AST-10ADT,M10.5.0/2,M3.5.0/3
results in all dates before 5th Sunday in October to use standard time,
while only those between 5th Sunday in March and 5th Sunday in October
should be standard time, the rest dst.
Details in http://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=60747
The problem is that tz_compute computes tz_rules[1].change in the next year,
so when __tz_convert actually compares the times, it thinks all times until
tz_rules[0].change are not daylight saving.
This patch should speed things up, because with the next year compute_change
we were never caching tz_rules[1].change (well, for southern hemisphere).
Also, I have noticed that compute_change never returns anything but 1 (and
likewise tz_compute), so I don't see why the return value should be ever
checked.

2002-03-06  Jakub Jelinek  <jakub@redhat.com>

	* time/tzset.c (compute_change): Don't return any value.
	(tz_compute): Likewise.  Don't handle southern hemisphere here.
	(__tz_convert): But here.

--- libc/time/tzset.c.jj	Thu Aug 23 18:51:42 2001
+++ libc/time/tzset.c	Wed Mar  6 16:56:32 2002
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1991-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -69,8 +69,8 @@ typedef struct
 static tz_rule tz_rules[2];
 
 
-static int compute_change __P ((tz_rule *rule, int year)) internal_function;
-static int tz_compute __P ((const struct tm *tm))
+static void compute_change __P ((tz_rule *rule, int year)) internal_function;
+static void tz_compute __P ((const struct tm *tm))
      internal_function;
 static void tzset_internal __P ((int always)) internal_function;
 
@@ -410,9 +410,8 @@ __tzname_max ()
 
 /* Figure out the exact time (as a time_t) in YEAR
    when the change described by RULE will occur and
-   put it in RULE->change, saving YEAR in RULE->computed_for.
-   Return nonzero if successful, zero on failure.  */
-static int
+   put it in RULE->change, saving YEAR in RULE->computed_for.  */
+static void
 internal_function
 compute_change (rule, year)
      tz_rule *rule;
@@ -422,7 +421,7 @@ compute_change (rule, year)
 
   if (year != -1 && rule->computed_for == year)
     /* Operations on times in 2 BC will be slower.  Oh well.  */
-    return 1;
+    return;
 
   /* First set T to January 1st, 0:00:00 GMT in YEAR.  */
   if (year > 1970)
@@ -498,28 +497,18 @@ compute_change (rule, year)
 
   rule->change = t - rule->offset + rule->secs;
   rule->computed_for = year;
-  return 1;
 }
 
 
 /* Figure out the correct timezone for TM and set `__tzname',
-   `__timezone', and `__daylight' accordingly.  Return nonzero on
-   success, zero on failure.  */
-static int
+   `__timezone', and `__daylight' accordingly.  */
+static void
 internal_function
 tz_compute (tm)
      const struct tm *tm;
 {
-  if (! compute_change (&tz_rules[0], 1900 + tm->tm_year)
-      || ! compute_change (&tz_rules[1], 1900 + tm->tm_year))
-    return 0;
-  /* We have to distinguish between northern and southern hemisphere.
-     For the latter the daylight saving time ends in the next year.
-     It is easier to detect this after first computing the time for the
-     wrong year since now we simply can compare the times to switch.  */
-  if (tz_rules[0].change > tz_rules[1].change
-      && ! compute_change (&tz_rules[1], 1900 + tm->tm_year + 1))
-    return 0;
+  compute_change (&tz_rules[0], 1900 + tm->tm_year);
+  compute_change (&tz_rules[1], 1900 + tm->tm_year);
 
   __daylight = tz_rules[0].offset != tz_rules[1].offset;
   __timezone = -tz_rules[0].offset;
@@ -535,8 +524,6 @@ tz_compute (tm)
     if (len1 > __tzname_cur_max)
       __tzname_cur_max = len1;
   }
-
-  return 1;
 }
 
 /* Reinterpret the TZ environment variable and set `tzname'.  */
@@ -590,8 +577,10 @@ __tz_convert (const time_t *timer, int u
     }
   else
     {
-      if (! (__offtime (timer, 0, tp) && tz_compute (tp)))
+      if (! __offtime (timer, 0, tp))
 	tp = NULL;
+      else
+	tz_compute (tp);
       leap_correction = 0L;
       leap_extra_secs = 0;
     }
@@ -602,8 +591,18 @@ __tz_convert (const time_t *timer, int u
 	{
 	  if (!__use_tzfile)
 	    {
-	      int isdst = (*timer >= tz_rules[0].change
-			   && *timer < tz_rules[1].change);
+	      int isdst;
+
+	      /* We have to distinguish between northern and southern
+		 hemisphere.  For the latter the daylight saving time
+		 ends in the next year.  */
+	      if (__builtin_expect (tz_rules[0].change
+				    > tz_rules[1].change, 0))
+		isdst = (*timer < tz_rules[1].change
+			 || *timer >= tz_rules[0].change);
+	      else
+		isdst = (*timer >= tz_rules[0].change
+			 && *timer < tz_rules[1].change);
 	      tp->tm_isdst = isdst;
 	      tp->tm_zone = __tzname[isdst];
 	      tp->tm_gmtoff = tz_rules[isdst].offset;


	Jakub


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