On 7/18/22 03:04, Michael H Deckers via tz wrote:
By the way, the draft standard seems to be defective in that it does not state that strftime() also looks at the members .tm_year, .tm_mon, tm_mday, .tm_hour, .tm_min, .tm_sec for printing %z or %Z -- one cannot determine the offset or the time zone abbreviation without knowing the timestamp.
Good point, and POSIX and the C standard are both wrong here. In practice, some implementations guess from the members that you mention (and therefore sometimes guess wrong), whereas others look at the nonstandard members tm_gmtoff and tm_zone (and therefore get the answer right if you've filled in the struct tm with localtime). Although all these implementations violate POSIX and the C standard (because they all look somewhere other than tm_isdst) that's a bug in the standards, not in the implementations. I suppose someone should file a defect report with the C standardization committee. (The C standard's spec for %z is also messed up: it's not clear whether four digits of output are required. POSIX doesn't have this problem.) I don't know how to navigate through the C standard bureaucracy, though. On 7/18/22 02:34, Almaz Mingaleev via tz wrote:
is there any downside of "doing the right thing" (tm) and instead of using user provided tm_gmtoff get it from mktime call?
One downside is that it's slower. More important, it can give the wrong answer in cases where mktime guesses wrong. (Many mktime implementations use the user-supplied tm_gmtoff to get the right answer - but if you're relying on that there's no point to calling mktime.) Attached is an example program where the strftime implementations that guess go wrong. On tzcode, GNU/Linux, FreeBSD, etc. (which use tm_gmtoff and tm_zone and so do not guess) this program prints: 1. 283981500 = 1978-12-31 23:45:00 +0400 (+04) standard 2. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 3. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 4. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight 5. 283981500 = 1978-12-31 23:45:00 +0400 (+04) standard 6. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 7. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 8. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight which is the correct answer. On Solaris 10 (which guesses) this prints: 1. 283981500 = 1978-12-31 23:45:00 +0330 (+0330) standard 2. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 3. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 4. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight 5. 283981500 = 1978-12-31 23:45:00 +0330 (+0330) standard 6. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 7. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 8. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight and lines 1 and 5 are wrong. On AIX 7.2 (which guesses in a different way) this prints: 1. 283981500 = 1978-12-31 23:45:00 +04 (+04) standard 2. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 3. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 4. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight 5. 283981500 = 1978-12-31 23:45:00 +0330 (+0330) standard 6. 283983300 = 1978-12-31 23:45:00 +0330 (+0330) standard 7. 1640982600 = 2022-01-01 00:00:00 +0330 (+0330) standard 8. 1656617400 = 2022-07-01 00:00:00 +0430 (+0430) daylight and line 5 is wrong, and line 1 disagrees with line 5 even though they're both converting the same time_t value.