Testing with FrozenClock

FastForward Clock provides FrozenClock specifically for testing scenarios where you need deterministic, reproducible time.

Unlike system time which changes every second, FrozenClock returns a fixed time that you control.

Direct usage in tests

The simplest way to use deterministic time in tests:

<?php

declare(strict_types=1);

use FastForward\Clock\FrozenClock;

$clock = new FrozenClock('2026-04-07 10:00:00');

echo $clock->now()->format(DATE_ATOM) . PHP_EOL;
// Output: 2026-04-07T10:00:00+00:00

With Fast Forward Container

To use FrozenClock with Fast Forward Container in your tests, register a provider that exposes your frozen clock before ClockServiceProvider :

<?php

declare(strict_types=1);

use FastForward\Clock\ServiceProvider\ClockServiceProvider;
use FastForward\Clock\FrozenClock;
use FastForward\Container\ServiceProvider\ArrayServiceProvider;
use Psr\Clock\ClockInterface;
use Psr\Container\ContainerInterface;
use function FastForward\Container\container;

$frozenClock = new FrozenClock('2026-04-07 10:00:00');

$testProvider = new ArrayServiceProvider([
    FrozenClock::class => static fn(ContainerInterface $container): FrozenClock => $frozenClock,
    ClockInterface::class => static fn(ContainerInterface $container): FrozenClock => $container->get(FrozenClock::class),
]);

$container = container($testProvider, new ClockServiceProvider());

$clock = $container->get(ClockInterface::class);

echo $clock->now()->format(DATE_ATOM) . PHP_EOL;

Why the provider order matters

Fast Forward Container resolves services from earlier initializers first. Registering the test provider before ClockServiceProvider ensures that the PSR interface points to your FrozenClock instead of the default SystemClock .

FrozenClock input formats

FrozenClock accepts multiple input types:

<?php

declare(strict_types=1);

use FastForward\Clock\FrozenClock;
use FastForward\Clock\SystemClock;

// From a string (relative or absolute)
$clock1 = new FrozenClock('2026-04-07 10:00:00');
$clock2 = new FrozenClock('next Monday');
$clock3 = new FrozenClock('+1 hour');

// From a DateTimeImmutable
$clock4 = new FrozenClock(new \DateTimeImmutable('2026-04-07 10:00:00'));

// From a timestamp (integer or float)
$clock5 = new FrozenClock(1775640000);

// From another ClockInterface
$clock6 = new FrozenClock(new SystemClock('America/New_York'));