-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Clock] Fix sleep()
in MockClock
#47615
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
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
To answer your questions, float is not enough precision on 32bit CPU. And clone is used to not leak the identify of the internal object.
8478c6e
to
381cdae
Compare
If it is true, some of my code leads to bugs. Could you guide me on what platforms PHP uses single precision? Maybe ARM32? The https://github.com/php/php-src/blob/master/Zend/zend_float.h tries hard to force double precisioin on any known platform. It's hardly possible to compile modern PHP with single precision floats. Or have I missed something? |
4371ba8
to
0f73cd8
Compare
Oh, that's something I have missed, thanks for pointing at this! We can then simplify things a bit you're right. We just need to be sure to never use any intermediary int in the process and all should be good. Can you do it in this PR? |
OK |
Well, the default "precision" ini setting is 14. So it's a bit tricky convertion: $m = 2.0**53/1e6;
printf('format: %.6F, auto: '. $m, $m);
// format: 9007199254.740992, auto: 9007199254.741 The And the maximum date without losing any presition will be "2112-09-17 23:53:47.370496":
It's possible to increase it up to "2255-06-05 23:47:34.740992" (plus 1 bit), but code will be less clear: public function sleep(float|int $seconds): void
{
$microseconds = (float) $this->now->format('Uu') + $seconds * 1e6;
$datetime = substr_replace(sprintf('@%07.0F', $microseconds), '.', -6, 0);
$timezone = $this->now->getTimezone();
$this->now = (new \DateTimeImmutable($datetime, $timezone))->setTimezone($timezone);
} |
5f9ce0f
to
37f4f7d
Compare
Shouldn't we keep the current code then if it doesn't have these issues? |
🤷♂️ Dates after 2100 year don't look practical. Anyway, it's a mock for testing only. |
f1a80b0
to
8a5a387
Compare
8a5a387
to
066ed61
Compare
Thank you @upyx. |
It fixes losing precision in
$us = $seconds - $s
that occurs because the$seconds
is float.Anyway, why so many calculation? Double precision is enough to represent any valid date and time:
Why is cloning needed for immutable? The beauty of immutables is that they don't need to be copied.