Skip to content

feat(duration): build a duration from a native DateInterval - #151

Merged
CodeLieutenant merged 1 commit into
trunkfrom
feat/duration-from-dateinterval
Aug 9, 2026
Merged

feat(duration): build a duration from a native DateInterval#151
CodeLieutenant merged 1 commit into
trunkfrom
feat/duration-from-dateinterval

Conversation

@CodeLieutenant

Copy link
Copy Markdown
Member

What

Cassandra\Duration now accepts PHP's native DateInterval.

$d = new Cassandra\Duration(new DateInterval('P1M15D'));
$d = Cassandra\Duration::fromDateInterval((new DateTime('2020-01-01'))->diff(new DateTime()));

Why

The class took three numeric arguments only. A caller who already had a DateInterval — from DateTime::diff(), from Carbon, from a config value — had to split it into months, days, and nanoseconds by hand and get the calendar arithmetic right.

Note: PHP has no Duration class. DateInterval is the native type for this.

Mapping

DateInterval Duration
y, m months = y * 12 + m
d days
h, i, s, f nanos
invert negates all three parts

f holds microseconds, so the last three digits of nanos() are always zero.

Rules

  • A DateInterval must be the only argument. Passing it with $days/$nanos throws InvalidArgumentException, because the other two values would be discarded.
  • The numeric form still requires all three arguments. A short call throws ArgumentCountError. The stub marks arguments 2 and 3 as optional to allow the one-argument form, so this check moved from arginfo into the constructor.
  • An interval outside the CQL range is rejected. months and days are 32 bit, nanos is 64 bit. Every intermediate product is checked for overflow.
  • An uninitialized DateInterval is rejected.
  • DateInterval subclasses work, Carbon\CarbonInterval included.

Changes

  • src/DateTime/Duration.stub.php, src/DateTime/Duration.c
  • tests/Unit/DurationTest.php — 16 new cases
  • docs/Cassandra/Duration.php, website/reference/values.md, website/guide/data-types.md

Test

php -d extension=out/DebugPHP8.4NTS/cassandra.dylib ./vendor/bin/pest tests/Unit/
Tests: 1 warning, 28 skipped, 849 passed (12157 assertions)

Not in this change

toDateInterval(). The reverse direction loses precision below microseconds and needs its own decision about what to do with the remainder.

Duration accepted only three numeric arguments. A caller that already has
a DateInterval had to split it into months, days and nanoseconds by hand.

The constructor now accepts a DateInterval as its only argument, and
Duration::fromDateInterval() does the same as a named factory. Years fold
into months, hours and smaller parts fold into nanoseconds, and an
inverted interval gives a negative duration.

A DateInterval together with the other two arguments throws
InvalidArgumentException. Three arguments stay mandatory for the numeric
form, so a short call throws ArgumentCountError.

The conversion rejects an interval that does not fit in the CQL duration
range. Months and days are 32 bit and nanoseconds are 64 bit.
@mergify

mergify Bot commented Aug 9, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@CodeLieutenant CodeLieutenant self-assigned this Aug 9, 2026
@CodeLieutenant
CodeLieutenant merged commit 1f9ec6a into trunk Aug 9, 2026
35 checks passed
@CodeLieutenant
CodeLieutenant deleted the feat/duration-from-dateinterval branch August 9, 2026 23:42
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