* include/time.h: Declare __tzset_parse_tz and __tzset_compute.

* time/tzset.c (tzset_internal): Break TZ string parsing out into
	__tzset_parse_tz and updating of daylight, timezone, tzname into
	update_vars.
	(__tz_compute): Renamed from tz_compute.  Take additional parameters.
	(__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now
	happens in __tz_compute.
	* time/tzfile.c (__tzfile_read): Also read TZ string.
	(find_transition): Fold into __tzfile_compute.
	(__tzfile_compute): For times beyond the last transition try to
	use the TZ string.
	* timezone/tst-timezone.c: Information in daylight and tzname does
	change for Asia/Tokyo timezone with more concrete information.
	Remove the test.

	* include/stdio.h: Add libc_hidden_proto for ftello.
	* libio/ftello.c: Add libc_hidden_def.
This commit is contained in:
Ulrich Drepper 2007-10-14 09:15:45 +00:00
parent 89dc9d4c5b
commit fa76dde2cf
8 changed files with 325 additions and 260 deletions

View File

@ -1,5 +1,23 @@
2007-10-14 Ulrich Drepper <drepper@redhat.com> 2007-10-14 Ulrich Drepper <drepper@redhat.com>
* include/time.h: Declare __tzset_parse_tz and __tzset_compute.
* time/tzset.c (tzset_internal): Break TZ string parsing out into
__tzset_parse_tz and updating of daylight, timezone, tzname into
update_vars.
(__tz_compute): Renamed from tz_compute. Take additional parameters.
(__tz_convert): Updating of tm_isdst, tm_zone, and tm_gmtoff now
happens in __tz_compute.
* time/tzfile.c (__tzfile_read): Also read TZ string.
(find_transition): Fold into __tzfile_compute.
(__tzfile_compute): For times beyond the last transition try to
use the TZ string.
* timezone/tst-timezone.c: Information in daylight and tzname does
change for Asia/Tokyo timezone with more concrete information.
Remove the test.
* include/stdio.h: Add libc_hidden_proto for ftello.
* libio/ftello.c: Add libc_hidden_def.
[BZ #1140] [BZ #1140]
* time/tzfile.c (__tzfile_compute): Compute tzname[] values based * time/tzfile.c (__tzfile_compute): Compute tzname[] values based
on the specified time and not the last entries in the file. Move on the specified time and not the last entries in the file. Move

View File

@ -138,6 +138,7 @@ libc_hidden_proto (rewind)
libc_hidden_proto (fileno) libc_hidden_proto (fileno)
libc_hidden_proto (fwrite) libc_hidden_proto (fwrite)
libc_hidden_proto (fseek) libc_hidden_proto (fseek)
libc_hidden_proto (ftello)
libc_hidden_proto (fflush_unlocked) libc_hidden_proto (fflush_unlocked)
libc_hidden_proto (fread_unlocked) libc_hidden_proto (fread_unlocked)
libc_hidden_proto (fwrite_unlocked) libc_hidden_proto (fwrite_unlocked)

View File

@ -46,6 +46,9 @@ extern void __tzfile_compute (time_t timer, int use_localtime,
struct tm *tp); struct tm *tp);
extern void __tzfile_default (const char *std, const char *dst, extern void __tzfile_default (const char *std, const char *dst,
long int stdoff, long int dstoff); long int stdoff, long int dstoff);
extern void __tzset_parse_tz (const char *tz);
extern void __tz_compute (time_t timer, struct tm *tm, int use_localtime)
__THROW internal_function;
/* Subroutine of `mktime'. Return the `time_t' representation of TP and /* Subroutine of `mktime'. Return the `time_t' representation of TP and
normalize TP, given that a `struct tm *' maps to a `time_t' as performed normalize TP, given that a `struct tm *' maps to a `time_t' as performed

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004 /* Copyright (C) 1993, 1995-2001, 2002, 2003, 2004, 2007
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
@ -63,3 +63,4 @@ ftello (fp)
} }
return pos; return pos;
} }
libc_hidden_def (ftello)

View File

@ -264,9 +264,9 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
retval = 0; retval = 0;
/* If there are no group members TOTAL_LEN is zero. */ /* If there are no group members TOTAL_LEN is zero. */
if (total_len > 0) if (gr_name == NULL)
{ {
if (gr_name == NULL) if (total_len > 0)
{ {
size_t n = __readall (sock, resultbuf->gr_mem[0], total_len); size_t n = __readall (sock, resultbuf->gr_mem[0], total_len);
if (__builtin_expect (n != total_len, 0)) if (__builtin_expect (n != total_len, 0))
@ -278,26 +278,26 @@ nscd_getgr_r (const char *key, size_t keylen, request_type type,
else else
*result = resultbuf; *result = resultbuf;
} }
else }
else
{
/* Copy the group member names. */
memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len);
/* Try to detect corrupt databases. */
if (resultbuf->gr_name[gr_name_len - 1] != '\0'
|| resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
|| ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
break;
cnt < gr_resp.gr_mem_cnt; }))
{ {
/* Copy the group member names. */ /* We cannot use the database. */
memcpy (resultbuf->gr_mem[0], gr_name + gr_name_len, total_len); retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
goto out_close;
/* Try to detect corrupt databases. */
if (resultbuf->gr_name[gr_name_len - 1] != '\0'
|| resultbuf->gr_passwd[gr_resp.gr_passwd_len - 1] != '\0'
|| ({for (cnt = 0; cnt < gr_resp.gr_mem_cnt; ++cnt)
if (resultbuf->gr_mem[cnt][len[cnt] - 1] != '\0')
break;
cnt < gr_resp.gr_mem_cnt; }))
{
/* We cannot use the database. */
retval = mapped->head->gc_cycle != gc_cycle ? -2 : -1;
goto out_close;
}
*result = resultbuf;
} }
*result = resultbuf;
} }
} }
else else

