Hello Tim Düsterhus, ----------------------------------------------------------------------- Tue, 22 Sep 2026 14:20:19 +0000
> following Time\Duration in PHP 8.6, Derick and I created an RFC for > Time\Instant and Time\Clock as the next part of the > new date and time API: > > https://wiki.php.net/rfc/time_instant_class And Tue, 29 Sep 2026 17:17:49 +0000 > Other than that it feels that this RFC has much fewer opinion than > Time\Duration in the same timeframe. Are you all happy and thus > didn't say anything or did you not get around to reading and > evaluating the RFC? If it's the former, feel free to provide a LGTM, > ship it. And if there's anything that bothers you or remains unclear, > please mention it, no matter how big or small. ----------------------------------------------------------------------- ========= Prologue ========= Well, I do have 8 comments on the Request For Comments (RFC). This is a lengthy post, be prepared for a long reading time. ========= Comment 1 ========= Is \Time\Instant meant to be immutable? If so, please state that in the RFC. ========= Comment 2 ========= The RFC states: > An Time\Instant carries no timezone. It represents a unique point > on the timeline of the universe. Why is there no explicit or implicit timezone attached? The RFC reads to me like there is an implicit timezone attached, namely the UTC timezone. Especially the `toIso8601DateTimeString()` function which always returns the 'Z' timezone identifier seems to imply an implicit UTC timezone? ========= Comment 3 ========= Why is it called \Time\Instant? I find \Time\UtcInstant a better name, which embeds the timeline unit used. \Time\UtcInstant leaves room for future different timeline Instants like: - \Time\TaiInstant (International Atomic Time) - \Time\Ut1Instant (Universal Time) - \Time\TtInstant (Terrestrial Time) ========= Comment 4 ========= The \Time\Clock interface conflicts with PSR-20 Clock interface, see https://www.php-fig.org/psr/psr-20/ . A class can never implement both interfaces at the same time. This will hinder adoption. Consider renaming the `function now(): \Time\Instant` function to `function nowAsInstant(): \Time\Instant`. To clarify, with the current proposal the following will not work: ```php <?php namespace Time { final readonly class Instant { // Omitted for the sake of brevity. } interface Clock { /** * The current instant, at the resolution offered by the * underlying clock. */ public function now(): Instant; } } namespace Psr\Clock { interface ClockInterface { /** * Returns the current time as a DateTimeImmutable Object */ public function now(): \DateTimeImmutable; } } namespace MyApp { class MyClock implements \Psr\Clock\ClockInterface, \Time\Clock { public function now(): \DateTimeImmutable { return new \DateTimeImmutable(); } public function nowAsInstant(): \Time\Instant { // return (new \DateTimeImmutable())->toInstant(); } } } // Fatal error: Declaration of MyApp\MyClock::now(): DateTimeImmutable // must be compatible with Time\Clock::now(): Time\Instant ?> ``` ========= Comment 5 ========= The RFC introduces a SystemClock class: ```php <?php final readonly class SystemClock implements \Time\Clock { public function __construct() {} /** * The current instant, at the resolution offered by the platform * clock, * which is generally coarser than nanoseconds. * * Returned values are not guaranteed to be monotonically * increasing across calls. */ public function now(): \Time\Instant {} } ?> ``` Why is SystemClock not a Singleton? Can there be multiple different system clocks in practice? I believe a System Clock, with the emphasis on "System" is a System Wide clock. This clock is not bound to PHP, but to all processes running on the system, including Apache, shell-scripts, NGINX and others. The RFC also states a FrozenClock for testing purposes. Well this pattern is not always going to work. Especially when an application (the main program) uses Composer libraries and wants to freeze time for each and everyone, including the `vendor` directory. Because not every library in the `vendor` directory uses SystemClock. They all use `time()`, because that is currently the standard way to obtain the System Clock. Time freezing must involve the `time()` function! I think `SystemClock` should be removed from this RFC, it deserves a seperate RFC. That RFC should also explore a frozen `time()` function. Meaning the output of `time()` can be frozen recursively. Because of this probably the \Time\Clock interface should also be moved to that new RFC. After removal, how to obtain a \Time\Instant from the System Clock is in comment 6. ========= Comment 6 ========= Why does \Time\Instant not have a named constructor `public function fromSystemClock(): \Time\Instant` ? Why all the complexity of constructing a \Time\SystemClock and calling `now()`? The System Clock is a Singleton and is always available, as the `time()` function shows. ========= Comment 7 ========= The RFC states: > PHP currently offers two ways to represent such a point, and both > are unsatisfying for the general case. A plain int as returned by > time() discards all sub-second precision and carries no type > information, leaving the question of “is this seconds, milliseconds > or something entirely different” to documentation instead of the > type system. I want to bring something else to the table. What if one wants *less* precision? What if one does not want seconds, milliseconds, microseconds, nanoseconds? How is that going to fit into the type system? As a practical example, take a public transportation coach. The coach has a schedule which is expressed in *minutes*, never in *seconds*. The same argument, only *minutes* precision, goes for flight departures and arrivals. Also ferries express their times in *minutes*. One could use a milliseconds \Time\Instant and state that seconds and lower must always be 0. But how can the type system then differentiate between a milliseconds precision \Time\Instant and a minutes precision \Time\Instant? Both are exactly the same type. I think *precision* should somehow be an explicit part of \Time\Instant class. How precise is the \Time\Instant? That can only be answered by the application/system who new-ed the \Time\Instant. Even with `fromUnixTimestamp()` the precision might not be 'seconds', if the agreement in the application-system is to never provide seconds, then only timestamps having :00 seconds are valid. Also the struggle with `toIso8601DateTimeString()` and its output precision indicates there is a need for explicitly specifying the precision. That would also eliminate the assumption that a fractional part can be omitted if it is 0. PHP can never guess in what system/application or communication the \Time\Instant is involved and should never guess its precision. ========= Comment 8 ========= The RFC states: > Extensions may want to adjust their API to take Time\Instant > in addition to an int representing a Unix timestamp or an > object implementing DateTimeInterface. With regard to the `DateTimeInterface`, I want to share that this interface is an internal interface and can't be implemented by user-space classes. See also issue #23543 at https://github.com/php/php-src/issues/23543 To clarify, this does not work: ```php <?php class MyTime implements DateTimeInterface { } // Fatal error: DateTimeInterface can't be implemented by user classes ?> ``` =============== End of comments =============== Kind regards, Mirco Babin
