[tz] strftime %s

Steve Summit scs at eskimo.com
Fri Jan 12 19:47:02 UTC 2024


kre wrote:
> Paul Gilmartin wrote:
>   | That doesn't happen with date +format or
>   | with well-designed C code which can call sprintf with the time_t
>   | used to generate the struct tm.
>
> I know that too, which is what I think I said, or at least, implied.

The bottom line is that %s is a really, really odd strftime
format -- and it's not surprising (it's manifestly inherent)
that it's hard to implement.

Here's the backstory, at least as I see it:

Ordinary C code has no use for %s.  Ordinary C code typically
starts with a time_t value, and only calls localtime or gmtime to
construct a struct tm if it needs to.  And pretty much the only
reason to call localtime or gmtime to construct a struct tm is
so that you can print out a human-readable time string, perhaps
using strftime.

But of course %s is not a human-readable time string.  And
ordinary C code wouldn't need strftime %s to print a raw time_t
value in the first place, because (as I was just saying) ordinary
C code typically has raw time_t values rattling around already,
which are easier to print with printf anyway.  (Yes, as kre
pointed out, it's unclear whether you'd want %ld or %lld, or
some other variant, to do so, but that's another story.)

But, despite their non-human-readableness, time_t values are now
so ubiquitous that they are occasionally of interest to humans,
so at some point along the way, the 'date' command acquired "%s"
as one of its custom output format specifiers.

So the specification for the 'date' command was really strange:
when you asked it to print a custom string using "date +fmt",
the specification for the format string was basically "anything
strftime can do, plus %s".

I don't know off the top of my head how the "official" date
command implemented this.  I know that in my own work I've
several times found myself writing code that took a
"strftime-plus-%s" format string, manually scanned for and
interpolated any %s specifiers, then handed it off to strftime to
take care of the rest.  This was unremittingly ugly -- but it was
(to my mind, anyway) still vastly preferable to trying to have
strftime handle %s by itself, because strftime just doesn't have
the right information available to it.

I gather from this thread that someone has decided to "solve"
this problem anyway, by officially adding %s to the supported
strftime formats.  However, it seems to me that the only
"problem" here is that the 'date' program has been difficult to
write.  My own opinion is that dragging the whole rest of the
world through this mudpit is not the right way of solving date's
implementation problem -- but then, I'm not on the Posix
committee, so it doesn't matter what I think.

(Me, I'd say that if strftime is to support %s, then either
(a) struct tm has to be augmented with a new field for the
original time_t value, or (b) %s has to be supported only with
a new strftime variant where you explicitly pass in the time_t
value for %s to use, if necessary: strftime_s(char *buf, size_t
bufsize, const char *format, struct tm *timeptr, time_t t).  I
hope that, in the absence of either of these admittedly radical
proposals, Posix is at least mandating tm_gmtoff, which we've
long needed anyway, and which would at least make the implicit
mktime call, necessitated by %s, a tractable problem.)



More information about the tz mailing list