-
Notifications
You must be signed in to change notification settings - Fork 561
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
POSIX::strftime() behavior change in Perl 5.39.8. #22062
Comments
Using this program:
... bisection with this invocation:
... pointed to 36e41d5
@khwilliamson, can you take a look? Thanks. |
It appears this commit inadvertently fixed a bug that the examples rely on.
So, if the
perlfunc says
So Prior to the blamed commit, We could go back to that behavior, but that is contrary to the documentation, and there would be no way to tell |
I see. But omitting the
The above was run in Olson zone America/New_York, with a corrected version of strftime-try. I note that (so far) Time::Piece does not have this problem, but I'm not sure (yet) how that helps me. Will its |
I'm having trouble understanding this. In New York there was no 2am March 10, 2024. Using your program , I get for the instant before: And, then for the next instant, replicating your results: The hour between 2am and 2:59:59am is "lost", to be regained the next November in the United States. Southhampton Island, in northern Canada is in the same timezone but does not observe daylight savings. Their timezone abbreviation is EST. Same for the entire country of Peru; their timezone is PET If you want UT, specify that as the time zone So it appears to me that the new behavior is accurate. What am I missing? My goal is to get Time-Piece to use POSIX::strftime(), for several reasons, chief is it doesn't work well under threads and has bugs with POSIX locales |
I suspect that we have encountered a smoke-test failure that is due to the problem being discussed in this ticket. See this log, http://perl.develop-help.com/dblog/5051317, which is the full log from this smoke-test run: https://perl5.test-smoke.org/report/5051326. There are 2 instances of 2 test failures each in
Here is the first instance of relevant code in
|
Karl: Maybe I'm missing something. Does
It is GMT I am trying to format, and no hours disappear in GMT regardless of what local time does. |
I'm rather confused by this discussion, perhaps I am missing some common implementation detail of strftime but why would strftime modify the time components it was given based on any timezone setting? It should already receive all of the information it needs, that's the purpose of the separated list output of localtime and gmtime. |
I've been seeing the podlators failure, and was having trouble reproducing it. I suspect now it will only happen between 10am and 11am (I'm on UTC+1100 summer time.) |
The POSIX 2017 Standard says for
The libc |
FWIW, I have added
which is what I was expecting Perl to do, and which it did do before Perl 5.39.8. Also FWIW, IEEE 1003.1-2017's description of Each conversion specifier is replaced by appropriate characters as described in the following list. The appropriate characters are determined using the LC_TIME category of the current locale and by the values of zero or more members of the broken-down time structure pointed to by timeptr, as specified in brackets in the description. The brackets for conversion specifiers for date and time specify only the corresponding fields in the Now, section 7.2 "POSIX Locale" defers to the ISO C standard. I have not looked into this yet, since it's getting late in America/New_York, and anyway ISO tends to want you to drop a wad of Euros on them to see their standards. I am just one Perl hobbyist, and it may well be that 5.39.8 fixes a long-standing bug. But having %H generate |
You can find links to the final working drafts of the C standards at https://en.cppreference.com/w/c/links , which should be good enough for most purposes. |
Well, we now have 16 instances of the failure of And, not surprisingly, we are getting failures when this distribution is tested via CPAN testers. See: http://fast-matrix.cpantesters.org/?dist=podlators;perl=5.39.9;reports=1. Hence, this is now a BBC situation. |
I set my system time to America/Chicago and ran the test between 10 and 11 am CDT. I did not get a test failure.
What am I missing? |
I live in a UTC+1000 (+1100 in summer) timezone, so between those local times problem described here switches the values generated for strftime() from one day to another between 10am and 11am. Chicago is UTC-0600 (-0500 in summer) going by google, so I think you'd need to test this between 6pm and 7pm Chicago time. |
Rather than brain out the time
In America/New_York tests 1 and 6 failed between 8 and 9 PM. I was unable to get failures when going through Correction to the above: I should have used Test::MockTime, but my brain wouldn't come up with it when I needed it. The problem with
|
And just now I happened to run the test suite during the 1-hour failure window, and got the test failure noted above. Running just that file:
Yup, this is a release blocker. |
The problem here is the This is actually the exact reason the I don't think it's appropriate to force |
Still there in 5.39.9. Why is it appropriate for Perl's |
I agree with @haarg that the problem is introduced by letting I believe the current behavior effectively means that It's unfortunate that Perl started canonicalizing the input to #include <stdio.h>
#include <time.h>
int
main(void)
{
time_t now;
struct tm *t;
char buf[BUFSIZ];
now = time(NULL);
t = gmtime(&now);
t->tm_mday = 56;
strftime(buf, sizeof(buf), "%Y-%m-%d", t);
printf("%s\n", buf);
return 0;
} which at the time of this writing prints out
I think that last sentence is the critical part, and would argue that the behavior in blead doesn't follow that promise (it applies a daylight saving rule even though I changed the Pod::Man test suite to stop calling |
After further discussion in Perl/perl5#22062, I'm convined the blead and Perl 5.39.9 behavior is a regression and calling strftime on gmtime should work correctly. Restore the previous test behavior, but retain the enhancement to avoid spurious failures at the day boundary. Partly reverts 34d8417.
On Sun, Mar 17, 2024 at 11:26:28PM -0700, Graham Knop wrote:
The problem here is the `mktime` call. `mktime` only operates on local times. It "normalizes" the fields in the `mytm` struct, which for the problematic cases here includes adjusting the time to match the local DST, changing `tm_isdst` from 0 to 1 and changing the hour.
This is actually the exact reason the `mini_mktime` function exists.
This was added to fix #838 : 33c0e3e.
Indeed. To quote the commit message from 1999:
normalize time for strftime() (without the isdst effects of
mktime()) using a custom mini_mktime()
Also, consider the code comments above the newly-added function:
/*
* mini_mktime - normalise struct tm values without the localtime()
* semantics (and overhead) of mktime().
*/
static void
mini_mktime(struct tm *ptm)
So it seems that it was *very* intentional that mini_mktime() would have
different DST semantics than mktime(), and that this was *specifically*
to give strftime() the "correct" semantics.
So making strftime use mktime() rather than mini_mktime() looks (on the
face of it) to be wrong, and should be reverted.
In any case, we need to decide what to do sometime soon, as
cpan/podlators/t/man/devise-date.t failures are kind of blowing up our
smokers, and we definitely can't release 5.40.0 in this state.
…--
"Emacs isn't a bad OS once you get used to it.
It just lacks a decent editor."
|
This fixes GH Perl#22062, which has extensive discussion not repeated in this commit message
#22119 reverts the blamed commit, clarifies the documentation, and makes unpublic an XS-callable function introduced earlier in the 5.39 series, hence has never appeared in a stable release. I'm doing that because I do view it as a bug that you can't choose whether to get daylight savings time versus not getting it. This will continue to be the case from Perl code, but there ought to be an API for XS code enabling the choice. I think it is too late in the development cycle to have a discussion about this and come to a reasonable conclusion, so this commit just defers the need for that. Note that the other new API function is retained, I find it interesting that there have been a lot of issues and poor decisions and poor communication about Part of the PR message @haarg referred to (thanks for doing the archaeology on this, BTW) says
This is wrong, because The commit message also says
This also not true. All three of those parameters are ignored. They don't need to exist, and it is confusing that they do. My new commit cleans up the text about those. It removes the documentation of what the proper values of two of them should be. There are no improper values, since they are ignored. Plain POSIX Since we have long turned that off, |
This will be fixed in the next commit, and the TODO removed.
This fixes GH Perl#22062, which has extensive discussion not repeated in this commit message
This will be fixed in the next commit, and the TODO removed.
This fixes GH Perl#22062, which has extensive discussion not repeated in this commit message
This fixes GH Perl#22062, which has extensive discussion not repeated in this commit message
This will be fixed in the next commit, and the TODO removed.
This fixes GH #22062, which has extensive discussion not repeated in this commit message
Fixed by #22119 |
POSIX::strftime() behavior change in Perl 5.39.8.
I have observed a behavior change in
POSIX::strftime()
in Perl 5.39.8. This is most succinctly demonstrated by this code:If the
$epoch
represents a time when the local zone is shifted to Summer time, the output will be an hour later than the actual time. That is, at 2024-05-01 23:30:00 the output will be2024-05-02 00:30:00
.Perls before 5.39.8 do not exhibit this behavior.
The behavior seems to be related to the value of element
[8]
of the returned array, theisdst
element. If this is0
(as it is by definition in the case ofgmtime()
), the behavior under Perl 5.39.8 is as described in the previous paragraph. If this element is absent or-1
, the output is an hour later only if the results ofgmtime()
specify a time which is during the jump to Summer time.These tests were done under Olson zone
America/New_York
, and with theTZ
environment variable undefined. I note that the core Perl testext/POSIX/t/time.t
jumps through all sorts of hoops to try to be portable among time zones. My read of this says that the steps relevant to formattinggmtime
output areDoing these does not affect the behavior of the code under any combination of OS and Perl I have tried. But setting
$ENV{TZ}
to any one ofGMT
,UTC
, orUTC0
does cause Perl 5.39.8 to behave like previous Perls, even in the absence of thetzset()
.I have read through the
perldelta.pod
for Perl 5.39.8 and not found this called out as a deliberate change. Adiff -u
between the 5.39.7 and 5.39.8 versions ofPOSIX.xs
finds two changes, but it is not obvious to me that either is relevant.In addition to this document, this Git repository contains two Perl scripts:
strftime-year
This script takes a year on the command line (defaulting to 2024), and formats the date and time for every 30 minutes throughout the year using both
strftime()
andsprintf()
on the output ofgmtime()
. If it detects intervals when the output of the two are not the same, it reports the first time where the difference occurs, and the first time where there ceases to be a difference. You can get more information usingstrftime-year --help
.strftime-try
This script formats its command-line arguments using
strftime()
and prints the results. The arguments are used verbatim. You can get more information usingstrftime-try --help
.Relevant data on the macOS Perl 5.39.8 build:
The text was updated successfully, but these errors were encountered: