On Wed, Jul 1, 2026, at 12:22 PM, Tim Düsterhus wrote: > Hi > > Am 2026-06-23 15:04, schrieb Tim Düsterhus: >> Both Derick and I were receptive to the `Duration::sum()` suggestion. >> >> One big benefit I am personally seeing is that it would allow to rename >> the `negate()`, `multiplyBy()`, and `divideBy()` methods to use “past >> tense” (is that the correct term?) to indicate that they return a copy, >> without requiring awkward naming like `added()`. `->sub()` is also >> technically redundant due to the existence of negative Durations, thus >> there is no need for a mirrored pair like multiplication / division, >> since the information can be encoded in the Duration object itself. >> >> To avoid readers making assumptions, can you spell out your arguments >> against replacing `->add()` and `->sub()` by a unified `::sum()` >> method? > > To close this out ourselves: While having a static `sum()` method works > for `Duration`s, since the Duration with addition forms an abelian > group, this doesn't work for the other future-scope classes where > addition doesn't form an (abelian) group. More specifically: Adding two > Instants together is not a meaningful operation. Adding a Duration to an > Instant however is. Using something like: > > $epoch = Instant::fromUnixtime(0); > $onePointFiveHoursLater = Instant::sum($epoch, > Duration::fromMinutes(30), Duration::fromHours(1)); > > would be very weird. Instead `->add()` is the obvious operation here: > > $epoch = Instant::fromUnixtime(0); > $onePointFiveHoursLater = $epoch > ->add(Duration::fromMinutes(30)) > ->add(Duration::fromHours(1)); > > notably this would also work then: > > $epoch = Instant::fromUnixtime(0); > $onePointFiveHoursLater = $epoch > ->add( > Duration::fromMinutes(30) > ->add(Duration::fromHours(1) > ); > > making the Instant + Duration -> Instant operation a “right group > action”.
How about that. Forgetting to respond to this thread meant you gave a good response for me. Thanks, Tim. :-) > We will thus keep instance methods for “addition” and “subtraction”. If > someone has a suggestion regarding naming (particularly with regard to > negate() vs negated() and multiplyBy() and multipliedBy()), I'll be > happy to discuss that. Java uses plus, minus, multipliedBy, dividedBy > and negated. Golang is just using an integer (meaning you just use the > operators). Rust’s std::time::Duration uses add, sub, mul, div (with > saturating and checked variants), but also overloads operators. Rust’s > chrono::TimeDelta is similar to std::time::Duration, but doesn't have > the saturating variants. JavaScript’s Temporal uses add, sub, negated > and doesn't support multiplication and division. > > Please keep the `divide**By**()` (Duration / int -> Duration) vs > `divide**Into**()` (Duration / Duration -> (int, Duration)) suggestion > in mind when having opinions about the naming. See: > https://news-web.php.net/php.internals/131634 negated() would be consistent with the "ed means return new" pattern found in many languages, so I would strongly recommend following that pattern. For the others, my inclination is to go short (add, sub) for easier typing and a more compact result, but that's not a make-or-break issue for me. --Larry Garfield
