Re: workaround for common programming error involving ctime and localtime
! /* ! ** The following is equivalent to `return asctime(localtime(timep));', ! ** except it does not modify localtime's static storage, ! ** and thus it works around all-too-common bugs like ! ** `struct tm *p = localtime(&t1); puts(ctime(&t2)); return p->tm_year'. ! */
Hmmm...given the X3J11 description of ctime in section 4.12.3.2... The ctime funciton converts the calendar time pointed to by timer to local time in the form of a string. It is equivalent to asctime(localtime(timer)) ...do we open ourselves up to standard conformance challenges if ctime is anything except "asctime(localtime(timer))"? --ado
Ooops! ado is right about standards conformance problems with my proposed patch. I looked at the C Standard and it turns out that even tz-1994g has problems, because the standard requires that localtime(&t) == gmtime(&t). The relevant text is in section 4.12.3 of X3.159-1989: Except for the strftime function, these functions [asctime, ctime, gmtime, localtime] return values in one of two static objects: a broken-down time structure and an array of char. So not only must ctime(&t) == asctime(&tm) (as tz-1994g provides), localtime(&t) == gmtime(&t) is also required. I assume that the same is true of offtime. Here's a patch. =================================================================== RCS file: RCS/localtime.c,v retrieving revision 1994.6.1.4 retrieving revision 1994.6.1.5 diff -c -r1994.6.1.4 -r1994.6.1.5 *** localtime.c 1994/05/11 21:32:24 1994.6.1.4 --- localtime.c 1994/05/11 21:50:59 1994.6.1.5 *************** *** 150,155 **** --- 150,161 ---- char * tzname[2] = { wildabbr, wildabbr }; + /* + ** The C Standard requires that localtime and gmtime + ** return values in the same object. + */ + static struct tm tm; + #ifdef USG_COMPAT time_t timezone = 0; int daylight = 0; *************** *** 964,971 **** localtime(timep) const time_t * const timep; { - static struct tm tm; - localsub(timep, 0L, &tm); return &tm; } --- 970,975 ---- *************** *** 1014,1021 **** gmtime(timep) const time_t * const timep; { - static struct tm tm; - gmtsub(timep, 0L, &tm); return &tm; } --- 1018,1023 ---- *************** *** 1027,1034 **** const time_t * const timep; const long offset; { - static struct tm tm; - gmtsub(timep, offset, &tm); return &tm; } --- 1029,1034 ----
participants (2)
-
ado -
eggert@twinsun.com