The Duration Class RFC has been accepted for PHP 8.6. It adds a Time\Duration class. Since 4.x introduces ChronosInterval as a new public API, it is worth deciding now how the two relate, while nothing is released yet.
There is no direct conflict
Time\Duration lives in a new Time\ namespace, models exact elapsed time only (int $seconds + int $nanoseconds + bool $negative), and rejects ISO 8601 duration strings with a date component ("The biggest allowed component is H"). ChronosInterval decorates the native DateInterval and covers full calendar units.
More importantly, the RFC changes nothing on the existing classes: no new DateTimeImmutable::diff() return type, no changes to DateInterval. So Chronos::diff(), ChronosDate::diff() and Chronos::fromNow() returning ChronosInterval in 4.x remain valid on PHP 8.6. No class-name clash, no signature clash.
The RFC's Future Scope does say that "Calculating the difference between two points in time ('Instant') will return a Time\Duration object", and that calendar math above hours will get a dedicated class. That is a parallel Time\* API alongside DateTimeImmutable, so it does not affect Chronos today, but it is the direction of travel.
Three things worth deciding for 4.x
1. totalSeconds() hardcodes 30-day months and 365-day years
src/ChronosInterval.php:
public function totalSeconds(): int
{
$seconds = $this->interval->s;
$seconds += $this->interval->i * 60;
$seconds += $this->interval->h * 3600;
$seconds += $this->interval->d * 86400;
$seconds += $this->interval->m * 30 * 86400;
$seconds += $this->interval->y * 365 * 86400;
return $this->interval->invert ? -$seconds : $seconds;
}
This is exactly the ambiguity the RFC cites as its reason for restricting Duration to hours and below: days and larger units "cannot be unambiguously mapped into a fixed number of seconds due to daylight saving time and months having different lengths".
The docblock does disclose the approximation, but this is a brand new public method, and a silently wrong number is worse than no method. Options:
- Throw when
y or m are non-zero and days === false, so only unambiguous intervals answer.
- Drop the method and let callers diff two concrete dates.
- Keep as is, with the caveat documented more prominently than a docblock note.
totalDays() is fine when the interval came from diff() (it uses ->days); it only falls back to the approximation otherwise, and the same decision applies to that fallback.
2. Method naming versus the RFC
The RFC's secondary vote picked full names 30 to 2. Current overlap is only add() / sub(), which already match in name and semantics. The rest diverges:
Time\Duration |
ChronosInterval |
fromSeconds(), fromMinutes(), fromHours(), fromIso8601DurationString() |
create(), createFromValues(), createFromDateString() |
negate(), absolute(), multiplyBy(), divideBy(), compare() |
not present |
| no ISO 8601 output method |
toIso8601String() |
Keeping createFrom* is defensible since it matches DateTime::createFromFormat. But adding negate(), absolute(), multiplyBy(), divideBy() and a static compare() under the RFC's names is cheap, fills real gaps, and makes the mental model transfer once 8.6 lands. Worth doing before 4.0 is tagged, since adding them later is fine but renaming is not.
3. Interop, later
Nothing to implement yet, but eventually a toDuration() / fromDuration() pair could bridge the two, guarded by a PHP 8.6 version check. Only meaningful for intervals with no date component. Filing this as a note rather than a task.
Suggested outcome
Decide on point 1 before 4.0 is tagged (it is a correctness question, not a style one), optionally do point 2 in the same pass, and leave point 3 until PHP 8.6 is actually out.
The Duration Class RFC has been accepted for PHP 8.6. It adds a
Time\Durationclass. Since 4.x introducesChronosIntervalas a new public API, it is worth deciding now how the two relate, while nothing is released yet.There is no direct conflict
Time\Durationlives in a newTime\namespace, models exact elapsed time only (int $seconds+int $nanoseconds+bool $negative), and rejects ISO 8601 duration strings with a date component ("The biggest allowed component is H").ChronosIntervaldecorates the nativeDateIntervaland covers full calendar units.More importantly, the RFC changes nothing on the existing classes: no new
DateTimeImmutable::diff()return type, no changes toDateInterval. SoChronos::diff(),ChronosDate::diff()andChronos::fromNow()returningChronosIntervalin 4.x remain valid on PHP 8.6. No class-name clash, no signature clash.The RFC's Future Scope does say that "Calculating the difference between two points in time ('Instant') will return a
Time\Durationobject", and that calendar math above hours will get a dedicated class. That is a parallelTime\*API alongsideDateTimeImmutable, so it does not affect Chronos today, but it is the direction of travel.Three things worth deciding for 4.x
1.
totalSeconds()hardcodes 30-day months and 365-day yearssrc/ChronosInterval.php:This is exactly the ambiguity the RFC cites as its reason for restricting
Durationto hours and below: days and larger units "cannot be unambiguously mapped into a fixed number of seconds due to daylight saving time and months having different lengths".The docblock does disclose the approximation, but this is a brand new public method, and a silently wrong number is worse than no method. Options:
yormare non-zero anddays === false, so only unambiguous intervals answer.totalDays()is fine when the interval came fromdiff()(it uses->days); it only falls back to the approximation otherwise, and the same decision applies to that fallback.2. Method naming versus the RFC
The RFC's secondary vote picked full names 30 to 2. Current overlap is only
add()/sub(), which already match in name and semantics. The rest diverges:Time\DurationChronosIntervalfromSeconds(),fromMinutes(),fromHours(),fromIso8601DurationString()create(),createFromValues(),createFromDateString()negate(),absolute(),multiplyBy(),divideBy(),compare()toIso8601String()Keeping
createFrom*is defensible since it matchesDateTime::createFromFormat. But addingnegate(),absolute(),multiplyBy(),divideBy()and a staticcompare()under the RFC's names is cheap, fills real gaps, and makes the mental model transfer once 8.6 lands. Worth doing before 4.0 is tagged, since adding them later is fine but renaming is not.3. Interop, later
Nothing to implement yet, but eventually a
toDuration()/fromDuration()pair could bridge the two, guarded by a PHP 8.6 version check. Only meaningful for intervals with no date component. Filing this as a note rather than a task.Suggested outcome
Decide on point 1 before 4.0 is tagged (it is a correctness question, not a style one), optionally do point 2 in the same pass, and leave point 3 until PHP 8.6 is actually out.