# [RFC] Duration class

- Thread: https://externals.io/message/131376
- Original archive: https://news-web.php.net/php.internals/131376
- Started by tim@bastelstu.be on 2026-06-18T13:47:57+00:00
- Messages: 103
- RFC: Polling API (Implemented (PHP 8.6)) — https://externals.io/rfc/poll_api.md
- RFC: Duration class (Implemented (PHP 8.6)) — https://externals.io/rfc/duration_class.md
- Page 1 of 5: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/131376.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #131376 — tim@bastelstu.be — 2026-06-18T13:47:57+00:00

URL: https://externals.io/message/131376#131376

Hi

Derick and I are proposing the introduction of a new `Time\Duration` 
class to represent “stop-watch” or “egg-timer” durations to improve the 
developer experience for APIs taking a timeout. We are specifically 
targeting PHP 8.6 for this RFC, since part of the motivation is 
improving the API of the new “Polling API” that already landed in PHP 
8.6 (https://wiki.php.net/rfc/poll_api) before the “backwards 
compatibility” door closes with the feature freeze in two months.

This RFC is also intended to be a first part of a modernized date and 
time API in PHP, while being useful on its own. To that extent and given 
the deadline we hope to make, the proposed API is intentionally minimal 
and focused on functionality that we are relatively certain to:

1. Be correct, or
2. be requirement for future additions that cannot later be added 
without breaking compatibility.

We would therefore ask to keep the discussion focused on actual issues 
rather than additional “convenience functionality” that might require 
extensive discussion or thought.

All that said, you can find the RFC at: 
https://wiki.php.net/rfc/duration_class. It hopefully includes all the 
important explanation and also provides a rationale as to why we made 
the design decisions we made.

Best regards
Tim Düsterhus

---

## #131378 — Seifeddine Gmati — 2026-06-18T14:18:24+00:00

URL: https://externals.io/message/131376#131378 · In reply to: #131376

>
> Hi
>
> Derick and I are proposing the introduction of a new `Time\Duration`
> class to represent “stop-watch” or “egg-timer” durations to improve the
> developer experience for APIs taking a timeout. We are specifically
> targeting PHP 8.6 for this RFC, since part of the motivation is
> improving the API of the new “Polling API” that already landed in PHP
> 8.6 (https://wiki.php.net/rfc/poll_api) before the “backwards
> compatibility” door closes with the feature freeze in two months.
>
> This RFC is also intended to be a first part of a modernized date and
> time API in PHP, while being useful on its own. To that extent and given
> the deadline we hope to make, the proposed API is intentionally minimal
> and focused on functionality that we are relatively certain to:
>
> 1. Be correct, or
> 2. be requirement for future additions that cannot later be added
> without breaking compatibility.
>
> We would therefore ask to keep the discussion focused on actual issues
> rather than additional “convenience functionality” that might require
> extensive discussion or thought.
>
> All that said, you can find the RFC at:
> https://wiki.php.net/rfc/duration_class. It hopefully includes all the
> important explanation and also provides a rationale as to why we made
> the design decisions we made.
>
> Best regards
> Tim Düsterhus

Hi Tim,

Thank you for proposing this! I think it would be a good addition, and
a move in the right direction for a better built-in date-time stuff.

I do have some questions:

- Is there a reason the highest unit is seconds not hours?
- The RFC specifies `Duration::fromIso8601String`, but there does not
seem to be a method to turn the duration itself back into an ISO 8601
string. is there a reason for that?
- I think it would be nice to have methods that return the total
duration as a specific unit as a floating point, e.e.g.,
`getTotalSeconds()`, was this considered?

Also, i wanted to point out `Psl\DateTime\Duration` that is basically
the same thing:
https://github.com/php-standard-library/php-standard-library/blob/next/packages/date-time/src/Psl/DateTime/Duration.php#L37
which was modeled after Rust's `std::time::Duration` (
https://doc.rust-lang.org/beta/std/time/struct.Duration.html ) and
Java's `Duration` (
https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html ).

Cheers,
Seifeddine.

---

## #131379 — tim@bastelstu.be — 2026-06-18T15:02:48+00:00

URL: https://externals.io/message/131376#131379 · In reply to: #131378

Hi

Am 2026-06-18 16:18, schrieb Seifeddine Gmati:
> - Is there a reason the highest unit is seconds not hours?

The highest unit supported by the constructors is hours 
(`Duration::fromHours()`). The internal representation uses a seconds + 
nanoseconds pair for the reasons outlined in the design considerations, 
similarly to Rust’s and Java’s Duration. 68 years on 32-bit systems and 
21× the age of the universe on 64-bit systems should be plenty.

> - The RFC specifies `Duration::fromIso8601String`, but there does not
> seem to be a method to turn the duration itself back into an ISO 8601
> string. is there a reason for that?

The best reason there probably is “the proposed API is intentionally 
minimal”.

There are probably also some decisions to be made for the 
re-stringification into ISO-8601: Should it stringify straight into 
`sprintf("PT%d.%09dS", $seconds, $nanoseconds)` or should it try to use 
“as large units as possible” (i.e. minutes and hours). The correct 
answer might depend on the use case and thus it's probably better to 
move this decision to the PHP 8.7 cycle :-)

