NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/60452: gmtime, gmtime_r put wrong time zone into result
This is now PR 60452, but I hadn't set the Category correctly, so it
wasn't sent to the mailing list.
Thomas
----- Forwarded message from wiz%NetBSD.org@localhost -----
>Submitter-Id: net
>Originator: Thomas Klausner
>Organization:
>Confidential: no
>Synopsis: gmtime, gmtime_r put TZ into struct tm
>Severity: serious
>Priority: medium
>Category:
>Class: sw-bug
>Release: NetBSD 11.99.7/x86_64
>Environment:
Architecture: x86_64
Machine: amd64
>Description:
gmtime() and gmtime_r() are documented to return Coordinated
Universal Time (UTC), but they put the time zone offset of the
current timezone (from the system, or from the TZ environment
variable) into the resulting struct tm, while the actual time value
_is_ UTC.
I found this while debugging a jq test failure.
>How-To-Repeat:
Save this to jq.c (based on the actual code in jq, but heavily
simplified):
--- begin ---
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
void f_gmtime(time_t secs, struct tm *tmp) {
memset(tmp, 0, sizeof(*tmp));
if (gmtime_r(&secs, tmp) == NULL)
err(1, "gmtime_r failed");
}
char *f_strftime(time_t secs) {
char buf[1000];
struct tm tm;
memset(&tm, 0, sizeof(struct tm));
f_gmtime(secs, &tm);
// struct tm *tmp;
// tmp = gmtime(&secs);
const char *fmt = "%FT%T%Z";
size_t n = strftime(buf, sizeof(buf), fmt, &tm);
// size_t n = strftime(buf, sizeof(buf), fmt, tmp);
/* POSIX doesn't provide errno values for strftime() failures; weird */
if ((n == 0) || n > sizeof(buf))
err(1, "strftime failed");
return strdup(buf);
}
void f_localtime(time_t secs, struct tm *tmp) {
memset(tmp, 0, sizeof(*tmp));
if (localtime_r(&secs, tmp) == NULL)
err(1, "localtime_r failed");
}
char *f_strflocaltime(time_t secs) {
struct tm tm;
char buf[1000];
f_localtime(secs, &tm);
const char *fmt = "%FT%T%z";
size_t n = strftime(buf, sizeof(buf), fmt, &tm);
/* POSIX doesn't provide errno values for strftime() failures; weird */
if ((n == 0) || n > sizeof(buf))
err(1, "strftime failed");
return strdup(buf);
}
int main(int argc, char *argv[]) {
uint64_t epoch_secs = 1731627341;
printf("%s\n", f_strftime(epoch_secs));
printf("%s\n", f_strflocaltime(epoch_secs));
}
--- end ---
and run this script:
--- begin ---
#!/bin/sh
make jq
./jq
TZ=Etc/GMT+7 ./jq
--- end ---
On my system this reports:
--- begin ---
2024-11-14T23:35:41CET
2024-11-15T00:35:41+0100
2024-11-14T23:35:41-07
2024-11-14T16:35:41-0700
--- end ---
The second and fourth lines are the correct result.
The first and third lines are wrong. They report the (correct) time
in UTC, but the reported time zones are CET (my system default) or
-7 (from TZ) respectively.
>Fix:
Yes, please.
----- End forwarded message -----
Home |
Main Index |
Thread Index |
Old Index