Open p5pRT opened 5 years ago
The valu for $Config{sGMTIME_max} is too big. That number\, when fed into gmtime() produces undef.
#!/usr/local/bin/perl use strict;
# One-liner to fond (base 2) when GMTIME stops returning dates. # perl -le 'for (32..65) {print "$_ ".scalar gmtime 2**$_}'
# Now narow it down my $format = "%.9f %17d %s";
for ($_=55.85; $_ \< 55.95 ; $_+=0.01 ) { printf "$format\n"\, $_\, 2**$_\, scalar gmtime 2**$_ ||"undef" }
# The value in %Config is wrong use Config; $_=$Config{sGMTIME_max}; printf "\n$format perl $^V \$Config{sGMTIME_max}\n"\, log($_)/log(2)\, $_\, scalar gmtime $_ ||"undef";
$_=67767976233316804; printf "$format Actual value\n\n"\, log($_)/log(2)\, $_\, scalar gmtime $_;
system "uname -srvm";
==========================================
zathras> ./gmtime-test.pl 55.850000000 64941939961306016 Sat Jul 24 05:26:56 2057930123 55.860000000 65393646875487224 Thu Nov 4 17:33:44 2072244145 55.870000000 65848495659720976 Tue Jan 10 22:56:16 2086657730 55.880000000 66306508167441704 Wed Aug 14 04:01:44 2101171568 55.890000000 66767706404086488 Tue Dec 9 22:14:48 2115786358 55.900000000 67232112528152320 Sun Mar 2 07:38:40 2130502803 55.910000000 67699748852260744 Sat May 10 06:39:04 2145321608 55.920000000 68170637844229840 undef 55.930000000 68644802128153736 undef 55.940000000 69122264485489576 undef 55.950000000 69603047856152056 undef
55.911454483 67768036191676799 undef perl v5.28.0 $Config{sGMTIME_max} 55.911453207 67767976233316804 Sun Dec 29 12:00:00 2147483647 Actual value
Linux 4.15.0-39-generic #42-Ubuntu SMP Tue Oct 23 15:48:01 UTC 2018 x86_64
FWIW\, sGMTIME_min\, sLOCALTIME_max\, and sLOCALTIME_min seem also to be affected. I don't understand the "time_size.U" annotation in the docs -- on my system (Darwin) the values appear to be determined by test programs generated and run by the Configure script.
The RT System itself - Status changed from 'new' to 'open'
On Tue\, 27 Nov 2018 09:22:55 -0800\, wyant wrote:
FWIW\, sGMTIME_min\, sLOCALTIME_max\, and sLOCALTIME_min seem also to be affected. I don't understand the "time_size.U" annotation in the docs -- on my system (Darwin) the values appear to be determined by test programs generated and run by the Configure script.
time_size.U refers to:
https://github.com/perl5-metaconfig/metaconfig/blob/master/U/perl/time_size.U
I'm seeing too large a value on Linux 64-bit too:
tony@mars:.../git/perl$ ./perl -Ilib '-V:.*GMTIME.*' sGMTIME_max='67768036191676799'; sGMTIME_min='-62167219200'; tony@mars:.../git/perl$ ./perl -wle 'print gmtime 67768036191676799' gmtime(67768036191676800) too large at -e line 1. gmtime(67768036191676800) failed at -e line 1.
though the output there might indicate a type selection problem - time_t is 64-bits\, but NV is a double (and Time64_T ends up as NV) losing some precision here (but not much it seems.)
Tony
On Tue\, Nov 27\, 2018 at 4:41 PM Tony Cook via RT \perlbug\-followup@​perl\.org wrote:
On Tue\, 27 Nov 2018 09:22:55 -0800\, wyant wrote:
FWIW\, sGMTIME_min\, sLOCALTIME_max\, and sLOCALTIME_min seem also to be affected. I don't understand the "time_size.U" annotation in the docs -- on my system (Darwin) the values appear to be determined by test programs generated and run by the Configure script.
time_size.U refers to:
https://github.com/perl5-metaconfig/metaconfig/blob/master/U/perl/time_size.U
I'm seeing too large a value on Linux 64-bit too:
tony@mars:.../git/perl$ ./perl -Ilib '-V:.*GMTIME.*' sGMTIME_max='67768036191676799'; sGMTIME_min='-62167219200'; tony@mars:.../git/perl$ ./perl -wle 'print gmtime 67768036191676799' gmtime(67768036191676800) too large at -e line 1. gmtime(67768036191676800) failed at -e line 1.
though the output there might indicate a type selection problem - time_t is 64-bits\, but NV is a double (and Time64_T ends up as NV) losing some precision here (but not much it seems.)
A double was chosen as the type to hold Perl's time values since the 53 bits of its mantissa will last us well past the heat death of the universe and works equally well in places where the native time_t is 32 bits or 64 bits:
But the min and max values determined by Configure seem to be looking only at the native time_t\, not Perl's.
According to Porting/README.y2038 and Porting/timecheck.c\, the value sGMTIME_max in %Config is correct. The value is legal in C code but not in Perl.
The following should countdown by seconds\, but jumps by eight. perl -le 'print scalar gmtime 67767976233316804-$_ for (0..59)' Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 12:00:00 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:52 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 Sun Dec 29 11:59:44 2147483647 ...
It's as if bits were being lost in a long int to double to long int conversion.
The precision of gmtime() at its max is 8 seconds. This is an understandable consequence of putting a 56-bit number into a 53-bit mantissa. But why does it stop at 67767976233316804? Perl's gmtime() is stopping 2.5 days before the system's limit of 23:59:59 on the 31st of December in the year 2**31-1.
The problem is an arbitrary constant in pp_sys.c (and t/op/time.t):
./pp_sys.c:4762:#define TIME_UPPER_BOUND 67767976233316800.0
That should be: eval { GMTIME_max . ".0" } ./pp_sys.c:4762:#define TIME_UPPER_BOUND (67768036191676799.0-8.0)
(The fudge factor is to make sure it rounds down to a multiple of 8 seconds.)
The value for sGMTIME_min matches the native min of "1-Jan-0000" in the proleptic Gregorian calendar. Perl currently does not use that value.
In pp_sys.c at line 4755 is this comment: /* The 32 bit int year limits the times we can represent to these boundaries with a few days wiggle room to account for time zone offsets */ /* Sat Jan 3 00:00:00 -2147481748 */ #define TIME_LOWER_BOUND -67768100567755200.0 /* Sun Dec 29 12:00:00 2147483647 */ #define TIME_UPPER_BOUND 67767976233316800.0 /* also used for: pp_localtime() */
There is no need for any wiggle room\, the syscall will return errno=75 when the native limits are exceeded. (EOVERFLOW=Value too large for defined data type)
On Sat\, Dec 1\, 2018 at 3:51 AM Joe Smith \joeinwap@​gmail\.com wrote:
The precision of gmtime() at its max is 8 seconds. This is an understandable consequence of putting a 56-bit number into a 53-bit mantissa. But why does it stop at 67767976233316804? Perl's gmtime() is stopping 2.5 days before the system's limit of 23:59:59 on the 31st of December in the year 2**31-1.
The problem is an arbitrary constant in pp_sys.c (and t/op/time.t):
./pp_sys.c:4762:#define TIME_UPPER_BOUND 67767976233316800.0
That should be: eval { GMTIME_max . ".0" } ./pp_sys.c:4762:#define TIME_UPPER_BOUND (67768036191676799.0-8.0)
(The fudge factor is to make sure it rounds down to a multiple of 8 seconds.)
The value for sGMTIME_min matches the native min of "1-Jan-0000" in the proleptic Gregorian calendar. Perl currently does not use that value.
Which is actually an invalid date: the Gregorian calendar does not have a year zero\, the year before 1AD is 1BC.
Leon
On Sat\, Dec 1\, 2018 at 2:17 PM Leon Timmermans \fawaka@​gmail\.com wrote:
On Sat\, Dec 1\, 2018 at 3:51 AM Joe Smith \joeinwap@​gmail\.com wrote:
The value for sGMTIME_min matches the native min of "1-Jan-0000" in the proleptic Gregorian calendar. Perl currently does not use that value.
Which is actually an invalid date: the Gregorian calendar does not have a year zero\, the year before 1AD is 1BC.
Leon
Which means that sGMTIME_min ought to be moved forward 366 days to 1-Jan-0001.
The values of sLOCALTIME_min and sLOCALTIME_max are unused bits of trivia that are useless for packaged binary distributions. They depend on the timezone of where is was packaged\, the month (DST or not DST)\, and the year (in 2018 California voted to change when daylight savings time ends).
On Sat\, Dec 01\, 2018 at 11:44:23PM -0800\, Joe Smith wrote:
On Sat\, Dec 1\, 2018 at 2:17 PM Leon Timmermans \fawaka@​gmail\.com wrote:
On Sat\, Dec 1\, 2018 at 3:51 AM Joe Smith \joeinwap@​gmail\.com wrote:
The value for sGMTIME_min matches the native min of "1-Jan-0000" in the proleptic Gregorian calendar. Perl currently does not use that value.
Which is actually an invalid date: the Gregorian calendar does not have a year zero\, the year before 1AD is 1BC.
Leon
Which means that sGMTIME_min ought to be moved forward 366 days to 1-Jan-0001.
The values of sLOCALTIME_min and sLOCALTIME_max are unused bits of trivia that are useless for packaged binary distributions. They depend on the timezone of where is was packaged\, the month (DST or not DST)\, and the year (in 2018 California voted to change when daylight savings time ends).
sGMTIME_min and sGMTIME_max are similarly fictional\, the length of the day is increasing about about 1.7ms per century[1]\, adding 1700 seconds to the length of the day in the next million years[2]\, well before the 2**31-1 year limits imposed by the implementation.
Tony
[1] https://www.scientificamerican.com/article/earth-rotation-summer-solstice/
[2] as a rough estimate\, the rate of change will slow
Migrated from rt.perl.org#133688 (status was 'open')
Searchable as RT133688$