orisai/clock – for reliable time testing

Marek Bartoš
Nette Blogger | 1275
+
-1
-

Testing time-related code with current time could be hard. Time moves constantly and we can't test edge-cases reliably. Instead of new DateTimeImmutable(), use $clock->now().

orisai/clock (with Nette integration via orisai/nette-clock) provides PSR-20 implementation just for that.

use Psr\Clock\ClockInterface;

class ExampleService
{

	private ClockInterface $clock;

	public function __construct(ClockInterface $clock)
	{
		$this->clock = $clock;
	}

	public function doSomething(): void
	{
		$currentTime = $this->clock->now();
	}

}

If you don't want or can't inject a service, use a shortcut instead

use function Orisai\Clock\now;

class ExampleService
{

	public function doSomething(): void
	{
		$currentTime = now();
	}

}

For tests, replace default SystemClock with FrozenClock

services:
	orisai.clock.clock:
        # Accepts epoch second (timestamp)
		create: Orisai\Clock\FrozenClock(978307200)
		type: Orisai\Clock\FrozenClock

With frozen clock, time does not change unless we want to. To move in time, use move()

$clock->move(42.666); // seconds.microseconds

Last edited by Marek Bartoš (2022-12-16 12:04)