Re: [RFC] Duration class

From: Date: Mon, 22 Jun 2026 18:08:29 +0000
Subject: Re: [RFC] Duration class
References: 1 2 3 4 5 6 7 8 9  Groups: php.internals 
Request: Send a blank email to internals+get-131472@lists.php.net to get a copy of this message
On Mon, Jun 22, 2026, at 12:25 PM, Tim Düsterhus wrote: > Hi > > Am 2026-06-22 17:11, schrieb ignace nyamagana butera: >> I concur with Marc remarks especially if we want to add a divmod like >> method this simple example shows the issue one would run into with the >> current constraints. >> >> $duration = Duration::fromHours(3)->negate(); >> >> $factor = Duration::fromHours(1); >> [$count, $remainder] = $duration->divmod($factor); >> // using BCMath implementation for the example ! >> //[-3, Duration::fromSeconds(0)] is returned in the tuple >> >> Duration::sum( >> $factor->multiplyBy($count), // with the current constraints this >> will throw >> $remainder, >> ); > > I would personally find [3, Duration::fromSeconds(0)] (i.e. ignoring the > sign) to be a reasonable reply to the question “how often can I fit this > duration into the other duration”. > > In fact the output of a divmod() would be very confusing when > the > divisor doesn't divide the dividend, since the result of the modulo > operator is always positive (see also: > https://stackoverflow.com/a/13683709): > > $duration = Duration::fromMinutes(3 * 60 + 20)->negate(); // > negative 3:20 hours > $factor = Duration::fromMinutes(60); // 1 hour > > $duration->divmod($factor); > // [-4, Duration::fromMinutes(40)] = (-4 * 60 minutes) + 40 minutes > = negative 3:20 hours > > A divrem() (“remainder”) would be: > > $duration = Duration::fromMinutes(3 * 60 + 20)->negate(); // > negative 3:10 hours > $factor = Duration::fromMinutes(60); // 1 hour > > $duration->divrem($factor); > // [-3, Duration::fromMinutes(20)->negate()] = (-3 * 60 minutes) - > 20 minutes = negative 3:20 hours > > In my opinion, implementing "Duration divided by Duration" as a > remainder operation is the only reasonable choice here and “ignoring the > sign” to avoid the entire “modulo vs remainder” discussion would be > reasonable when the method is appropriately named. > > Staying with the IEEE-754 comparison for the sign-magnitude > representation, I could also imagine adding a “copysign” method matching > the copysign() function > (https://man7.org/linux/man-pages/man3/copysign.3.html). > > The example would then be: > > Duration::sum($factor->multiplyBy($count), > $remainder)->copysign($duration); > > If we feel that the “Duration divided by Duration” *should* be able to > return negative values, then lifting the >= 0 restriction of > > multiplyBy() would also easily be possible. > > Best regards > Tim Düsterhus To be clear, I absolutely hate using a static method here. Even if we're just using methods and not operators, $dur3 = $dur1->add($dur2) is the way to go. --Larry Garfield

« previous php.internals (#131472) next »