> - I think it would be nice to have methods that return the total
> duration as a specific unit as a floating point, e.e.g.,
> `getTotalSeconds()`, was this considered?

Derick and I haven't discussed this, but the “minimal API” applies here 
as well. Floating point versions we specifically left out (for now), 
because we didn't want to go into the precision / rounding question. As 
an example how many nanoseconds should `1.4` be? The internal 
representation of that float is `1.3999999999999999`.

Best regards
Tim Düsterhus

---

## #131380 — Seifeddine Gmati — 2026-06-18T15:20:57+00:00

URL: https://externals.io/message/131376#131380 · In reply to: #131379

> Derick and I haven't discussed this, but the “minimal API” applies here
> as well. Floating point versions we specifically left out (for now),
> because we didn't want to go into the precision / rounding question. As
> an example how many nanoseconds should `1.4` be? The internal
> representation of that float is `1.3999999999999999`.
>

I think precision doesn't matter here. The primary reason we added float
total methods in Psl was to be able to bridge a Duration object to other
APIs that accepted float $seconds ( mainly Revolt ), Rust and Java also
both offer the floating point methods, and i think they make sense. Could
be added in the future though.

Another nitpick: I think the namespace should be `DateTime` if this is
supposed to be start of a new API that covers both date and time, so we
don't end up with two namespace later (which will share alot of things back
and forth).

Cheers,
Seifeddine.

---

## #131382 — tim@bastelstu.be — 2026-06-18T15:54:23+00:00

URL: https://externals.io/message/131376#131382 · In reply to: #131380

Hi

Am 2026-06-18 17:20, schrieb Seifeddine Gmati:
> […] float […] Could be added in the future though.

Yes, my reply was not intended to be a “we are definitely against 
floats”, but more a “floats are not completely obvious to handle, so we 
rather think about the consequences later”.

> Another nitpick: I think the namespace should be `DateTime` if this is
> supposed to be start of a new API that covers both date and time, so we
> don't end up with two namespace later (which will share alot of things 
> back
> and forth).

The `Time` namespace matches that of most references we looked at. 
`std::time` in Rust, `java.time` in Java, `time` in Golang. JavaScript 
calling it Temporal is the “odd person out”. Personally I also think of 
“Time” as the generic concept that also includes “Dates”.

Thus the upcoming classes to also handle “calendar dates” and “time as 
shown on a clock” would be appropriately located in the `Time` 
namespace. Java uses `java.time.ZonedDateTime` for the closest 
equivalent to PHP’s existing `DateTimeImmutable` (and 
`java.time.Instant` for timezone-less points in time). See 
https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html#package.description 
for a description of the class hierarchy and relationships.

Best regards
Tim Düsterhus

---

## #131385 — Jorg Sowa — 2026-06-18T16:33:25+00:00

URL: https://externals.io/message/131376#131385 · In reply to: #131382

Hi Tim,
The only one concern I see is the method `fromIso8601String`.

Unfortunately the PHP has this weird constant that is called DATE_ISO8601
https://www.php.net/manual/en/class.datetimeinterface.php#datetimeinterface.constants.iso8601,
that is not in fact proper standard.

I wanted to deprecate it few years ago, but the push back from community
was strong, so I did suggest only deprecation of DATE_RFC7231.

So what kind of format this method will except, standard ISO, or PHP's
version of ISO? Maybe it's worth to find another name?

Kind regards,
Jorg

---

## #131388 — tim@bastelstu.be — 2026-06-18T17:02:42+00:00

URL: https://externals.io/message/131376#131388 · In reply to: #131385

Hi

Am 2026-06-18 18:33, schrieb Jorg Sowa:
> So what kind of format this method will except, standard ISO, or PHP's
> version of ISO? Maybe it's worth to find another name?

The method will accept a ISO-8601 “Period” string, just like 
`DateInterval::__construct()` does. The only restriction is that period 
strings accepted by the Time\Duration class may only contain the “time” 
components. In simplified terms: The given string must start with `PT`.

The format strings you are thinking about are those to format 
date-times, which is a different concern and which will become relevant 
when classes to represent dates and times are added in the future. Given 
those are intended to fix the issues of the current API, I expect them 
to exactly follow the relevant standards when referring to a standard. 
Just like the URI parsers in the new URI extension follow the WHATWG and 
RFC 3986 standards - and any difference is considered a bug. Given that 
namespaces for PHP’s standard library are a relatively new thing, this 
luckily allows us to fix issues by building an entirely new, 
well-designed API without breaking backwards compatibility and without 
needing to come up with weird names to avoid conflicts. This worked well 
for the new random API in 8.2, the new DOM API in 8.4 and the new URI 
API in 8.5 and we hope to continue that with the new date API starting 
in 8.6.

Best regards
Tim Düsterhus

---

## #131390 — Frederik Bosch — 2026-06-18T20:25:10+00:00

