Feature proposals
Hello,
I encountered an issue with the following code:
Carbon::setTestNow('2019-08-22 14:42:00');
PHP version: 7.1.25
Carbon version: 2.23.1
I expected to get:
Only set time on setTestNow called. Don't pause the time. Keeps time running.
But I actually get:
Paused time
Thanks!
That's on purpose, Carbon::setTestNow is for tests only (unit tests for examples) and it helps you having reliable tests because you can't know in advance how fast your tests will run. So you can pause the time with it. That's precisely the goal of this method. As you're supposed to be in tests and able to mock the date, you can ellipse the time as you wish:
Carbon::setTestNow('2019-08-22 14:42:00');
$user_register_date = Carbon::now();
Carbon::setTestNow('2019-08-22 14:42:10');
$this->assertSame(10, Carbon::now()->diffInSeconds($user_register_date));
What are you trying to achieve?
@kylekatarnls thank you very much for the explanation that is very easy to understand :+1:
my other question, does Carbon have a special method for set the time without making time stop?
Thanks
You can change the clock of your server. It's the clock PHP DateTime uses (and so Carbon), it will always be what gives you the reference (like how long is a second).
So what you expect would be to add/subtract a delta to every Carbon::now() calls.
$delta = Carbon::now()->diffInMicroseconds('2019-08-22 14:42:00', false);
// 3 seconds later
sleep(3);
$date = Carbon::now()->addMicroseconds($delta); // 2019-08-22 14:42:03
I may have an idea. Carbon::setTestNow() could take a closure as argument and in this case we could call this closure to calculate on the fly the now instance each time it's called. So you would have a "live" testNow.
But you still should understand Carbon::setTestNow() is not optimized for production and result in real apps is not guarantee. It will still be just an testing helper.
You can change the clock of your server. It's the clock PHP DateTime uses (and so Carbon), it will always be what gives you the reference (like how long is a second).
So what you expect would be to add/subtract a delta to every
Carbon::now()calls.$delta = Carbon::now()->diffInMicroseconds('2019-08-22 14:42:00'); // 3 seconds later sleep(3); $date = Carbon::now()->addMicroseconds($delta); // 2019-08-22 14:42:03
wow the example you gave is the behavior that I expected. diffInMicroseconds and addMicroseconds in your example open my mind. thank you very much :D :+1:
as a newbie, my idea is save $delta variable to global, then make an wrapper that call addMicroseconds
XD
but I think there is a better way. Any ideas, sir?
Nope, I do not plan to implement so specific usage as shifting the now but to allow the user to say:
$delta = Carbon::now()->diffInMicroseconds('2019-08-21 14:42:00');
Carbon::setTestNow(function (Carbon $now) use ($delta) {
return $now->copy()->addMicroseconds($delta);
});
Carbon::now(); // 2019-08-21 14:42:00 + elapsed time
Carbon::today(); // 2019-08-21 00:00:00
So the user can decide freely how to calculate the now instance each time it's requested. You could say: "time pass twice faster", get it from an external source or any kind of fantasy, for example:
$start = Carbon::now();
Carbon::setTestNow(function (Carbon $now) use ($start) {
return $now->copy()->subMicroseconds($now->diffInMicroseconds($start, false));
});
I prefer more open solution until you would explain how the particular case of shifting the time without freezing it in tests would be useful.
I'm still interested in what you're trying to achieve. It could help me a lot to find the best way to handle it.
Thank you very much, sir @kylekatarnls :smile: :+1: :+1:
In 2.24.0, you will be able to do tests on random date:
Carbon::setTestNow(function () {
return Carbon::parse('2018-'.mt_rand(1, 12).'-'.mt_rand(1, 28));
});
echo new Carbon(); // 2018-01-06
echo "\n";
echo new Carbon(); // 2018-06-25
Or using any calculation based on the real moment (like in previous examples):
$delta = Carbon::now()->diffInMicroseconds('2019-08-21 14:42:00', false);
Carbon::setTestNow(function (Carbon $realNow) use ($delta) {
return $realNow->addMicroseconds($delta);
});
echo Carbon::now()->format('H:i:s.u'); // 14:42:00.000117
echo "\n";
echo Carbon::now()->format('H:i:s.u'); // 14:42:00.000925
Cool! This is more than I want, sir. Thank you very much!
Edit: may be you forget to add use ($delta) in line 3 sir
Indeed.