|
Message-ID: <20180118163452.GQ1627@brightrain.aerifal.cx> Date: Thu, 18 Jan 2018 11:34:52 -0500 From: Rich Felker <dalias@...c.org> To: musl@...ts.openwall.com Subject: Re: Differences between strftime in musl and glibc On Thu, Jan 18, 2018 at 04:25:07PM +0000, Adrián López Tejedor wrote: > Hi, > > I was having a problem parsing dates with python in an Alpine container and > after some time digging I have found a difference in how musl and > glibc calculate the unix Epoch using strftime. > > The format specifier to get the unix epoch is "%s", which is an extension > of GNU ( > https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time..html > ). > > In Glibc they use mktime ( > https://github.com/bminor/glibc/blob/master/time/strftime_l.c#L1127), being > this function aware of time zone. > > In musl is calculated without mktime, adding the seconds of each part of > the tm struct ( > https://git.musl-libc.org/cgit/musl/tree/src/time/strftime.c?h=v1.1.18#n132) > and substracting the GMT offset. This method is unaware of the TZ data (I > have not seen how to define that gmt offset when using strptime). > > Calling directly to musl/mktime work as expected. > > I have attached a small program which shows the difference between musl and > glibc. > > Compiled with glibc: > $ TZ=Europe/Madrid ./a.out > strftime: -3600 > mktime: -3600 > $ TZ=America/New_York ./a.out > strftime: 18000 > mktime: 18000 > > > Compiled with musl: > $ TZ=Europe/Madrid ./a.out > strftime: 0 > mktime: -3600 > $ TZ=America/New_York ./a.out > strftime: 0 > mktime: 18000 > > > Thanks! > Adrián > #define _XOPEN_SOURCE > #include "stdio.h" > #include "stdlib.h" > #include "time.h" > #include "string.h" > > > int main(void) { > char buf[100]; > struct tm tm1, tm2; > memset(&tm1, 0, sizeof(struct tm)); > memset(&tm2, 0, sizeof(struct tm)); > strptime("1/1/1970 00:00:00", "%d/%m/%Y %H:%M:%S", &tm1); > strptime("1/1/1970 00:00:00", "%d/%m/%Y %H:%M:%S", &tm2); > > strftime(buf, 100, "%s", &tm1); > printf("strftime: %s\n", buf); > > time_t seg = mktime(&tm2); > printf("mktime: %ld\n", seg); > > return 0; > } The glibc behavior assumes the tm object is in units of local time (in the current time zone), which is a really bad assumption, since everything else about the strftime API is timezone-agnostic and works with tm objects produced by gmtime() as well as local times. So I believe the musl behavior is correct and the glibc behavior is wrong, but I'm open to further discussion. It probably needs to happen on the Austin Group tracker/list, as %s is scheduled for inclusion in future versions of POSIX but grossly underspecified: http://austingroupbugs.net/view.php?id=169 In particular, the glibc behavior requires that strftime become aware of [changes in] the timezone, which it's currently not specified to do, and there's no specification of if or how strftime determines if the argument is a local or UTC time. My preference would be to say that, unless the struct tm was produced by localtime[_r] or derived from such a struct tm, it's unspecified what time zone %s is referenced against. But I'm open to discussion as part of the standardization process. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.