提交 c13f2af1 编写于 作者: N Natanael Copa 提交者: Rich Felker

match historical behavior for tm_gmtoff member of struct tm

tm_gmtoff is a nonstandard field, but on historical systems which have
this field, it stores the offset of the local time zone from GMT or
UTC. this is the opposite of the POSIX extern long timezone object and
the offsets used in POSIX-form TZ strings, which represent the offset
from local time to UTC. previously we were storing these negated
offsets in tm_gmtoff too.

programs which only used this field indirectly via strftime were not
affected since strftime performed the negation for presentation.
however, some programs and libraries accesse tm_gmtoff directly and
were obtaining negated time zone offsets.
上级 e5b086e1
......@@ -354,9 +354,9 @@ void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo
size_t alt, i = scan_trans(t, local, &alt);
if (i != -1) {
*isdst = types[6*i+4];
*offset = -(int32_t)zi_read32(types+6*i);
*offset = (int32_t)zi_read32(types+6*i);
*zonename = (const char *)abbrevs + types[6*i+5];
if (oppoff) *oppoff = -(int32_t)zi_read32(types+6*alt);
if (oppoff) *oppoff = (int32_t)zi_read32(types+6*alt);
UNLOCK(lock);
return;
}
......@@ -390,15 +390,15 @@ void __secs_to_zone(long long t, int local, int *isdst, long *offset, long *oppo
}
std:
*isdst = 0;
*offset = __timezone;
if (oppoff) *oppoff = dst_off;
*offset = -__timezone;
if (oppoff) *oppoff = -dst_off;
*zonename = __tzname[0];
UNLOCK(lock);
return;
dst:
*isdst = 1;
*offset = dst_off;
if (oppoff) *oppoff = __timezone;
*offset = -dst_off;
if (oppoff) *oppoff = -__timezone;
*zonename = __tzname[1];
UNLOCK(lock);
}
......
......@@ -11,7 +11,7 @@ struct tm *__localtime_r(const time_t *restrict t, struct tm *restrict tm)
return 0;
}
__secs_to_zone(*t, 0, &tm->tm_isdst, &tm->__tm_gmtoff, 0, &tm->__tm_zone);
if (__secs_to_tm((long long)*t - tm->__tm_gmtoff, tm) < 0) {
if (__secs_to_tm((long long)*t + tm->__tm_gmtoff, tm) < 0) {
errno = EOVERFLOW;
return 0;
}
......
......@@ -10,14 +10,14 @@ time_t mktime(struct tm *tm)
__secs_to_zone(t, 1, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
if (tm->tm_isdst>=0 && new.tm_isdst!=tm->tm_isdst)
t += opp - new.__tm_gmtoff;
t -= opp - new.__tm_gmtoff;
t += new.__tm_gmtoff;
t -= new.__tm_gmtoff;
if ((time_t)t != t) goto error;
__secs_to_zone(t, 0, &new.tm_isdst, &new.__tm_gmtoff, &opp, &new.__tm_zone);
if (__secs_to_tm(t - new.__tm_gmtoff, &new) < 0) goto error;
if (__secs_to_tm(t + new.__tm_gmtoff, &new) < 0) goto error;
*tm = new;
return t;
......
......@@ -126,7 +126,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
fmt = "%H:%M";
goto recu_strftime;
case 's':
val = __tm_to_secs(tm) + tm->__tm_gmtoff;
val = __tm_to_secs(tm) - tm->__tm_gmtoff;
width = 1;
goto number;
case 'S':
......@@ -178,7 +178,7 @@ const char *__strftime_fmt_1(char (*s)[100], size_t *l, int f, const struct tm *
return "";
}
*l = snprintf(*s, sizeof *s, "%+.2d%.2d",
(-tm->__tm_gmtoff)/3600,
(tm->__tm_gmtoff)/3600,
abs(tm->__tm_gmtoff%3600)/60);
return *s;
case 'Z':
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册