Skip to content

Return ChronosInterval from Chronos::diff()#515

Open
dereuromark wants to merge 3 commits into4.xfrom
diff-returns-interval
Open

Return ChronosInterval from Chronos::diff()#515
dereuromark wants to merge 3 commits into4.xfrom
diff-returns-interval

Conversation

@dereuromark
Copy link
Member

@dereuromark dereuromark commented Mar 26, 2026

Summary

  • Changes Chronos::diff() and ChronosDate::diff() to return ChronosInterval instead of DateInterval
  • Adds the ChronosInterval class (merged from 3.x branch)
  • Updates fromNow() to return ChronosInterval

This provides:

  • ISO 8601 duration formatting via __toString()
  • Convenience methods like totalSeconds(), totalDays(), isZero(), isNegative()
  • Arithmetic methods add(), sub()
  • toDateString() for strtotime-compatible output
  • toNative() for backwards compatibility when a DateInterval is needed

Migration Path

Users who need a DateInterval can call ->toNative() on the result:

// Before (3.x)
$interval = $date1->diff($date2);

// After (4.x) - if DateInterval is needed
$interval = $date1->diff($date2)->toNative();

// After (4.x) - using new features
$interval = $date1->diff($date2);
echo $interval; // "P1Y2M3D"
echo $interval->totalDays();

Note

Good news: No changes required in CakePHP core!

PHPStan reports an error about covariant return types - this is expected for this BC break. The baseline will need to be updated.

Closes #511

@dereuromark
Copy link
Member Author

dereuromark commented Mar 26, 2026

For downstream users:

Anyone using $chronos->diff() with type hints will need updates:

// If they have:                                                                                                   
function process(DateInterval $interval) { ... }                                                                   
                                                                                                                     
// They need:                                                                                                      
function process(DateInterval|ChronosInterval $interval) { ... }                                                   
// Or:                                                                                                             
$date->diff($other)->toNative()  // to get DateInterval                                                            

CI Status

All 954 tests pass. The CI failures are due to:

  1. PHPStan - Expected error about covariant return type:

    Return type ChronosInterval of method Chronos::diff() is not covariant with tentative return type DateInterval of method DateTimeInterface::diff()

  2. PHPUnit (PHP 8.3+) - The repo has failOnDeprecation="true" in phpunit.xml.dist, so the PHP deprecation notice about incompatible return types causes tests to fail even though they all pass.

Both issues are expected for this BC break. We will need to decide how to handle:

  • Update phpstan.neon to ignore this specific error
  • Either update phpunit.xml.dist or add baseline for the deprecation

This changes Chronos::diff() and ChronosDate::diff() to return
ChronosInterval instead of DateInterval. This provides:

- ISO 8601 duration formatting via __toString()
- Convenience methods like totalSeconds(), totalDays(), isZero(), isNegative()
- Arithmetic methods add(), sub()
- toDateString() for strtotime-compatible output
- toNative() for backwards compatibility when DateInterval is needed

Users who need a DateInterval can call ->toNative() on the result.

Also updates fromNow() to return ChronosInterval.

Closes #511
Suppress PHP deprecation notice and PHPStan errors for the
intentional return type change from DateInterval to ChronosInterval.
@dereuromark dereuromark force-pushed the diff-returns-interval branch from 15c25e2 to 556c707 Compare March 26, 2026 14:04
@dereuromark dereuromark marked this pull request as ready for review March 26, 2026 14:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant