commit 8b7fb5985bed7f160c13007f19914317e0bcc6a6
parent 8b2d17a35d1d4d0a40f5a615ae36dd084d1ae079
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date: Tue, 14 Apr 2026 11:05:42 +0200
libc/time: Preserve timezone fields in localtime
Commit b843da74 fixed a bug initializating the timezone fields in
gmtime() because these fields were assumed to have a value always,
but as gmtime was used to adjust the calendar time at the end of
localtime() then the correct value for them was overwritten, making
localtime() returned always a tm with false information about using
UTC. The problem also happened because the commit 059ee8d which
introduced the parsing of the TZ variable removed the copy back
that was done before that code which assumed that gmtime was updating
them.
Diffstat:
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/src/libc/time/localtime.c b/src/libc/time/localtime.c
@@ -27,9 +27,10 @@ gmtoff(char *tz)
struct tm *
localtime(const time_t *timep)
{
+ char *name;
struct tm *tm;
- time_t t;
- int yday;
+ time_t t, off;
+ int yday, dst;
static int first = 1;
t = *timep;
@@ -45,21 +46,25 @@ localtime(const time_t *timep)
}
first = 0;
- tm->tm_gmtoff = _tzstdoff;
- tm->tm_zone = _tzname[0];
- tm->tm_isdst = 0;
+ off = _tzstdoff;
+ name = _tzname[0];
+ dst = 0;
if (_tzjulian && yday+1 < 60 || FEBDAYS(tm->tm_year) < 29)
yday++;
if (yday >= _tzstart && yday <= _tzend && tm->tm_hour >= 2) {
- tm->tm_gmtoff = _tzdstoff;
- tm->tm_zone = _tzname[1];
- tm->tm_isdst = 1;
+ off = _tzdstoff;
+ name = _tzname[1];
+ dst = 1;
}
- t += tm->tm_gmtoff;
+ t += off;
tm = gmtime(&t);
+ tm->tm_zone = name;
+ tm->tm_isdst = dst;
+ tm->tm_gmtoff = off;
+
return tm;
}