The application of $timestamp = (new DateTime('@' . $timestamp))->getTimestamp();
line should be idempotent, since all we’re doing is switching formats and the output format is the same as the input format, meaning that repeated applications should lead to the same result, right?
Now, could anyone guess what this code would output in PHP 8.0?
<?php
$date = '0000-02-29 00:00:00 UTC';
$timestamp = strtotime($date);
for ($i = 0; $i<29; $i++) {
$timestamp = (new DateTime('@' . $timestamp))->getTimestamp();
}
echo (new DateTime('@' . $timestamp))->format('Y-m-d') . "\n";
This has been reported as bug 78496 and 78499 already
The DateTime class in PHP is an endless wellspring of WTFs.
Time travel in this way is only possible since PHP 7.2.
I just ran this on 8.1-dev and the output is:
Okay sweetie.
Sounds like 8.1 is going to be our best release yet! 😜
TL;DR: This only affects February dates in the year 0000
(something very unlikely for almost anyone to run into).
For links to the mentioned bugs:
https://bugs.php.net/bug.php?id=78496
https://bugs.php.net/bug.php?id=78499 (duplicate of 78496)
(OP posted in the bug report over a year ago)
Output via 3v4l:
https://3v4l.org/vqrKt
This code has even more problems than you might think.
Not only does the 29th of February not exist, neither does the year 0. We go from 1 BC to 1 AD.
That timestamp would also not fit into a 32 bit int, making things even more weird if that’s the int size you compiled php with.
error
Nope.
Output for 7.2.0 – 7.2.34, 7.3.0 – 7.3.25, 7.4.0 – 7.4.13, 8.0.
00000-01-30
Output for 5.4.0 – 5.4.45, 5.5.0 – 5.5.38, 5.6.0 – 5.6.40, 7.0.0 – 7.0.33, 7.1.0 – 7.1.33
0000-02-29
Output for 4.4.2 – 4.4.9, 5.1.0 – 5.1.6, 5.2.0 – 5.2.17, 5.3.0 – 5.3.29
Parse error: syntax error, unexpected T_OBJECT_OPERATOR in /in/nEDII on line 7
Process exited with code 255*.*
Output for 4.3.0 – 4.3.1, 4.3.5 – 4.3.11, 4.4.0 – 4.4.1, 5.0.0 – 5.0.5
Parse error: parse error, unexpected T_OBJECT_OPERATOR in /in/nEDII on line 7
Process exited with code 255*.*
Output for 4.3.2 – 4.3.4
Parse error: parse error in /in/nEDII on line 7
Process exited with code 255*.*