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:        Mon, 07 Nov 2022 21:04:49 +0700
    From:        Robert Elz <kre%munnari.OZ.AU@localhost>
    Message-ID:  <12822.1667829889%jacaranda.noi.kre.to@localhost>

Replying to my own message....

  |     Date:        Sun, 6 Nov 2022 17:31:59 +0000
  |     From:        David Holland <dholland-tech%netbsd.org@localhost>
  |     Message-ID:  <Y2fvj/+E7OOx4rbO%netbsd.org@localhost>

  |   | There is nothing in the C99 description of mktime (or
  |   | POSIX either) that specifies which fields it uses,
  |
  | I don't know what's in the C standards, but in POSIX that is specified.

Since then Mouse has sent me the mktime() section from his late C99
draft (I assume) of the C standard.

In this area it is close to 100% identical to the POSIX spec, and specifies
that mktime() uses the same fields of struct tm as POSIX does in the
same way (POSIX clearly copied the text from the C standard...)

POSIX:

  | 	The mktime( ) function shall convert the broken-down time,
  | 	expressed as local time, in the structure pointed to by timeptr,
  | 	into a time since the Epoch value with the same encoding as that
  | 	of the values returned by time( ). The original values of the
  | 	tm_wday and tm_yday components of the structure shall be ignored,
  | 	and the original values of the other components shall not be
  | 	restricted to the ranges described in <time.h>.

C:
      [#2]  The  mktime  function  converts  the broken-down time,
       expressed as local time, in  the  structure  pointed  to  by
       timeptr into a calendar time value with the same encoding as
       that of the values  returned  by  the  time  function.   The
       original values of the tm_wday and tm_yday components of the
       structure are ignored, and the original values of the  other
       components  are  not  restricted  to  the  ranges  indicated
       above.

That is, my earlier analysis of why this does specify the fields
that mktime() uses, and exactly what they are, remains, but now
instead of applying only to the POSIX, applies to both POSIX and C.


It also turns out that the C standard has an important paragraph
that's missing from the POSIX standard.   This has no bearing whatever
on strftime() - it concerns the struct tm that results from a
call to mktime() (and so has some relevance for posix issue #1614,
which is 100% unrelated to strftime) but I include it here for
the benefit of any future readers of this thread.

       [#3] If the call is successful, a second call to the  mktime
       function  with  the  resulting  struct tm value shall always
       leave it unchanged and return the same value  as  the  first
       call.   Furthermore,  if  the  normalized  time  is  exactly
       representable as a time_t value, then the normalized broken-
       down  time  and the broken-down time generated by converting
       the result of the mktime function by  a  call  to  localtime
       shall be identical.

Note that even though mktime() is called by strftime, the struct tm
passed to mktime() is (must be) a copy of the one passed to strftime().

The strftime() arg has the const qualifier (a pointer to a const struct tm)
so strftime is not permitted to modify it.   On the other hand, mktime()
is permitted, perhaps even required to modify the struct tm passed to
it (which obviously does not have the const qualifier).

Hence strftime must make a copy of the struct and pass that to mktime().
No modifications made by mktime() to the struct passed to it are
returned to the caller of strftime, nor are they used in any other
way by strftime - strftime just uses the return value (if it doesn't
indicate an error) to provide the value to be converted to a string
to produce the %s result.

kre



Home | Main Index | Thread Index | Old Index