Re: [RFC] Time\Instant and Time\Clock
| From: | Andreas Heigl | Date: | Thu, 01 Oct 2026 15:57:52 +0000 |
| Subject: | Re: [RFC] Time\Instant and Time\Clock | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-132756@lists.php.net to get a copy of this message | ||
Hey Mirco
On 1 Oct 2026, at 17:22, Mirco Babin wrote:
> Hello Tim Düsterhus,
>
>>> https://wiki.php.net/rfc/time_instant_class
>
> Reply to Wed, 30 Sep 2026 19:48:51 +0000
>
>>> =========
>>> Comment 2
>>> =========
>>> The RFC states:
>>>
>>>> An Time\Instant carries no timezone. It represents a unique point
>>>> on the timeline of the universe.
>>>
>
>> Timezones are a concept to translate a point in time (“Instant”) into
>> date and time as shown on a clock. Both 2026-09-30T20:13:30+02:00 and
>> 2026-09-30T18:13:30+00:00 refer to the same point in time. The point in
>> time itself does not have a timezone. The ISO-8601 getter chooses to
>> represent the point in time with the UTC / Zulu timezone, because
>> specifying an offset is required for the “date and time” representation
>> to be unambiguous. It would be equally valid for it to select a random
>> offset each time you use it. Using UTC / a zero offset is just a
>> pragmatic choice for best interoperability.
>
> Is this unique point on the timelime of the universe concept somewhere
> defined? For example in an IETF-RFC, academic paper or somewhere else?
> Because it seems to me that timeline of the universe must have some
> definition somewhere? The RFC does not have any reference to a formal
> definition?
I'd say that is defined as Barycentric Coordinated Time (TCB). But that is slightly off towards
the Geocentric Coordinated Time (TCG) by about 490 ms per year. Geocentric Coordinated Time and
Terrestrial Time (TT) again differ by a constant from one another. Though both are linear counts of
SI-seconds.
But all that is obsoleted and irrelevant in the end as the Instant is based on the epoch which is
based on UTC minus leap-seconds. At least as far as I understood Tim.
>
>>> =========
>>> 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.
>
>> The RFC acknowledges that. Writing an adapter is easy, particularly
>> since the addition of the
Attachment: [application/pgp-signature] OpenPGP digital signature signature.asc
DateTimeImmutable::toInstant()
>> method to the
>> proposal.
>
> I have demonstrated it is impossible to write an adapter. Given the
> constraint that only the PSR-20 MyClock class can be changed, call-sites
> must not be adjusted. Also the purpose of a PSR-20 Clock is to never
> call new DateTimeImmutable() or
> time() anymore, so the assumption there
> are new DateTimeImmutable() calls that can be adapted is
> incorrect.
An adapter does never need to implement both interfaces. In essence an adapter only needs to
implement "the other" interface. A ClockAdapter uses a ClockInterface to create an Instant
whereas a ClockInterfaceAdapter uses a Clock to create a DateTime. 2 classes that seem rather
straight forward.
>
>>> Consider renaming the function now(): \Time\Instant
>>> function to
>>> function nowAsInstant(): \Time\Instant.
>
>> now() is the obvious name for the method. Using something
>> else would
>> mean that the proposed API would still suffer from a decision made for
>> compatibility after everyone has migrated to it and PSR-20 is long
>> forgotten. The horizon we are planning with is *at least* the next 15
>> years, but we're hoping that the API holds up for even longer.
>
> This is a strange point of view. Why would PSR-20 be forgotten? Is it
> a goal to deprecate/forget PSR-20? And why is this not mentioned in
> the RFC? And what would the duration be of the forget timeline?
>
> time() is also an obvious name for the method. And it would not
> conflict with PSR-20.
I can only second Tim here. The correct and only sensible method name is now() as is
for any other ClockInterface.
Time() has a very special meaning in PHP and people will be very confused to realise that time()
does not return a timestamp.
We had a lot of these discussions when preparing PSR20 and now() IS the sensible name.
And it will also make very clear that it is not possible to have ONE clock that serves BOTH
purposes. Where we come back again to the adapters that make it possible to translate between the
two
>
> ```php
>
> SystemClock::get()->time();
>
> ```
>
>>> =========
>>> Comment 5
>>> =========
>>> The RFC introduces a SystemClock class:
>>>
>
>
>>> The RFC also states a FrozenClock for testing purposes. Well this
>>
>> The FrozenClock is *not* part of the RFC. It is provided in
>> the
>> non-normative part of the RFC as an example to showcase how the
>> Clock
>> interface can be useful for testing purposes. Whether or not a
>> FrozenClock will be added to PHP itself is to be decided as
>> part of a
>> future RFC (by different authors, as indicated in my email from
>> yesterday).
>
> That is surprising. How can a SystemClock be designed without
> exploring the freezing of time? If the SystemClock is wrongly
> designed in this RFC, and hinders the unexplored, unknown FrozenTime,
> "*at least* the next 15 years" there will be an misdesign.
>
> I really think Time\Clock interface, SystemClock, FrozenTime,
> DateTimeImmutable freezing and time() freezing must be one RFC,
> that designs them very well. And don't forget the very popular Carbon
> library in this picture. This design should not be split between
> 2 RFC's and different authors.
Freezing time is always subject to the circumstances. And creating a frozenClock is just a few lines
of code so that for the sake of testing it makes indeed more sense to leave that to the implementor
of the test to create a FrozenClock matching exactly their needs.
>
>>> =========
>>> Comment 6
>>> =========
>>> Why does \Time\Instant not have a named constructor
>>> public static function fromSystemClock(): \Time\Instant
>>> ?
>>>
>
>> If SystemClock was made a singleton
>> with a static getter as mentioned above (while still implementing the
>> interface), this would allow for:
>>
>> SystemClock::get()->now()
>>
>> for simple use cases and one-off scripts, which would be even shorter
>> than your proposed:
>>
>> Instant::fromSystemClock()
>
> If it becomes SystemClock::get()->time() both variants have
> 26
> characters to type. But IDE autocompletion has to parse 3 parts in
> SystemClock::get()->time() and only 2 parts in
> Instant::fromSystemClock().
>
> If it is not too much trouble I would add them both, because it
> increases Developer Experience.
When using SystemClock::get() or Instant::fromSystemClock() you can equally just call time() and be
done.
The whole advantage of injecting an interface that can then be used with a "real" clock in
production and a frozen clock for testing is then obsoleted.
If one requires these static dependencies in their code it is very easy to create the appropriate
classes in Userland and be done.
IMO that is not something the language should provide out of the box.
My 0.02€
Cheers
Andreas
(PSR20 Workinggroup Member)
--
,,,
(o o)
+---------------------------------------------------------ooO-(_)-Ooo-+
| Andreas Heigl |
| mailto:andreas@heigl.org N
50°22'59.5" E 08°23'58" |
| https://andreas.heigl.org
|
+---------------------------------------------------------------------+
| https://hei.gl/appointmentwithandreas
|
+---------------------------------------------------------------------+
| GPG-Key: https://hei.gl/keyandreasheiglorg
|
+---------------------------------------------------------------------+
Attachment: [application/pgp-signature] OpenPGP digital signature signature.asc