Re: [RFC] Duration class

From: Date: Mon, 22 Jun 2026 17:25:53 +0000
Subject: Re: [RFC] Duration class
References: 1 2 3 4 5 6 7 8  Groups: php.internals 
Request: Send a blank email to internals+get-131469@lists.php.net to get a copy of this message
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

« previous php.internals (#131469) next »