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

Reply via email to