tech-userlevel archive

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

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



    Date:        Tue, 25 Oct 2022 16:11:48 +0300
    From:        Valery Ushakov <uwe%stderr.spb.ru@localhost>
    Message-ID:  <Y1fglMwkBslXhMK4%pony.stderr.spb.ru@localhost>

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

That, and that strftime() is really just a upgrade for asctime()

  | I further guess that gmtime(3) was there as a surrogate.

gmtime() is an ancient interface, that one has been around a long time.

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

The standard, here, as in most places (unfortunately not all, but most)
just writes down what exists, so everyone knows what can be depended upon.
For whatever reasons, this is how strftime() was defined, and how, when
%s was added to it, it was made to work.

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

You're imagining there's some grand design.   There isn't.  mktime()
as an interface preceded the tzdata that we have now, and was defined
to work using local time.   That is, it is the inverse of localtime().
That's more or less set in stone.   There is (sometimes) a timegm()
interface which does the same for gmtime().   And we have mktime_z()
which allows any zone to be specified.

When %s was added to strftime() it was done by simply calling mktime().
I don't know who originally did that, but that's what happened, and
after that the interface was simply copied.   The original strftime()
interface was really just a (localised) version of
	 sprintf(buf, "%4.4d-%2.2d-%2.2d ..."
with enough flexibility to cope with whatever format the user wanted
(just as writing it as an explicitly as an sprintf format would allow).
That didn't need the zone, so there's no parameter in its arg list to
set it.  When %s was added, the zone is important, there's no parameter,
no guarantee an implementation would have tm_gmtoff available, so
simply using mktime(), and assuming that the local time zone is what
applies makes sense - certainly better than any alternative.

The standard is going to (as it should) say what works now, and what
applications and users can expect.   In this case it is that
strftime("%s") gives the same thing as printf("%ld", mktime())
when applied to the same tm.

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

Yes, as it should here too.   That our man page doesn't mention  mktime()
with %s is a defect, and should get fixed.

There's no point lamenting minor issues like this one - struct tm (which
might be the oldest struct type interface in unix that's still mostly
unchanged from how it existed in the ancient past (ie: before 7th edition))
has long passed its use by date - we really need something entirely new,
with a whole new set of interface functions.   Aside from anything else
tm_year being an int is just too small, there ought to be a field for
fractional seconds, the tm_zone info should be done properly, probably
the original time_t (or maybe timespec, or even better, bintime) should
probably be saved as well.

But doing that in a way that's agreeable to everyone, and then getting it
actually used by applications, is a huge job.   It will take years
(writing the struct definition, probably just days, or weeks for agreement,
writing (or modifying) all the library code certainly weeks, probably
longer to get better interfaces than we now have, updating all the applications
years, or even decades.

kre

kre



Home | Main Index | Thread Index | Old Index