Re: [RFC] Time\Instant and Time\Clock

From: Date: Mon, 05 Oct 2026 13:36:29 +0000
Subject: Re: [RFC] Time\Instant and Time\Clock
References: 1 2 3 4 5 6 7  Groups: php.internals 
Request: Send a blank email to internals+get-132792@lists.php.net to get a copy of this message
Hi On 2026-10-04 16:04, Mirco Babin wrote:
Can an extra explanation be added in the introduction near the aforementioned RFC paragraph? Something like: A \Time\Instant can be viewed as a replacement for the Unix-Epoch-int. With the difference that the base-date might not be 1970-01-01. And with the difference that the \Time\Instant can have more precision in the form of milliscondes, microseconds, nanoseconds. The base-date and extra precision are an implementation detail and not described further. This also means the full timerange of the \Time\Instant is at least that of the Unix-Epoch-int, but can be extended in the future.
I'll put adding a clarification on my list for the next RFC update.
[…] At some point in the future time, one of the 4 libraries switches to \Time\SystemClock. Let's assume it is Beta that adapts. How is this code then going to look?
<?php
//
// Modified theoretical PSR-20-application
//

function AFunctionOfTheApplication()
{
    // $clock might also come from a Dependency Injection container.
    // Or be injected via parameters or via constructor injection.
    // It doesn't really matter.
    $clock = new MyApp_Clock();

    // The $clock is injected into external libraries. These
    // libraries are not under the control of the application.
    // Also the libraries do not use the Dependency Injection
    // container of the application. Otherwise the DI container
    // would have beeen provided as parameter instead of the
    // \Psr\Clock\ClockInterface.
    $result1 = Library_Alfa_Do_Something($clock);

    // Or use the provided Psr20ToNative adapter.
    $clockInstant = new \Time\SystemClock();
    $result2 = Library_Beta_Do_Something($clockInstant);

    $result3 = Library_Gamma_Do_Something($clock);

    $result4 = Library_Theta_Do_Something($clock);
}
?>
I hope the pattern becomes clear. After the \Time\Clock fact the PSR-20-application will be split in 2 clocks. Carefully selecting the right clock for the right call. And the careful selection has to take place on every update of any external library. Because the external library might have switched to \Time\Clock at any moment. This is a maintenance disaster.
The expectation is that you would use one of the two adapters to translate between the PSR-20 clock and PHP’s native clock, depending on which one is the source of truth in your application. The resulting code would look like this:
    function AFunctionOfTheApplication()
    {
        $clock = new MyApp_Clock();
        // The PSR-20 clock is the canonical one for this application,
        // create the native adapter.
        $nativeClock = new Psr20ToNative($clock);
        $result1 = Library_Alfa_Do_Something($clock);
        $result2 = Library_Beta_Do_Something($nativeClock);
        $result3 = Library_Gamma_Do_Something($clock);
        $result4 = Library_Theta_Do_Something($clock);
    }
This is one extra line to initialize the $nativeClock adapter and one changed line to pass the native clock to Beta instead of the PSR-20 clock.
But because the \Time\Clock->now() conflicts, as I have demonstrated, with the \Psr\Clock\ClockInterface->now(), this one-time solution is not possible. Now assume this PSR-20-application is a big one, thousands of classes, millions line of code. This will become a PSR-20-application maintenance disaster.
As Larry noted, changing from PSR-20 to the new date and time API would be a breaking change. This kind of migration would also not be limited to just the change in clocks. The Time\Instant, and the modeling of the new date and time API in general are not a drop-in replacement for the existing DateTimeImmutable API. A library that migrates from PSR-20 to the native clock will want to consistently use the date and time API to benefit from it. This will affect internal calculations and possibly returned values (e.g. returning an Instant where previously a DateTimeImmutable was returned). Just replacing the clock and keeping everything else the same brings little benefit. Changing the clock you pass in is the smallest part of the migration effort. Best regards Tim Düsterhus

« previous php.internals (#132792) next »