[tz] [PROPOSED 2/2] strftime: conform better to POSIX+

Paul Eggert eggert at cs.ucla.edu
Thu Aug 13 23:18:13 UTC 2020

On 8/12/20 6:25 AM, Robert Elz wrote:

> I think it might be just %Z (rarely) and %p (sometimes) which ever
> produce an empty string.   How many of those other APIs would ever
> be given either "%Z" or "%p" as their arg?

It's pretty common to design a general-purpose API that is a wrapper around 
strftime. For example, Emacs has a function 'emacs_nmemftime' that is a wrapper 
around strftime that also allows formats containing NUL bytes (as these are 
allowed in Emacs strings). An Emacs Lisp program supplied by the user can invoke 
(format-time-string "%p") which invokes emacs_nmemftime which in turn invokes 
strftime with a "%p" argument. (The actual code is a bit more complicated than 
this, but for now let's assume this simpler version.)

Now, emacs_nmemftime could be modified to treat formats like "%p%Z" as special 
cases, and format " %p%Z" instead and discard the leading space in the output. 
Or, we could modify emacs_nmemftime to always make a copy of the format with an 
extra space in it, call strftime, and then remove the leading space in the 
result. Or, we could document 'format-time-string' to mishandle formats like 
"%p%Z" in some cases.

But none of these alternatives are good, for obvious reasons. They're all hacks 
to work around the deficiency in the C11 strftime API. Since POSIX is fixing 
strftime errno deficiencies anyway in other areas, by defining what to do with 
out-of-range times, it might as well fix this deficiency with "%p" too, while 
it's at it.

> The problem with this one is that all implementations need to support it,
> or it is worthless.

That same objection applies to the EOVERFLOW errno change that is already in the 
POSIX strftime draft, as well as to many of the other changes in the POSIX 
draft, so evidently it's not a fatal objection.

> [for mktime] ... In most cases it is safe to simply assume that won't be the
> case, and simply treat -1 as the error indicator only
That isn't safe in general-purpose routines.

> when more is needed, the check is not all that difficult
> (after a successful return, which is what it would be if the -1 indicates
> that 1969 date, the tm has been normalised, Dec 31, 1969 was a Wednesday,
> so set tm_wday to 0, and then check if on return it has become 3 or 4

I've used that hack too, but neither POSIX nor C11 require the hack to work. 
What I'd propose is that the standard specifies that mktime must not not update 
tm_yday when it fails. This matches all implementations that I know of, and 
allows the hack to work. The variant that I use is to set tm_yday to -1 before 
calling mktime, and test whether it's negative afterwards.

> Another way, if -1 is returned, is to take the original struct tm
> do tm_sec++ and then mktime() again.

This won't work if tm_sec == INT_MAX.

More information about the tz mailing list