|
|
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.