Document that DateInterval addition depends on how the interval was created - #5830
Merged
Merged
Conversation
lacatoire
force-pushed
the
doc/dateinterval-wall-civil
branch
from
September 3, 2026 12:52
342a0e1 to
777ba7a
Compare
An example, a variablelist or a simplelist that is alone in a para should be a direct child of its container.
DateTimeImmutable::add and DateTime::add apply an interval in one of two
ways, picked from how the interval was created rather than from what it
holds:
new DateInterval('PT24H') -> elapsed time
DateInterval::createFromDateString('24 hours') -> component values
DateTimeInterface::diff() -> component values
The two agree on any ordinary day and differ by an hour across a DST
transition, which is not documented anywhere. The example on the
DateInterval::createFromDateString page stated the opposite outright
("Each set of intervals is equal.").
Add a third example to the Date/Time Arithmetic page contrasting the two,
state the rule on the DateInterval class page, note it where the equality
was claimed, and link the arithmetic page from
DateTimeImmutable::add/sub.
Output verified on PHP 8.5.4.
lacatoire
force-pushed
the
doc/dateinterval-wall-civil
branch
from
September 3, 2026 12:59
777ba7a to
261bbc4
Compare
Only the time part of an interval (hours, minutes, seconds, microseconds) is applied as elapsed time when the interval comes from DateInterval::__construct. The date part goes through the same calendar arithmetic in both cases, so P1D and '1 day' never diverge: 2015-11-01 00:00:00 -04:00 America/New_York + P1D -> 2015-11-02 00:00:00 -05:00 + 1 day -> 2015-11-02 00:00:00 -05:00 Over 400 days of hourly start times, PT24H and '24 hours' diverge 46 times while P1D and '1 day' never do. Of the seven sets listed in the first createFromDateString example, only the two carrying a time part can diverge at all.
DateInterval has no week component: new DateInterval('P1W') yields d=7,
and property_exists($i, 'w') is false.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #5653
DateTimeImmutable::add()applies the time part of an interval, that is hours, minutes, seconds and microseconds, in one of two ways, and it picks based on how the interval was created rather than on what the interval holds:new DateInterval('PT24H')DateInterval::createFromDateString('24 hours')modify()DateTimeInterface::diff()The date part, that is years, months and days, always increments or decrements the individual component values, whichever way the interval was created:
P1Dand'1 day'never diverge. The two therefore only give a different result when a timezone transition falls within the time part,PT24Hversus'24 hours'across a DST transition being the canonical case.Nothing documented this, and the first example on the
DateInterval::createFromDateStringpage claimed the opposite ("Each set of intervals is equal."), for sets that mostly cannot diverge at all.The first commit unwraps the examples and lists of the two files it touches from their surrounding
para; the others are the change itself. Example output verified on PHP 8.5.4.Sources (line numbers as of php-src
3c6a57189e):add()/sub()branch oncivil_or_wall:ext/date/php_date.c:3432and:3497DateInterval::__constructsetsPHP_DATE_WALL:ext/date/php_date.c:4646DateInterval::createFromDateStringsetsPHP_DATE_CIVIL:ext/date/php_date.c:4890DateTimeInterface::diffsetsPHP_DATE_CIVIL:ext/date/php_date.c:4021h/i/s/usare added tossein wall mode,y/m/dgo through the sametimelib_update_tsas in civil mode:ext/date/lib/interval.c,timelib_add_wallversustimelib_add