tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: strftime(3) oddities with %s, %z



On Tue, Oct 25, 2022 at 14:56:23 +0700, Robert Elz wrote:

>     Date:        Tue, 25 Oct 2022 04:08:13 +0300
>     From:        Valery Ushakov <uwe%stderr.spb.ru@localhost>
>     Message-ID:  <Y1c2/dI8SeQ1Oz8c%pony.stderr.spb.ru@localhost>
> 
>   | strftime(3) %s format is not in ISO C or POSIX, though the rumor is
>   | that it will be in the next POSIX version.
> 
> It will be.   The text is:
> 
> s    Replaced by the number of seconds since the Epoch as a decimal number,
>      calculated as described for mktime( ). [all members]
> 
> For what it is worth, since we are here, tm_zone and tm_gmtoff will be
> in the next POSIX as well. [...]
> 
>   | The problem though is that mktime(3) is specified to convert tm
>   | "expressed as local time".
> 
> Yes, that is not a problem though, it is how it is specified to work.
> Everything in strftime() takes the struct tm as being in local time.
> (That's why NetBSD has strftime_z()).

I'm not very familiar with the lore of this API, but my guess was that
strftime(3) was specified the way it was b/c TZ info (except for
tm_isdst) was not the official part of struct tm - as you say, the
tm_zone and tm_gmtoff are only now being added to it.

I further guess that gmtime(3) was there as a surrogate.  If we can't
standardize the API that provides conversion for an arbitrary,
explicitly specified timezone, let's provide at least API for UTC and
local time do dodge the "explicitly specified timezone" part.


>   | The test below produces ("g" is for tm from gmtime, "l" is for tm from
>   | localtime):
> 
> I am not sure that calling strftime() on something obtained from gmtime()
> makes any sense.  If one wants UTC conversions, either use strftime_z()
> (not a POSIX interface) or set the timezone to UTC (tzset() with TZ="UTC").

I think this circles back to the issue of whether TZ information is in
fact kept in struct tm, smuggled in by the implementation - as it's
not part of the standard.  Now that tm::tm_gmtoff will be official I'm
not sure the above argument is really convincing.  The tz information
is (will be) part of tm, so it at least feels weird that it is
explicitly ignored by other parts of the same standard.

One can obtain struct tm from gmtime() or from localtime_rz() (or with
the equivalent tzset() song and dance) and the standard (will) require
TZ info to be part of that struct tm, yet strftime() is still told to
ignore those parts, which confuses me.  What is the intended
composability here?  In another thread you said that a man page should
just lay out bare facts and let the user figure out how to use the
API.  Color me stupid.


-uwe


Home | Main Index | Thread Index | Old Index