URL: https://externals.io/message/131376#131390 · In reply to: #131376

Hi Tim


> Hi
>
> Derick and I are proposing the introduction of a new `Time\Duration` 
> class to represent “stop-watch” or “egg-timer” durations to improve 
> the developer experience for APIs taking a timeout. We are 
> specifically targeting PHP 8.6 for this RFC, since part of the 
> motivation is improving the API of the new “Polling API” that already 
> landed in PHP 8.6 (https://wiki.php.net/rfc/poll_api) before the 
> “backwards compatibility” door closes with the feature freeze in two 
> months.
>
> This RFC is also intended to be a first part of a modernized date and 
> time API in PHP, while being useful on its own. To that extent and 
> given the deadline we hope to make, the proposed API is intentionally 
> minimal and focused on functionality that we are relatively certain to:
>
> 1. Be correct, or
> 2. be requirement for future additions that cannot later be added 
> without breaking compatibility.
>
> We would therefore ask to keep the discussion focused on actual issues 
> rather than additional “convenience functionality” that might require 
> extensive discussion or thought.
>
> All that said, you can find the RFC at: 
> https://wiki.php.net/rfc/duration_class. It hopefully includes all the 
> important explanation and also provides a rationale as to why we made 
> the design decisions we made.
>
> Best regards
> Tim Düsterhus
>

Hi Tim,

Rather than building a whole new date/time library, did you consider 
using the temporal_rs library instead? This library is used for the new 
Temporal API that is now available in Firefox and Chrome and is 
a browser standard.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal

The temporal_rs library is already used in V8, Boa and Kiesel. This 
means the library has a large user-base, that is actively developed, but 
also stable because it needs to adhere to the standards.

Regards,
Frederik

---

## #131391 — tim@bastelstu.be — 2026-06-18T21:20:00+00:00

URL: https://externals.io/message/131376#131391 · In reply to: #131390

Hi

Am 2026-06-18 22:25, schrieb Frederik Bosch:
> Rather than building a whole new date/time library, did you consider 
> using the temporal_rs library instead? This library is used for the new 
> Temporal API that is now available in Firefox and Chrome and is 
> a browser standard.

We did not look specifically at temporal_rs (I wasn't aware of its 
existing until now), but we looked at JavaScript’s Temporal API - 
amongst others.

I'm not speaking for Derick here, but I do not believe it is possible to 
just take an API that was built for a different programming language and 
plug it into a different programming language without making any 
changes. Different programming languages have different capabilities, 
ecosystems and code styles and without adjusting the API to the 
respective language, it will just stick out like a sore thumb.

As an example, JavaScript’s Temporal.Duration.prototype.round is an 
overloaded function with one overload taking an “options object”. This 
is something that works well with JavaScript’s dynamic nature, but is 
something we are moving away from in PHP, because it doesn't interact 
well with explicit type-checked signatures that are a first-class 
citizen in PHP. Semantically PHP is much closer to Java than it is to 
JavaScript and I believe that Java’s `java.time.*` is a comparatively 
better fit than JavaScript’s Temporal, but even that cannot be taken 
as-is, because Java supports overloaded methods (e.g. 
java.time.Duration.minus()) whereas PHP does not.

The complicated part here is the API design, not the internal 
implementation, particularly since PHP already has a date API that 
supports all the relevant operations. It's just that the userland API 
really starts to show its age. So using temporal_rs under the hood, 
while exposing a PHP-specific API will not provide any meaningful 
benefit - and would on the contrary add a new dependency on Rust. I'm 
not saying that including Rust is a bad idea, but integrating Rust 
libraries nicely into the Zend Engine, for example to make them work 
with PHP’s `memory_limit` would be a significant undertaking by itself 
and not be something we can just do as a “don’t worry about it” 
implementation detail.

Best regards
Tim Düsterhus

---

## #131401 — ignace nyamagana butera — 2026-06-19T10:25:40+00:00

URL: https://externals.io/message/131376#131401 · In reply to: #131391

Hi Tim and Derick,

I appreciate the way the Duration class has been introduced. It is
intentionally minimal, which is a sensible approach, while still leaving
room for future extensions.

However, I would advise against introducing Duration::add and Duration::sub
methods. Instead, I would recommend providing a single method,
Duration::sum(Duration
...$durations): self.

Given that a Duration already carries a sign and may therefore be either
positive or negative, the presence of separate add and sub methods could
create an implicit and potentially misleading notion of directional
behavior.

In contrast, a sum method using variadic arguments would allow multiple
Duration instances to be combined in a natural and consistent manner. It
would also avoid implying any expectation regarding the resulting sign,
which may legitimately be either positive or negative depending on the
input values.



> Hi
>
> Am 2026-06-18 22:25, schrieb Frederik Bosch:
> > […]
>
> We did not look specifically at temporal_rs (I wasn't aware of its
> existing until now), but we looked at JavaScript’s Temporal API -
> amongst others.
>
> I'm not speaking for Derick here, but I do not believe it is possible to
> just take an API that was built for a different programming language and
> plug it into a different programming language without making any
> changes. Different programming languages have different capabilities,
> ecosystems and code styles and without adjusting the API to the
> respective language, it will just stick out like a sore thumb.
>
> As an example, JavaScript’s Temporal.Duration.prototype.round is an
> overloaded function with one overload taking an “options object”. This
> is something that works well with JavaScript’s dynamic nature, but is
> something we are moving away from in PHP, because it doesn't interact
> well with explicit type-checked signatures that are a first-class
> citizen in PHP. Semantically PHP is much closer to Java than it is to
> JavaScript and I believe that Java’s `java.time.*` is a comparatively
> better fit than JavaScript’s Temporal, but even that cannot be taken
> as-is, because Java supports overloaded methods (e.g.
> java.time.Duration.minus()) whereas PHP does not.
>
> The complicated part here is the API design, not the internal
> implementation, particularly since PHP already has a date API that
> supports all the relevant operations. It's just that the userland API
> really starts to show its age. So using temporal_rs under the hood,
> while exposing a PHP-specific API will not provide any meaningful
> benefit - and would on the contrary add a new dependency on Rust. I'm
> not saying that including Rust is a bad idea, but integrating Rust
> libraries nicely into the Zend Engine, for example to make them work
> with PHP’s `memory_limit` would be a significant undertaking by itself
> and not be something we can just do as a “don’t worry about it”
> implementation detail.
>
> Best regards
> Tim Düsterhus

---

## #131409 — Larry Garfield — 2026-06-19T16:17:39+00:00

URL: https://externals.io/message/131376#131409 · In reply to: #131376

> Hi
>
> Derick and I are proposing the introduction of a new `Time\Duration` 
> class to represent “stop-watch” or “egg-timer” durations to improve the 
> developer experience for APIs taking a timeout. We are specifically 
> targeting PHP 8.6 for this RFC, since part of the motivation is 
> improving the API of the new “Polling API” that already landed in PHP 
> 8.6 (https://wiki.php.net/rfc/poll_api) before the “backwards 
> compatibility” door closes with the feature freeze in two months.
>
> This RFC is also intended to be a first part of a modernized date and 
> time API in PHP, while being useful on its own. To that extent and given 
> the deadline we hope to make, the proposed API is intentionally minimal 
> and focused on functionality that we are relatively certain to:
>
> 1. Be correct, or
> 2. be requirement for future additions that cannot later be added 
> without breaking compatibility.
>
> We would therefore ask to keep the discussion focused on actual issues 
> rather than additional “convenience functionality” that might require 
> extensive discussion or thought.
>
> All that said, you can find the RFC at: 
> https://wiki.php.net/rfc/duration_class. It hopefully includes all the 
> important explanation and also provides a rationale as to why we made 
> the design decisions we made.
>
> Best regards
> Tim Düsterhus

I support this proposal in general.  I especially like the public readonly properties. :-)

My main suggestions would be for more constructors, though I'm sure that's going to get a response of "MVP, add later." :-P

My main pushback, I think, is the fromIso8601String() method, which is not at all self-descriptive.  Presuming it means the format accepted by DatePeriod (give or take bugs), that's not self-evident anywhere in the RFC, or the method name.  I can easily see people who aren't familiar with that period format (which is, I suspect, most people) trying to use "5:23:44" or similar human time formats instead, which will break.  But that format actually feels more useful, and is also defined somewhere in ISO8601 (as part of the full date/time string if nothing else), so the method name is ambiguous.

I think we do need to come up with a better, more self-documenting name for that operation, and consider if we also want a fromHumanTimeString() that accepts "5:23"44" type strings.

--Larry Garfield

---

## #131410 — Marc B. — 2026-06-19T16:26:52+00:00

URL: https://externals.io/message/131376#131410 · In reply to: #131376

Hi Tim,


Am 18. Juni 2026 15:47:57 MESZ schrieb "Tim Düsterhus" <tim@bastelstu.be>:
>Hi
>
>Derick and I are proposing the introduction of a new `Time\Duration` class to represent “stop-watch” or “egg-timer” durations to improve the developer experience for APIs taking a timeout. We are specifically targeting PHP 8.6 for this RFC, since part of the motivation is improving the API of the new “Polling API” that already landed in PHP 8.6 (https://wiki.php.net/rfc/poll_api) before the “backwards compatibility” door closes with the feature freeze in two months.
>
>This RFC is also intended to be a first part of a modernized date and time API in PHP, while being useful on its own. To that extent and given the deadline we hope to make, the proposed API is intentionally minimal and focused on functionality that we are relatively certain to:
>
>1. Be correct, or
>2. be requirement for future additions that cannot later be added without breaking compatibility.
>
>We would therefore ask to keep the discussion focused on actual issues rather than additional “convenience functionality” that might require extensive discussion or thought.
>
>All that said, you can find the RFC at: https://wiki.php.net/rfc/duration_class. It hopefully includes all the important explanation and also provides a rationale as to why we made the design decisions we made.

Thanks for being this up. I think that's a sensible approach and can be used as a starting point for further improvements to the date/time API.

Some comments though:

1. Why `seconds` is always positive with separate `negative` boolean? I don't get the reason behind that logic and it puts additional effort on the user reading these values. A negative Duration should just be negative seconds. Nanoseconds on the other hand should always between 0 and 999_999_999.

2. fromIso8601String should just be fromIso8601. The name implies a string already and the argument type defines it as well.

3. fromSeconds is the only initiator with a second nanoseconds argument. That feels a bit inconsistent from consistency POV. Also, it's not just applying these values because, to be valid, there needs to be some calculation be done.

4. You have some operator methods defined (+add, -sum, /multiplyBy, <>=compare, what about other operators?

5. Did you thought of supporting float on the initializer methods?

6. You should at least mention that this class works with a fixed definition of e.g. how long a minute is - no leaps tz handling here. Which is the correct approach for it.

7. Naming consistency ... add/sub vs. multiplyBy. Why not addBy/sub[tract]By or multiply to be more consistent?

8. negative vs. isNegative 

9. negate() I would expect to get back a negative Duration. Also, it sounds like modifying the duration but I'm assuming a new instance gets returned. What about inverted()?

10. On assuming the duration is immutable. Does the medifier function still return the same object for the same resulting durations? 

I have spend quite some time experimenting with building a good date/time API matching PHP. What I came up with went into an experimental but already working library in PHP without using the available date/calendar extension.
<https://github.com/marc-mabe/php-timelib>
PS: don't use in product 

PS 2: A working group for that would be great 😃 

Regards,
Marc

---

## #131412 — Larry Garfield — 2026-06-19T16:35:03+00:00

URL: https://externals.io/message/131376#131412 · In reply to: #131410

> Thanks for being this up. I think that's a sensible approach and can be 
> used as a starting point for further improvements to the date/time API.
>
> Some comments though:

> 4. You have some operator methods defined (+add, -sum, /multiplyBy, 
> <>=compare, what about other operators?

What would those be?  Personally I'd want to see operators for add and sub, at least, but I'm not sure what else would be useful.

> 5. Did you thought of supporting float on the initializer methods?

Floats introduce all the complexity and lack of precision of, well, floats.  Best to avoid them.

> 6. You should at least mention that this class works with a fixed 
> definition of e.g. how long a minute is - no leaps tz handling here. 
> Which is the correct approach for it.
>
> 7. Naming consistency ... add/sub vs. multiplyBy. Why not 
> addBy/sub[tract]By or multiply to be more consistent?

I concur here.

> 8. negative vs. isNegative 
>
> 9. negate() I would expect to get back a negative Duration. Also, it 
> sounds like modifying the duration but I'm assuming a new instance gets 
> returned. What about inverted()?

Good point.  negated() would be fine, I think.  (As noted elsewhere, `sort()` vs sorted() is a very common pattern for "modify in place" vs. "make new", across a number of languages.)

--Larry Garfield

---

## #131413 — Marc B. — 2026-06-19T17:12:55+00:00

URL: https://externals.io/message/131376#131413 · In reply to: #131412

Am 19. Juni 2026 18:35:03 MESZ schrieb Larry Garfield <larry@garfieldtech.com>:
>
>
> > […]
>
> > […]
>
>What would those be?  Personally I'd want to see operators for add and sub, at least, but I'm not sure what else would be useful.

Omg, I wrote in a wrong way - sorry.
I mean the RFC just mentions "The Time\Duration class will also implement internal “comparison handlers”, which means that direct comparisons with operators such as < will work".
So there are no other operators defined but there are methods defined for it. I would expect these defined as operators as well. 

Actually, for the division, there are two use cases but the method supports only one.
6s / 2 = 3s
6s / 2s = 3

>
> > […]
>
>Floats introduce all the complexity and lack of precision of, well, floats.  Best to avoid them.

If you have a float at hand you already have the lack of precision. Forcing the user to cast to int before does not make anything better. It's even another source of complexity the user have to deal with. If this gets handled on the initializer it will reduce the complexity for the user.

>
> > […]
>
>I concur here.
>
> > […]
>
>Good point.  negated() would be fine, I think.  (As noted elsewhere, `sort()` vs sorted() is a very common pattern for "modify in place" vs. "make new", across a number of languages.)
>
>--Larry Garfield

---

## #131417 — tim@bastelstu.be — 2026-06-20T10:52:25+00:00

URL: https://externals.io/message/131376#131417 · In reply to: #131409

Hi

Am 2026-06-19 18:17, schrieb Larry Garfield:
> My main suggestions would be for more constructors, though I'm sure 
> that's going to get a response of "MVP, add later." :-P

Well, you would need to explain what constructors you are missing out 
on. If it's something “obviously correct and we are not going to regret 
it” I wouldn't necessarily rule out adding them straight away. But 
otherwise your suspicion would be correct.

> My main pushback, I think, is the fromIso8601String() method, which is 
> not at all self-descriptive.  Presuming it means the format accepted by 
> DatePeriod (give or take bugs), that's not self-evident anywhere in the 
> RFC, or the method name.

The doc comment for the method explains “Parse a ISO-8601 period.” and 
even the automated AI summary in Google (almost) correctly tells right 
away “An ISO-8601 period (or duration) represents an amount of time 
using the format P[n]Y[n]M[n]W[n]T[n]H[n]M[n]S.” There is a small 
mistake in there in that `T` doesn't have a preceding `[n]`, but it 
gives the correct idea of what is being expected there. And of course 
all the search results point towards the same thing.

>  I can easily see people who aren't familiar with that period format 
> (which is, I suspect, most people) trying to use "5:23:44" or similar 
> human time formats instead, which will break.  But that format actually 
> feels more useful, and is also defined somewhere in ISO8601 (as part of 
> the full date/time string if nothing else), so the method name is 
> ambiguous.

“break” is a strong word there. It will be rejected with a `ValueError` 
as an invalid input.

> I think we do need to come up with a better, more self-documenting name 
> for that operation, and consider if we also want a 
> fromHumanTimeString() that accepts "5:23"44" type strings.

Without checking with Derick, I would be open to renaming the method to 
`fromIso8601PeriodString()`. While that would be quite long, (fuzzy) 
auto-completion should handle that. And I suspect that constructor would 
also be used comparatively rarely.

If that name makes sense to you, I'll discuss all the feedback (also 
from the other mails) that I didn't outright reject myself with Derick 
in bulk in the next days :-)

The “from human time” one I would reject outright, because of the 
ambiguity with regard to how fractional seconds are represented. In the 
wild I've sometime seen `.` as the separator between seconds and 
fractional seconds, but also `:`, which means that the format would be 
ambiguous. And I'm sure there are also going to be differences between 
languages, just like some countries use 24h formats and others use 12h. 
And then of course, what even is a “human time”. And with regard to the 
flexibility in inputs that `strtotime()` accepts, is `"12 hours and 45 
seconds"` a “human time”? Is `"12.5h"` a “human time”? Is `"500µs"` a 
“human time” (notably the µ character is not in 7-bit ASCII)?

Best regards
Tim Düsterhus

---

## #131418 — tim@bastelstu.be — 2026-06-20T11:01:20+00:00

URL: https://externals.io/message/131376#131418 · In reply to: #131401

Hi

Am 2026-06-19 12:25, schrieb ignace nyamagana butera:
> However, I would advise against introducing Duration::add and 
> Duration::sub
> methods. Instead, I would recommend providing a single method,
> Duration::sum(Duration
> ...$durations): self.
> 
> Given that a Duration already carries a sign and may therefore be 
> either
> positive or negative, the presence of separate add and sub methods 
> could
> create an implicit and potentially misleading notion of directional
> behavior.
> 
> In contrast, a sum method using variadic arguments would allow multiple
> Duration instances to be combined in a natural and consistent manner. 
> It
> would also avoid implying any expectation regarding the resulting sign,
> which may legitimately be either positive or negative depending on the
> input values.

Can you clarify if you expect the `sum()` method to be a static method 
or an instance method? If it's a static method, what would you expect 
`Duration::sum()` (with an empty list of durations) to result in? Should 
it be an Error, `Duration::fromSeconds(0)`, or perhaps something 
entirely different?

Best regards
Tim Düsterhus

PS: Please don't forget to reply below the quoted parts; and to cut the 
quoted parts to the relevant portion.

---

## #131419 — tim@bastelstu.be — 2026-06-20T11:40:04+00:00

URL: https://externals.io/message/131376#131419 · In reply to: #131410

Hi

Am 2026-06-19 18:26, schrieb Marc B.:
> 1. Why `seconds` is always positive with separate `negative` boolean? I 
> don't get the reason behind that logic and it puts additional effort on 
> the user reading these values. A negative Duration should just be 
> negative seconds. Nanoseconds on the other hand should always between 0 
> and 999_999_999.

This is answered in the “design considerations” section of the RFC. Did 
you miss that one? With regard to your specific suggestion of only the 
seconds should be negative: How do you represent a Duration of negative 
0.5 seconds then?

> 2. fromIso8601String should just be fromIso8601. The name implies a 
> string already and the argument type defines it as well.

See my sibling reply to Larry with regard a possible rename. With regard 
to the `String` suffix specifically. I find it important for several 
reasons:

- Horizontal consistency with `Dom\HTMLDocument::createFromString()` 
(which also has `createFromFile()` with an identical signature).
- The lack of method overloading. There could possibly be an ISO-8601 
object that might require a slightly different signature so that a 
simple union type is insufficient.
- Just “from ISO-8601” sounds like an incomplete sentence (and “from 
ISO-8601 period” does as well). I would add the “string” part in my 
spoken communication as well, so I feel it should also be there in the 
method name.

> 3. fromSeconds is the only initiator with a second nanoseconds 
> argument. That feels a bit inconsistent from consistency POV.

See “design considerations”.

> Also, it's not just applying these values because, to be valid, there 
> needs to be some calculation be done.

This is incorrect, as demonstrated by the proof-of-concept userland 
implementation.

> 4. You have some operator methods defined (+add, -sum, /multiplyBy, 
> <>=compare, what about other operators?

What are you looking for?

> 5. Did you thought of supporting float on the initializer methods?

See the sub-thread started by Seifeddine.

> 6. You should at least mention that this class works with a fixed 
> definition of e.g. how long a minute is - no leaps tz handling here. 
> Which is the correct approach for it.

I believe the “Introduction” section (and the non-normative userland 
implementation) was pretty clear on that the class represents 
“stop-watch time”, not something related to clocks. But for completeness 
I have just added a PHPDoc comment to that effect to the class itself 
(in addition to the existing PHPDoc on the methods).

> 7. Naming consistency ... add/sub vs. multiplyBy. Why not 
> addBy/sub[tract]By or multiply to be more consistent?

I don't think “add by” and “sub(tract) by” is correct grammar. The `By` 
on `divideBy` was a deliberate choice to make it clear that the Duration 
is the dividend and the given integer is the divisor, because this isn't 
entirely clear using use `divide`. For multiplication as the inverse of 
division we added it for consistency (even though it doesn't matter 
there, because multiplication is commutative).

This also roughly matches Java's naming of `multipliedBy` / `dividedBy` 
and `plus` / `minus`.

> 8. negative vs. isNegative

Please provide a concrete suggestion.

> 9. negate() I would expect to get back a negative Duration. Also, it 
> sounds like modifying the duration but I'm assuming a new instance gets 
> returned. What about inverted()?

The class is `readonly`, so yes, a new instance gets returned. 
`negated()` is also something I thought of, which would also work with 
`multipliedBy()` and `dividedBy()` as in Java, but (as not a native 
speaker of English) I believe this naming pattern breaks down for the 
addition / subtraction. Ignace's suggestion of just having `sum()` might 
solve this, though.

> 10. On assuming the duration is immutable. Does the medifier function 
> still return the same object for the same resulting durations?

I don't understand the question.

> I have spend quite some time experimenting with building a good 
> date/time API matching PHP. What I came up with went into an 
> experimental but already working library in PHP without using the 
> available date/calendar extension.
> <https://github.com/marc-mabe/php-timelib>

Yes, that repository is referenced in the backwards incompatible changes 
section.

Best regards
Tim Düsterhus

---

## #131420 — ignace nyamagana butera — 2026-06-20T11:45:15+00:00

URL: https://externals.io/message/131376#131420 · In reply to: #131418

> Hi
>
> Am 2026-06-19 12:25, schrieb ignace nyamagana butera:
> > […]
>
> Can you clarify if you expect the `sum()` method to be a static method
> or an instance method? If it's a static method, what would you expect
> `Duration::sum()` (with an empty list of durations) to result in? Should
> it be an Error, `Duration::fromSeconds(0)`, or perhaps something
> entirely different?
>
> Best regards
> Tim Düsterhus
>
> PS: Please don't forget to reply below the quoted parts; and to cut the
> quoted parts to the relevant portion.
>

Hi Tim,

I would make the method static and if no argument is given I would expect
an ArgumentCountError to be thrown just like with array_sum.

Best regards,
Ignace

---

## #131421 — tim@bastelstu.be — 2026-06-20T11:47:34+00:00

URL: https://externals.io/message/131376#131421 · In reply to: #131412

Hi

Am 2026-06-19 18:35, schrieb Larry Garfield:
> What would those be?  Personally I'd want to see operators for add and 
> sub, at least, but I'm not sure what else would be useful.

I find the current behavior of operator overloading very unintuitive, 
because there is no obvious way of defining an expected signature, it's 
not in the stub, and if the overloaded operator throws, the stack trace 
will not provide any indication to what has happened either, see:

     php > var_dump(new GMP(5) + new stdClass());
     PHP Warning:  Uncaught TypeError: Number must be of type 
GMP|string|int, stdClass given in php shell code:1
     Stack trace:
     #0 {main}
       thrown in php shell code on line 1


I believe the overloaded comparison handler is a reasonable 
middle-ground and I wouldn't necessarily be against adding the other 
overloads when the entire user-story is better. But 
`Duration::fromSeconds(5) + 6` throwing with a `TypeError` (Duration + 
int is not meaningful) without being able to look up which operations 
are supported is not helping anyone.

> > […]
> 
> I concur here.

See my reply to Marc.

> > […]
> 
> Good point.  negated() would be fine, I think.  (As noted elsewhere, 
> `sort()` vs sorted() is a very common pattern for "modify in place" vs. 
> "make new", across a number of languages.)

See my reply to Marc.

Best regards
Tim Düsterhus

---

## #131422 — tim@bastelstu.be — 2026-06-20T11:52:16+00:00

URL: https://externals.io/message/131376#131422 · In reply to: #131420

Hi

Am 2026-06-20 13:45, schrieb ignace nyamagana butera:
> if no argument is given I would expect
> an ArgumentCountError to be thrown just like with array_sum.

This statement is not accurate (it's also not a recent change: 
https://3v4l.org/Ia8Mc#v):

     php > var_dump(array_sum([]));
     int(0)

But following the implied argument, `Duration::fromSeconds(0)` would be 
the expected answer. I'll discuss this with Derick.

Best regards
Tim Düsterhus

---

## #131423 — tim@bastelstu.be — 2026-06-20T12:00:53+00:00

URL: https://externals.io/message/131376#131423 · In reply to: #131413

Hi

Am 2026-06-19 19:12, schrieb Marc B.:
> Omg, I wrote in a wrong way - sorry.
> I mean the RFC just mentions "The Time\Duration class will also 
> implement internal “comparison handlers”, which means that direct 
> comparisons with operators such as < will work".
> So there are no other operators defined but there are methods defined 
> for it. I would expect these defined as operators as well.

See my reply to Larry.

> Actually, for the division, there are two use cases but the method 
> supports only one.
> 6s / 2 = 3s
> 6s / 2s = 3

This is a good point, though. While we're probably not going to 
implement Duration/Duration from the start, we should account for that 
in the naming of the Duration/int method. Do you have any suggestions? 
Rust’s std::time::Duration calls these `div_duration_<variant>`. Java 
doesn't have it, but could technically just use method overloading. And 
in Golang it will just implicitly work, because `time.Duration` there is 
just a 64-bit integer without any “unit”.

To support Duration/Duration->int it would also be necessary to restrict 
the entire range to a signed 64-bit integer of nanoseconds, because 
overwise `Duration/Duration->int` might overflow on 64-bit systems. This 
is already something I considered doing based on off-list feedback I've 
received (and lifting this restrictions later is always possible, so 
better play safe). I'll discuss this with Derick. We'll also need to 
define the overflow behavior in general (e.g. 
`Duration::fromHours(PHP_INT_MAX)->multiplyBy(PHP_INT_MAX)`).

> > […]
> 
> If you have a float at hand you already have the lack of precision. 
> Forcing the user to cast to int before does not make anything better. 
> It's even another source of complexity the user have to deal with. If 
> this gets handled on the initializer it will reduce the complexity for 
> the user.

See my reply to Larry and Seifeddine.

Best regards
Tim Düsterhus

---

## #131431 — ignace nyamagana butera — 2026-06-20T15:50:32+00:00

URL: https://externals.io/message/131376#131431 · In reply to: #131413

>
>
> Omg, I wrote in a wrong way - sorry.
> I mean the RFC just mentions "The Time\Duration class will also implement
> internal “comparison handlers”, which means that direct comparisons with
> operators such as < will work".
> So there are no other operators defined but there are methods defined for
> it. I would expect these defined as operators as well.
>
> Actually, for the division, there are two use cases but the method
> supports only one.
> 6s / 2 = 3s
> 6s / 2s = 3
>
>
 Hi Tim and Marc

I would go with two methods if possible :

Duration::countOf(Duration $duration): int;  // which would act a bit like
intdiv
Duration::remainder(Duration $duration): Duration;  // which would return
the remainder as a Duration instance

But that's just a thought.

Also why are there some restrictions on the factor argument of divideBy and
multiplyBy to only accept positive integers ?
At least that is what I understood when I quickly checked the proof of
concept. Since Duration are signed instances that restriction seems strange
?

Best regards,
Ignace

---

## #131435 — Morgan — 2026-06-20T23:31:25+00:00

URL: https://externals.io/message/131376#131435 · In reply to: #131431

> 
> Hi Tim and Marc
> 
> I would go with two methods if possible :
> 
> Duration::countOf(Duration $duration): int;  // which would act a bit 
> like intdiv
> Duration::remainder(Duration $duration): Duration;  // which would 
> return the remainder as a Duration instance
> 
> But that's just a thought.
> 

And BCMath just recently picked up a function to do both of those in a 
single call, since calculating one gives you the other for free and 
frequently users want both.

---

## #131436 — ignace nyamagana butera — 2026-06-21T09:18:04+00:00

URL: https://externals.io/message/131376#131436 · In reply to: #131435

Le dim. 21 juin 2026, 01:34, Morgan <weedpacket@varteg.nz> a écrit :

> 
> > […]
>
> And BCMath just recently picked up a function to do both of those in a
> single call, since calculating one gives you the other for free and
> frequently users want both.
>

Indeed Duration::divmod is the way forward just wondering about  the return
type. Should it be an array or a immutable DTO with .2 properties quotient
and remainder?

Best regards,
Ignace

---

## #131437 — tim@bastelstu.be — 2026-06-21T13:52:23+00:00

URL: https://externals.io/message/131376#131437 · In reply to: #131431

Hi


> Also why are there some restrictions on the factor argument of divideBy and
> multiplyBy to only accept positive integers ?
> At least that is what I understood when I quickly checked the proof of
> concept. Since Duration are signed instances that restriction seems strange
> ?

Enforcing positive values for multiplication and division means that 
flipping the sign of a Duration is a deliberate action and not just 
something that happens as part of another operation.

See also the last paragraph in the “Design considerations” section.

Best regards
Tim Düsterhus

---

Next page: https://externals.io/message/131376.md?page=2
