Attached code prints "+0000 America/Los_Angeles" both with glibc and with linked ToT strftime implementation. On MacOs it prints "-0800 America/Los_Angeles". Is it a known issue?
On Jul 18 2022, Almaz Mingaleev via tz wrote:
Attached code prints "+0000 America/Los_Angeles" both with glibc and with linked ToT strftime implementation. On MacOs it prints "-0800 America/Los_Angeles". Is it a known issue? #include <time.h> #include <stdio.h> #include <stdlib.h>
int main() { struct tm tm = {.tm_mday = 12, .tm_mon = 3, .tm_year = 2022 - 1900, .tm_zone = "America/Los_Angeles"};
You are not setting tm_gmtoff, thus it remains at zero. MacOS probably doesn't have tm_gmtoff. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different."
On Jul 18, 2022, at 1:44 AM, Andreas Schwab via tz <tz@iana.org> wrote:
You are not setting tm_gmtoff, thus it remains at zero. MacOS probably doesn't have tm_gmtoff.
Given that it's derived from, among other sources, various 4.4-Lite-derived BSDs, macOS most definitely *does* have tm_gmtoff.
Setting tm_gmtoff "fixes" it. Should I call mktime before passing tm struct into strftime? Or assumption here is "garbage in - garbage out"? It was unexpected to me and it is not clear from man pages. Also, as strftime has no way of indicating error [1], is there any downside of "doing the right thing" (tm) and instead of using user provided tm_gmtoff get it from mktime call? Yep, there is tm_gmtoff in MacOs. Moreover, its strftime implementation ignores any garbage value stored there and puts the correct value into the passed array. [1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html On Mon, 18 Jul 2022 at 10:04, Guy Harris via tz <tz@iana.org> wrote:
On Jul 18, 2022, at 1:44 AM, Andreas Schwab via tz <tz@iana.org> wrote:
You are not setting tm_gmtoff, thus it remains at zero. MacOS probably doesn't have tm_gmtoff.
Given that it's derived from, among other sources, various 4.4-Lite-derived BSDs, macOS most definitely *does* have tm_gmtoff.
On 2022-07-18 09:34, Almaz Mingaleev via tz wrote:
Setting tm_gmtoff "fixes" it.
According to page 366 in the newest C draft standard at [https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2912.pdf], strftime() looks at the member .tm_isdst for the format patterns %z and %Z; but this member was not initialized and is therefore "indeterminate", so that the result produced by strftime() may be "unspecified". 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. Michael Deckers.
Tried to set tm_isdst to 0 and 1. With glibc and tzcode strftime the result is the same, they print +0000. MacOs works as expected - it prints standard and DST offsets. Though when I set it to -1 both glibc and MacOs just skip %z. tzcode's implementation replaces %z with +0000 in that case. On Mon, 18 Jul 2022 at 11:04, Michael H Deckers < michael.h.deckers@googlemail.com> wrote:
On 2022-07-18 09:34, Almaz Mingaleev via tz wrote:
Setting tm_gmtoff "fixes" it.
According to page 366 in the newest C draft standard at [https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2912.pdf], strftime() looks at the member .tm_isdst for the format patterns %z and %Z; but this member was not initialized and is therefore "indeterminate", so that the result produced by strftime() may be "unspecified".
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.
Michael Deckers.
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.
On 7/18/22 10:03:11, Paul Eggert via tz wrote:
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.
It may be worse. I read somewhere (citation needed) that in SMTP Date: headers a signed value indicates a geographic longitude; unsigned 0000 merely UTC with location unspecified. -- gil
On 7/18/22 09:03, Paul Eggert wrote:
I suppose someone should file a defect report with the C standardization committee.
I found what I hope is the correct email address for that (it's not well-advertised) and submitted the following bug report: ---- Subject: strftime %z and %Z depend on more than just tm_isdst A recent discussion in the Time Zone Database mailing list <https://mm.icann.org/pipermail/tz/2022-July/031674.html> has prompted me to file this bug report against the C standard. Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3 says that the %z and %Z conversion specifiers examine only the tm_isdst members of the passed-in structure. However, this is not how many implementations actually behave. Some implementations (e.g., AIX, Solaris) infer %z and %Z output from tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and therefore sometimes guess %z or %Z output incorrectly when the clock moves back from one standard time to another (e.g., Iran at the end of the year 1978). These implementations typically also depend on the current setting of the TZ environment variable. Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and abbreviation from struct tm members tm_gmtoff and tm_zone that are not specified by the C standard. These implementations do not have to guess %z and %Z output; however, they require that the nonstandard members be filled in correctly by localtime or equivalent. Implementations that conform to the standard's current wording cannot handle anything more complicated than a time zone with just one standard time offset and abbreviation, which means they cannot handle timestamps for locations like Iran, Portugal, etc., that have changed their standard-time offset. The C standard should not require implementations to be so limited that they cannot handle common timekeeping situations. A simple fix for this issue is to require applications to initialize a struct tm as if by localtime or equivalent, before passing the struct tm to strftime. This is what applications need to do anyway, if they want to be portable to real-world systems such as AIX, FreeBSD, GNU/Linux, Solaris, etc. Proposed fix: 1. Remove the two instances of "[tm_isdst]" in the %z and %Z entries in Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3. 2. Add the following text to that paragraph: If the %z and %Z conversion specifiers are used, the broken-down time structure pointed to by timeptr shall contain values generated by a successful previous call to gmtime, gmtime_r, gmtime_s, localtime, localtime_r, localtime_s, or mktime.
Date: Mon, 18 Jul 2022 09:03:11 -0700 From: Paul Eggert via tz <tz@iana.org> Message-ID: <3c04acad-382b-66d2-e16a-97b69643d3dd@cs.ucla.edu> | Good point, and POSIX and the C standard are both wrong here. They're wrong. But not (as things stand) not there. The standards (at least POSIX) treat a timezone (TZ) as stdoffset[dst[offset][,start[/time],end[/time]]] (which does not represent well in plain ascii). At most two offsets, one for standard time, one for summer time. The same for all years, the only variation is which of the two applies now. The alternate form with a leading : is implementation defined, and so nothing more can be said about that. So, tm_isdst is all that is ever need to select one of those. The problem is that that is a hopelessly inept view of how a timezone really behaves - but that's at a whole other level than the specification of strftime("%z") which just follows from this definition. kre
On 7/18/22 10:30, Robert Elz via tz wrote:
So, tm_isdst is all that is ever need to select one of those.
Good point. Still, the C standard (which doesn't mention TZ) should not impose a at-most-two-offsets requirement, since that's not how many C implementations actually behave. And once we get the C standard fixed POSIX will follow, and this should allow the common behavior when TZ has a value like "America/Los_Angeles" or ":America/Los_Angeles" that uses our extension to POSIX.
Paul Gilmartin via tz <tz@iana.org> writes:
It may be worse. I read somewhere (citation needed) that in SMTP Date: headers a signed value indicates a geographic longitude; unsigned 0000 merely UTC with location unspecified.
RFC 2822 section 3.3: The form "+0000" SHOULD be used to indicate a time zone at Universal Time. Though "-0000" also indicates Universal Time, it is used to indicate that the time was generated on a system that may be in a local time zone other than Universal Time and therefore indicates that the date-time contains no information about the local time zone. -- Russ Allbery (eagle@eyrie.org) <https://www.eyrie.org/~eagle/>
Paul Eggert wrote in <7bfb9e88-eeb0-7cd1-b57b-b648558c1ddc@cs.ucla.edu>: |On 7/18/22 09:03, Paul Eggert wrote: |> |> I suppose someone should file a defect report with the C standardization |> committee. | |I found what I hope is the correct email address for that (it's not |well-advertised) and submitted the following bug report: ... |Subject: strftime %z and %Z depend on more than just tm_isdst ... |Some implementations (e.g., AIX, Solaris) infer %z and %Z output from |tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and |therefore sometimes guess %z or %Z output incorrectly when the clock |moves back from one standard time to another (e.g., Iran at the end of |the year 1978). These implementations typically also depend on the |current setting of the TZ environment variable. | |Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and |abbreviation from struct tm members tm_gmtoff and tm_zone that are not |specified by the C standard. These implementations do not have to guess |%z and %Z output; however, they require that the nonstandard members be |filled in correctly by localtime or equivalent. The next POSIX standard at least will support these two members: https://austingroupbugs.net/view.php?id=1533 ... --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt)
On 2022-07-18 16:03, Paul Eggert wrote:
and lines 1 and 5 are wrong.
Thanks for these examples! The semantics of strftime() is a matter of the C standard only, hence the result is not required to depend on members like .tm_gmtoff or .tm_zone which are not required by C (but it could depend on the exact value of .tm_isdst). And POSIX seems to say that their struct tm and strftime() are compliant with C18. So it is perhaps a bit too harsh to say that AIX and Solaris are wrong -- they do not seem to violate a requirement of C. Michael Deckers.
On 7/18/22 15:19, Steffen Nurpmeso wrote:
Thanks for the URL. In looking at that I see one way in which tzcode doesn't conform to the draft POSIX spec: its gmtime generates the abbreviation "GMT" whereas draft POSIX requires it to generate the more-modern "UTC". Proposed patch 0001 attached. Also, while writing the above patch I noticed that 'make install' defaults LOCALTIME to GMT. In the spirit of being more like POSIX, let's change the LOCALTIME default back to Factory. That's the way it used to be. Although we changed it from Factory to GMT in 2010 due to issues with the length of the old Factory abbreviation, these issues were fixed in 2016 so we don't need to worry about them any more. Proposed patches 0002 and 0003 attached.
Just to make sure I understand it correctly: does it mean that %z will be replaced by offset used by a time zone at a time specified by tm struct and TZ env variable so developer won't be able to get DST offset at a time when standard time is in effect as specified methods override tm_isdst field? Or setting the tm_isdst field to the opposite value _after_ any of these calls should also change the way strftime behaves? My understanding of the proposed fix is that users won't be able to get DST time when standard is used and vice-versa. That removes ambiguity around certain dates at some time zones, I like that. On Mon, 18 Jul 2022 at 18:19, Paul Eggert <eggert@cs.ucla.edu> wrote:
On 7/18/22 09:03, Paul Eggert wrote:
I suppose someone should file a defect report with the C standardization committee.
I found what I hope is the correct email address for that (it's not well-advertised) and submitted the following bug report:
----
Subject: strftime %z and %Z depend on more than just tm_isdst
A recent discussion in the Time Zone Database mailing list <https://mm.icann.org/pipermail/tz/2022-July/031674.html> has prompted me to file this bug report against the C standard.
Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3 says that the %z and %Z conversion specifiers examine only the tm_isdst members of the passed-in structure. However, this is not how many implementations actually behave.
Some implementations (e.g., AIX, Solaris) infer %z and %Z output from tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and therefore sometimes guess %z or %Z output incorrectly when the clock moves back from one standard time to another (e.g., Iran at the end of the year 1978). These implementations typically also depend on the current setting of the TZ environment variable.
Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and abbreviation from struct tm members tm_gmtoff and tm_zone that are not specified by the C standard. These implementations do not have to guess %z and %Z output; however, they require that the nonstandard members be filled in correctly by localtime or equivalent.
Implementations that conform to the standard's current wording cannot handle anything more complicated than a time zone with just one standard time offset and abbreviation, which means they cannot handle timestamps for locations like Iran, Portugal, etc., that have changed their standard-time offset. The C standard should not require implementations to be so limited that they cannot handle common timekeeping situations.
A simple fix for this issue is to require applications to initialize a struct tm as if by localtime or equivalent, before passing the struct tm to strftime. This is what applications need to do anyway, if they want to be portable to real-world systems such as AIX, FreeBSD, GNU/Linux, Solaris, etc.
Proposed fix:
1. Remove the two instances of "[tm_isdst]" in the %z and %Z entries in Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3.
2. Add the following text to that paragraph:
If the %z and %Z conversion specifiers are used, the broken-down time structure pointed to by timeptr shall contain values generated by a successful previous call to gmtime, gmtime_r, gmtime_s, localtime, localtime_r, localtime_s, or mktime.
On 7/21/22 04:25, Almaz Mingaleev wrote:
Just to make sure I understand it correctly: does it mean that %z will be replaced by offset used by a time zone at a time specified by tm struct and TZ env variable so developer won't be able to get DST offset at a time when standard time is in effect as specified methods override tm_isdst field? Or setting the tm_isdst field to the opposite value _after_ any of these calls should also change the way strftime behaves?
The former (if I understand you correctly). Platforms that have tm_gmtoff can use its value and ignore tm_isdst's value when interpreting %z.
My understanding of the proposed fix is that users won't be able to get DST time when standard is used and vice-versa. That removes ambiguity around certain dates at some time zones, I like that.
Yes, that's the idea.
Just curious, was there any response? On Mon, 18 Jul 2022 at 18:19, Paul Eggert <eggert@cs.ucla.edu> wrote:
On 7/18/22 09:03, Paul Eggert wrote:
I suppose someone should file a defect report with the C standardization committee.
I found what I hope is the correct email address for that (it's not well-advertised) and submitted the following bug report:
----
Subject: strftime %z and %Z depend on more than just tm_isdst
A recent discussion in the Time Zone Database mailing list <https://mm.icann.org/pipermail/tz/2022-July/031674.html> has prompted me to file this bug report against the C standard.
Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3 says that the %z and %Z conversion specifiers examine only the tm_isdst members of the passed-in structure. However, this is not how many implementations actually behave.
Some implementations (e.g., AIX, Solaris) infer %z and %Z output from tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and therefore sometimes guess %z or %Z output incorrectly when the clock moves back from one standard time to another (e.g., Iran at the end of the year 1978). These implementations typically also depend on the current setting of the TZ environment variable.
Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and abbreviation from struct tm members tm_gmtoff and tm_zone that are not specified by the C standard. These implementations do not have to guess %z and %Z output; however, they require that the nonstandard members be filled in correctly by localtime or equivalent.
Implementations that conform to the standard's current wording cannot handle anything more complicated than a time zone with just one standard time offset and abbreviation, which means they cannot handle timestamps for locations like Iran, Portugal, etc., that have changed their standard-time offset. The C standard should not require implementations to be so limited that they cannot handle common timekeeping situations.
A simple fix for this issue is to require applications to initialize a struct tm as if by localtime or equivalent, before passing the struct tm to strftime. This is what applications need to do anyway, if they want to be portable to real-world systems such as AIX, FreeBSD, GNU/Linux, Solaris, etc.
Proposed fix:
1. Remove the two instances of "[tm_isdst]" in the %z and %Z entries in Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3.
2. Add the following text to that paragraph:
If the %z and %Z conversion specifiers are used, the broken-down time structure pointed to by timeptr shall contain values generated by a successful previous call to gmtime, gmtime_r, gmtime_s, localtime, localtime_r, localtime_s, or mktime.
There may may be no response for a while, as the next joint WG14/INCITS/C (was PL22.11) meeting is next week, agenda is CD ballot and NB comments, and next meeting is in 2 months mid-April, and expected agenda is FCD and DIS. Unless the submission is accepted and someone can get the item discussed under other business, it may not be on any agenda until mid-June or autumn. One point of order is that the latest WCD was 2022-09-03 *N3054* and any DR should refer to that doc §7.29.3.5¶3 p408 at: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf#page=427 As WG14 and INCITS/C are independent and work jointly, it may be useful to submit a change proposal to INCITS/C, and also to the Austin Group, perhaps with the help of some on the list who are or whose org is a member (Apple/Google/IBM/MS/Oracle?) If you also change tzcode docs to follow your proposal and something like the POSIX [tm_isdst] or Linux/glibc man-pages (Calculated from /tm_isdst/.) dependency statements, by adding tm_gmtoff, timezone, altzone or TM_GMTOFF, and tzname or TM_ZONE, as appropriate, referring to the proposal, that would soon get an instance of the changes out to projects that distribute your docs. Similar changes could go in a patch to the Linux man-pages project, perhaps a followup to Almaz post last year https://lore.kernel.org/linux-man/CAJ0cOr-v1GDCqsU86w-rZVvejtppOAW56FxApFPnf... CC current maintainer Alejandro Colomar alx DOT manpages AT gmail DOT com. That would get another instance of the proposal and changes out there on distros which distribute up to date kernels, glibc, and man-pages. Others could also submit copies of the proposal to any standards bodies, and suitable patches referring to the proposal and making the changes, to library and doc projects with which they have contact. -- Take care. Thanks, Brian Inglis Calgary, Alberta, Canada On 2023-02-10 03:42, Almaz Mingaleev via tz wrote:
Just curious, was there any response?
On Mon, 18 Jul 2022 at 18:19, Paul Eggert <eggert@cs.ucla.edu <mailto:eggert@cs.ucla.edu>> wrote:
On 7/18/22 09:03, Paul Eggert wrote: > > I suppose someone should file a defect report with the C standardization > committee.
I found what I hope is the correct email address for that (it's not well-advertised) and submitted the following bug report:
----
Subject: strftime %z and %Z depend on more than just tm_isdst
A recent discussion in the Time Zone Database mailing list <https://mm.icann.org/pipermail/tz/2022-July/031674.html <https://mm.icann.org/pipermail/tz/2022-July/031674.html>> has prompted me to file this bug report against the C standard.
Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3 says that the %z and %Z conversion specifiers examine only the tm_isdst members of the passed-in structure. However, this is not how many implementations actually behave.
Some implementations (e.g., AIX, Solaris) infer %z and %Z output from tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and therefore sometimes guess %z or %Z output incorrectly when the clock moves back from one standard time to another (e.g., Iran at the end of the year 1978). These implementations typically also depend on the current setting of the TZ environment variable.
Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and abbreviation from struct tm members tm_gmtoff and tm_zone that are not specified by the C standard. These implementations do not have to guess %z and %Z output; however, they require that the nonstandard members be filled in correctly by localtime or equivalent.
Implementations that conform to the standard's current wording cannot handle anything more complicated than a time zone with just one standard time offset and abbreviation, which means they cannot handle timestamps for locations like Iran, Portugal, etc., that have changed their standard-time offset. The C standard should not require implementations to be so limited that they cannot handle common timekeeping situations.
A simple fix for this issue is to require applications to initialize a struct tm as if by localtime or equivalent, before passing the struct tm to strftime. This is what applications need to do anyway, if they want to be portable to real-world systems such as AIX, FreeBSD, GNU/Linux, Solaris, etc.
Proposed fix:
1. Remove the two instances of "[tm_isdst]" in the %z and %Z entries in Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3.
2. Add the following text to that paragraph:
If the %z and %Z conversion specifiers are used, the broken-down time structure pointed to by timeptr shall contain values generated by a successful previous call to gmtime, gmtime_r, gmtime_s, localtime, localtime_r, localtime_s, or mktime.
On 2/10/23 02:42, Almaz Mingaleev wrote:
Just curious, was there any response?
No, I never got a response.
On Mon, 18 Jul 2022 at 18:19, Paul Eggert <eggert@cs.ucla.edu> wrote:
On 7/18/22 09:03, Paul Eggert wrote:
I suppose someone should file a defect report with the C standardization committee.
I found what I hope is the correct email address for that (it's not well-advertised) and submitted the following bug report:
----
Subject: strftime %z and %Z depend on more than just tm_isdst
A recent discussion in the Time Zone Database mailing list <https://mm.icann.org/pipermail/tz/2022-July/031674.html> has prompted me to file this bug report against the C standard.
Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3 says that the %z and %Z conversion specifiers examine only the tm_isdst members of the passed-in structure. However, this is not how many implementations actually behave.
Some implementations (e.g., AIX, Solaris) infer %z and %Z output from tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, and tm_isdst, and therefore sometimes guess %z or %Z output incorrectly when the clock moves back from one standard time to another (e.g., Iran at the end of the year 1978). These implementations typically also depend on the current setting of the TZ environment variable.
Other implementations (e.g., FreeBSD, GNU/Linux) get the UT offset and abbreviation from struct tm members tm_gmtoff and tm_zone that are not specified by the C standard. These implementations do not have to guess %z and %Z output; however, they require that the nonstandard members be filled in correctly by localtime or equivalent.
Implementations that conform to the standard's current wording cannot handle anything more complicated than a time zone with just one standard time offset and abbreviation, which means they cannot handle timestamps for locations like Iran, Portugal, etc., that have changed their standard-time offset. The C standard should not require implementations to be so limited that they cannot handle common timekeeping situations.
A simple fix for this issue is to require applications to initialize a struct tm as if by localtime or equivalent, before passing the struct tm to strftime. This is what applications need to do anyway, if they want to be portable to real-world systems such as AIX, FreeBSD, GNU/Linux, Solaris, etc.
Proposed fix:
1. Remove the two instances of "[tm_isdst]" in the %z and %Z entries in Draft N2912, section 7.28.3.5 "The strftime function", pages 365-6, paragraph 3.
2. Add the following text to that paragraph:
If the %z and %Z conversion specifiers are used, the broken-down time structure pointed to by timeptr shall contain values generated by a successful previous call to gmtime, gmtime_r, gmtime_s, localtime, localtime_r, localtime_s, or mktime.
participants (10)
-
Almaz Mingaleev
-
Andreas Schwab
-
Brian Inglis
-
Guy Harris
-
Michael H Deckers
-
Paul Eggert
-
Paul Gilmartin
-
Robert Elz
-
Russ Allbery
-
Steffen Nurpmeso