View File

@ -62,6 +62,7 @@ static long int rule_stdoff;
static long int rule_dstoff; static long int rule_dstoff;
static size_t num_leaps; static size_t num_leaps;
static struct leap *leaps; static struct leap *leaps;
static char *tzspec;
#include <endian.h> #include <endian.h>
#include <byteswap.h> #include <byteswap.h>
@ -113,6 +114,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
size_t leaps_idx; size_t leaps_idx;
int was_using_tzfile = __use_tzfile; int was_using_tzfile = __use_tzfile;
int trans_width = 4; int trans_width = 4;
size_t tzspec_len;
if (sizeof (time_t) != 4 && sizeof (time_t) != 8) if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
abort (); abort ();
@ -241,10 +243,18 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
& ~(__alignof__ (struct leap) - 1)); & ~(__alignof__ (struct leap) - 1));
leaps_idx = total_size; leaps_idx = total_size;
total_size += num_leaps * sizeof (struct leap); total_size += num_leaps * sizeof (struct leap);
tzspec_len = (trans_width == 8
? st.st_size - (ftello (f)
+ num_transitions * (8 + 1)
+ num_types * 6
+ chars
+ num_leaps * 8
+ num_isstd
+ num_isgmt) - 1 : 0);
/* Allocate enough memory including the extra block requested by the /* Allocate enough memory including the extra block requested by the
caller. */ caller. */
transitions = (time_t *) malloc (total_size + extra); transitions = (time_t *) malloc (total_size + tzspec_len + extra);
if (transitions == NULL) if (transitions == NULL)
goto lose; goto lose;
@ -253,6 +263,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
types = (struct ttinfo *) ((char *) transitions + types_idx); types = (struct ttinfo *) ((char *) transitions + types_idx);
zone_names = (char *) types + num_types * sizeof (struct ttinfo); zone_names = (char *) types + num_types * sizeof (struct ttinfo);
leaps = (struct leap *) ((char *) transitions + leaps_idx); leaps = (struct leap *) ((char *) transitions + leaps_idx);
if (trans_width == 8)
tzspec = (char *) leaps + num_leaps * sizeof (struct leap);
else
tzspec = NULL;
if (extra > 0) if (extra > 0)
*extrap = (char *) &leaps[num_leaps]; *extrap = (char *) &leaps[num_leaps];
@ -356,11 +370,16 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
while (i < num_types) while (i < num_types)
types[i++].isgmt = 0; types[i++].isgmt = 0;
/* XXX When a version 2 file is available it can contain a POSIX TZ-style /* Read the POSIX TZ-style information if possible. */
formatted string which specifies how times past the last one specified if (tzspec != NULL)
are supposed to be handled. We might want to handle this at some {
point. But it might be overhead since most/all? files have an /* Skip over the newline first. */
open-ended last entry. */ if (getc_unlocked (f) != '\n'
|| fread_unlocked (tzspec, 1, tzspec_len - 1, f) != tzspec_len - 1)
tzspec = NULL;
else
tzspec[tzspec_len - 1] = '\0';
}
fclose (f); fclose (f);
@ -530,128 +549,6 @@ __tzfile_default (const char *std, const char *dst,
compute_tzname_max (stdlen + dstlen); compute_tzname_max (stdlen + dstlen);
} }
static struct ttinfo *
internal_function
find_transition (time_t timer)
{
size_t i;
__tzname[0] = NULL;
__tzname[1] = NULL;
if (num_transitions == 0 || timer < transitions[0])
{
/* TIMER is before any transition (or there are no transitions).
Choose the first non-DST type
(or the first if they're all DST types). */
i = 0;
while (i < num_types && types[i].isdst)
{
if (__tzname[1] == NULL)
__tzname[1] = __tzstring (&zone_names[types[i].idx]);
++i;
}
if (i == num_types)
i = 0;
__tzname[0] = __tzstring (&zone_names[types[i].idx]);
if (__tzname[1] == NULL)
{
size_t j = i;
while (j < num_types)
if (types[j].isdst)
{
__tzname[1] = __tzstring (&zone_names[types[j].idx]);
break;
}
else
++j;
}
}
else if (timer >= transitions[num_transitions - 1])
{
i = num_transitions - 1;
goto found;
}
else
{
/* Find the first transition after TIMER, and
then pick the type of the transition before it. */
size_t lo = 0;
size_t hi = num_transitions - 1;
/* Assume that DST is changing twice a year and guess initial
search spot from it.
Half of a gregorian year has on average 365.2425 * 86400 / 2
= 15778476 seconds. */
i = (transitions[num_transitions - 1] - timer) / 15778476;
if (i < num_transitions)
{
i = num_transitions - 1 - i;
if (timer < transitions[i])
{
if (i < 10 || timer >= transitions[i - 10])
{
/* Linear search. */
while (timer < transitions[i - 1])
--i;
goto found;
}
hi = i - 10;
}
else
{
if (i + 10 >= num_transitions || timer < transitions[i + 10])
{
/* Linear search. */
while (timer >= transitions[i])
++i;
goto found;
}
lo = i + 10;
}
}
/* Binary search. */
/* assert (timer >= transitions[lo] && timer < transitions[hi]); */
while (lo + 1 < hi)
{
i = (lo + hi) / 2;
if (timer < transitions[i])
hi = i;
else
lo = i;
}
i = hi;
found:
/* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
__tzname[types[type_idxs[i - 1]].isdst]
= __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
size_t j = i;
while (j < num_transitions)
{
int type = type_idxs[j];
int dst = types[type].isdst;
int idx = types[type].idx;
if (__tzname[dst] == NULL)
{
__tzname[dst] = __tzstring (&zone_names[idx]);
if (__tzname[1 - dst] != NULL)
break;
}
++j;
}
i = type_idxs[i - 1];
}
return &types[i];
}
void void
__tzfile_compute (time_t timer, int use_localtime, __tzfile_compute (time_t timer, int use_localtime,
long int *leap_correct, int *leap_hit, long int *leap_correct, int *leap_hit,
@ -661,7 +558,139 @@ __tzfile_compute (time_t timer, int use_localtime,
if (use_localtime) if (use_localtime)
{ {
struct ttinfo *info = find_transition (timer); __tzname[0] = NULL;
__tzname[1] = NULL;
if (num_transitions == 0 || timer < transitions[0])
{
/* TIMER is before any transition (or there are no transitions).
Choose the first non-DST type
(or the first if they're all DST types). */
i = 0;
while (i < num_types && types[i].isdst)
{
if (__tzname[1] == NULL)
__tzname[1] = __tzstring (&zone_names[types[i].idx]);
++i;
}
if (i == num_types)
i = 0;
__tzname[0] = __tzstring (&zone_names[types[i].idx]);
if (__tzname[1] == NULL)
{
size_t j = i;
while (j < num_types)
if (types[j].isdst)
{
__tzname[1] = __tzstring (&zone_names[types[j].idx]);
break;
}
else
++j;
}
}
else if (timer >= transitions[num_transitions - 1])
{
if (tzspec == NULL)
{
use_last:
i = num_transitions - 1;
goto found;
}
/* Parse the POSIX TZ-style string. */
__tzset_parse_tz (tzspec);
/* Convert to broken down structure. If this fails do not
use the string. */
if (! __offtime (&timer, 0, tp))
goto use_last;
/* Use the rules from the TZ string to compute the change. */
__tz_compute (timer, tp, 1);
*leap_correct = 0L;
*leap_hit = 0;
return;
}
else
{
/* Find the first transition after TIMER, and
then pick the type of the transition before it. */
size_t lo = 0;
size_t hi = num_transitions - 1;
/* Assume that DST is changing twice a year and guess initial
search spot from it.
Half of a gregorian year has on average 365.2425 * 86400 / 2
= 15778476 seconds. */
i = (transitions[num_transitions - 1] - timer) / 15778476;
if (i < num_transitions)
{
i = num_transitions - 1 - i;
if (timer < transitions[i])
{
if (i < 10 || timer >= transitions[i - 10])
{
/* Linear search. */
while (timer < transitions[i - 1])
--i;
goto found;
}
hi = i - 10;
}
else
{
if (i + 10 >= num_transitions || timer < transitions[i + 10])
{
/* Linear search. */
while (timer >= transitions[i])
++i;
goto found;
}
lo = i + 10;
}
}
/* Binary search. */
/* assert (timer >= transitions[lo] && timer < transitions[hi]); */
while (lo + 1 < hi)
{
i = (lo + hi) / 2;
if (timer < transitions[i])
hi = i;
else
lo = i;
}
i = hi;
found:
/* assert (timer >= transitions[i - 1] && timer < transitions[i]); */
__tzname[types[type_idxs[i - 1]].isdst]
= __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
size_t j = i;
while (j < num_transitions)
{
int type = type_idxs[j];
int dst = types[type].isdst;
int idx = types[type].idx;
if (__tzname[dst] == NULL)
{
__tzname[dst] = __tzstring (&zone_names[idx]);
if (__tzname[1 - dst] != NULL)
break;
}
++j;
}
i = type_idxs[i - 1];
}
struct ttinfo *info = &types[i];
__daylight = rule_stdoff != rule_dstoff; __daylight = rule_stdoff != rule_dstoff;
__timezone = -rule_stdoff; __timezone = -rule_stdoff;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991-2002,2003,2004 Free Software Foundation, Inc. /* Copyright (C) 1991-2002,2003,2004,2007 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -70,7 +70,6 @@ static tz_rule tz_rules[2];
static void compute_change (tz_rule *rule, int year) __THROW internal_function; static void compute_change (tz_rule *rule, int year) __THROW internal_function;
static void tz_compute (const struct tm *tm) __THROW internal_function;
static void tzset_internal (int always, int explicit) static void tzset_internal (int always, int explicit)
__THROW internal_function; __THROW internal_function;
@ -92,7 +91,7 @@ __tzstring (const char *s)
{ {
char *p; char *p;
struct tzstring_l *t, *u, *new; struct tzstring_l *t, *u, *new;
size_t len = strlen(s); size_t len = strlen (s);
/* Walk the list and look for a match. If this string is the same /* Walk the list and look for a match. If this string is the same
as the end of an already-allocated string, it can share space. */ as the end of an already-allocated string, it can share space. */
@ -140,80 +139,34 @@ __tzname_max ()
static char *old_tz; static char *old_tz;
/* Interpret the TZ envariable. */
static void static void
internal_function internal_function
tzset_internal (always, explicit) update_vars (void)
int always; {
int explicit; __daylight = tz_rules[0].offset != tz_rules[1].offset;
__timezone = -tz_rules[0].offset;
__tzname[0] = (char *) tz_rules[0].name;
__tzname[1] = (char *) tz_rules[1].name;
/* Keep __tzname_cur_max up to date. */
size_t len0 = strlen (__tzname[0]);
size_t len1 = strlen (__tzname[1]);
if (len0 > __tzname_cur_max)
__tzname_cur_max = len0;
if (len1 > __tzname_cur_max)
__tzname_cur_max = len1;
}
/* Parse the POSIX TZ-style string. */
void
__tzset_parse_tz (tz)
const char *tz;
{ {
static int is_initialized;
register const char *tz;
register size_t l; register size_t l;
char *tzbuf; char *tzbuf;
unsigned short int hh, mm, ss; unsigned short int hh, mm, ss;
unsigned short int whichrule; unsigned short int whichrule;
if (is_initialized && !always)
return;
is_initialized = 1;
/* Examine the TZ environment variable. */
tz = getenv ("TZ");
if (tz == NULL && !explicit)
/* Use the site-wide default. This is a file name which means we
would not see changes to the file if we compare only the file
name for change. We want to notice file changes if tzset() has
been called explicitly. Leave TZ as NULL in this case. */
tz = TZDEFAULT;
if (tz && *tz == '\0')
/* User specified the empty string; use UTC explicitly. */
tz = "Universal";
/* A leading colon means "implementation defined syntax".
We ignore the colon and always use the same algorithm:
try a data file, and if none exists parse the 1003.1 syntax. */
if (tz && *tz == ':')
++tz;
/* Check whether the value changes since the last run. */
if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
/* No change, simply return. */
return;
if (tz == NULL)
/* No user specification; use the site-wide default. */
tz = TZDEFAULT;
tz_rules[0].name = NULL;
tz_rules[1].name = NULL;
/* Save the value of `tz'. */
if (old_tz != NULL)
free (old_tz);
old_tz = tz ? __strdup (tz) : NULL;
/* Try to read a data file. */
__tzfile_read (tz, 0, NULL);
if (__use_tzfile)
return;
/* No data file found. Default to UTC if nothing specified. */
if (tz == NULL || *tz == '\0'
|| (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
{
tz_rules[0].name = tz_rules[1].name = "UTC";
tz_rules[0].type = tz_rules[1].type = J0;
tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
tz_rules[0].secs = tz_rules[1].secs = 0;
tz_rules[0].offset = tz_rules[1].offset = 0L;
tz_rules[0].change = tz_rules[1].change = (time_t) -1;
tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
goto out;
}
/* Clear out old state and reset to unnamed UTC. */ /* Clear out old state and reset to unnamed UTC. */
memset (tz_rules, 0, sizeof tz_rules); memset (tz_rules, 0, sizeof tz_rules);
tz_rules[0].name = tz_rules[1].name = ""; tz_rules[0].name = tz_rules[1].name = "";
@ -413,20 +366,81 @@ tzset_internal (always, explicit)
} }
out: out:
__daylight = tz_rules[0].offset != tz_rules[1].offset; update_vars ();
__timezone = -tz_rules[0].offset; }
__tzname[0] = (char *) tz_rules[0].name;
__tzname[1] = (char *) tz_rules[1].name;
{ /* Interpret the TZ envariable. */
/* Keep __tzname_cur_max up to date. */ static void
size_t len0 = strlen (__tzname[0]); internal_function
size_t len1 = strlen (__tzname[1]); tzset_internal (always, explicit)
if (len0 > __tzname_cur_max) int always;
__tzname_cur_max = len0; int explicit;
if (len1 > __tzname_cur_max) {
__tzname_cur_max = len1; static int is_initialized;
} register const char *tz;
if (is_initialized && !always)
return;
is_initialized = 1;
/* Examine the TZ environment variable. */
tz = getenv ("TZ");
if (tz == NULL && !explicit)
/* Use the site-wide default. This is a file name which means we
would not see changes to the file if we compare only the file
name for change. We want to notice file changes if tzset() has
been called explicitly. Leave TZ as NULL in this case. */
tz = TZDEFAULT;
if (tz && *tz == '\0')
/* User specified the empty string; use UTC explicitly. */
tz = "Universal";
/* A leading colon means "implementation defined syntax".
We ignore the colon and always use the same algorithm:
try a data file, and if none exists parse the 1003.1 syntax. */
if (tz && *tz == ':')
++tz;
/* Check whether the value changes since the last run. */
if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
/* No change, simply return. */
return;
if (tz == NULL)
/* No user specification; use the site-wide default. */
tz = TZDEFAULT;
tz_rules[0].name = NULL;
tz_rules[1].name = NULL;
/* Save the value of `tz'. */
if (old_tz != NULL)
free (old_tz);
old_tz = tz ? __strdup (tz) : NULL;
/* Try to read a data file. */
__tzfile_read (tz, 0, NULL);
if (__use_tzfile)
return;
/* No data file found. Default to UTC if nothing specified. */
if (tz == NULL || *tz == '\0'
|| (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
{
tz_rules[0].name = tz_rules[1].name = "UTC";
tz_rules[0].type = tz_rules[1].type = J0;
tz_rules[0].m = tz_rules[0].n = tz_rules[0].d = 0;
tz_rules[1].m = tz_rules[1].n = tz_rules[1].d = 0;
tz_rules[0].secs = tz_rules[1].secs = 0;
tz_rules[0].offset = tz_rules[1].offset = 0L;
tz_rules[0].change = tz_rules[1].change = (time_t) -1;
tz_rules[0].computed_for = tz_rules[1].computed_for = 0;
update_vars ();
return;
}
__tzset_parse_tz (tz);
} }
/* Figure out the exact time (as a time_t) in YEAR /* Figure out the exact time (as a time_t) in YEAR
@ -523,13 +537,34 @@ compute_change (rule, year)
/* Figure out the correct timezone for TM and set `__tzname', /* Figure out the correct timezone for TM and set `__tzname',
`__timezone', and `__daylight' accordingly. */ `__timezone', and `__daylight' accordingly. */
static void void
internal_function internal_function
tz_compute (tm) __tz_compute (timer, tm, use_localtime)
const struct tm *tm; time_t timer;
struct tm *tm;
int use_localtime;
{ {
compute_change (&tz_rules[0], 1900 + tm->tm_year); compute_change (&tz_rules[0], 1900 + tm->tm_year);
compute_change (&tz_rules[1], 1900 + tm->tm_year); compute_change (&tz_rules[1], 1900 + tm->tm_year);
if (use_localtime)
{
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);
tm->tm_isdst = isdst;
tm->tm_zone = __tzname[isdst];
tm->tm_gmtoff = tz_rules[isdst].offset;
}
} }
/* Reinterpret the TZ environment variable and set `tzname'. */ /* Reinterpret the TZ environment variable and set `tzname'. */
@ -583,35 +618,14 @@ __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
if (! __offtime (timer, 0, tp)) if (! __offtime (timer, 0, tp))
tp = NULL; tp = NULL;
else else
tz_compute (tp); __tz_compute (*timer, tp, use_localtime);
leap_correction = 0L; leap_correction = 0L;
leap_extra_secs = 0; leap_extra_secs = 0;
} }
if (tp) if (tp)
{ {
if (use_localtime) if (! use_localtime)
{
if (!__use_tzfile)
{
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;
}
}
else
{ {
tp->tm_isdst = 0; tp->tm_isdst = 0;
tp->tm_zone = "GMT"; tp->tm_zone = "GMT";

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc. /* Copyright (C) 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Andreas Jaeger <aj@suse.de>, 1998. Contributed by Andreas Jaeger <aj@suse.de>, 1998.
@ -44,7 +44,6 @@ static const struct test_times tests[] =
{ "America/Chicago", 1, 21600, {"CST", "CDT" }}, { "America/Chicago", 1, 21600, {"CST", "CDT" }},
{ "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }}, { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }},
{ "America/Los_Angeles", 1, 28800, {"PST", "PDT" }}, { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }},
{ "Asia/Tokyo", 1, -32400, {"JST", "JDT" }},
{ "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }}, { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }},
{ NULL, 0, 0 } { NULL, 0, 0 }
}; };