In Symfony 6.2 we introduced a new Clock component so you can decouple your applications from the system clock (e.g. to create better time-sensitive tests). In Symfony 6.3 we've improved it with new features.

Added a Clock Class and a now() Function

Nicolas Grekas
Contributed by Nicolas Grekas in #48642

In Symfony 6.2 we introduced a ClockInterface and three concrete implementations: NativeClock, ClockMock, and MonotonicClock. In Symfony 6.3 we're introducing a new Clock class which returns the current time and allows to use any implementation of the interface described by PSR-20: Clock spec as a global clock in your application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Symfony\Component\Clock\Clock;
use Symfony\Component\Clock\MockClock;

// You can set a custom clock implementation, or use the NativeClock default one
Clock::set(new MockClock());

// Then, you can get the clock instance
$clock = Clock::get();

// From here, you are able to get the current time
$now = $clock->now();

// And also to sleep for an amount of time
$clock->sleep(2.5);

We also added a now() function that you can use anywhere in your application to get the current time:

1
2
3
use function Symfony\Component\Clock\now;

$now = now(); // returns a DateTimeImmutable instance

Symfony now also wires this global clock as a service so that injecting the ClockInterface or using now() or Clock::get() returns the same time.

Added a ClockAwareTrait

Nicolas Grekas
Contributed by Nicolas Grekas in #48362

Thanks to the ClockInterface, you can update your time-sensitive services as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class StoreSchedule
 {
     public function __construct(
         // ...
+        private ClockInterface $clock
     ) {
     }

     public function isOpen(): bool
     {
-        $now = new \DateTimeImmutable();
+        $now = $this->clock->now();

         return $this->openTime > $now && ...;
     }
 }

However, for those who prefer to not inject new dependencies in your service constructors, we've also added a trait so you can use this more easily:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Store
 {
+    use ClockAwareTrait;

     public function __construct(
         // ...
     ) {
     }

     public function isOpen(): bool
     {
-        $now = new \DateTimeImmutable();
+        $now = $this->now();

         return $this->openTime > $now && ...;
     }
 }

Clock Support in Other Components

In Symfony 6.3 we've also continued integrating the Clock component in other Symfony features, such as:

Published in #Living on the edge