Skip to content

DateInterval month durations not accounting for calendar month days #18203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
roborourke opened this issue Mar 31, 2025 · 2 comments
Closed

DateInterval month durations not accounting for calendar month days #18203

roborourke opened this issue Mar 31, 2025 · 2 comments

Comments

@roborourke
Copy link

roborourke commented Mar 31, 2025

Description

The following code:

<?php
$og = new DateTime(date('2025-03-31'));
$d = clone( $og );
$one_month = new DateInterval('P1M');
$next_month = $d->add($one_month);

echo "Start Date: " . $og->format('Y-m-d') . "\n";
echo "Next Month: " . $next_month->format('Y-m-d');

Resulted in this output:

Start Date: 2025-03-31
Next Month: 2025-05-01

But I expected this output instead:

Start Date: 2025-03-31
Next Month: 2025-04-30

For comparison in JS Temporal:

> now = Temporal.Now.zonedDateTimeISO()
> now.toString()
"2025-03-31T14:19:39.108140159+01:00[Europe/London]"
> now.add('P1M').toString()
"2025-04-30T14:19:39.108140159+01:00[Europe/London]" 

Month durations / interval modifications should be able to account for calendar days per ISO 8601 and consistently change the month only without carrying excess days over and returning a date in the following month.

In the ISO8601 spec:

month
duration of 28, 29, 30 or 31 calendar days depending on the start and/or the end of the corresponding time
interval within the specific calendar month
NOTE 1 The term “month” applies also to the duration of any time interval which starts at a certain time of day at a
certain calendar day of the calendar month and ends at the same time of day at the same calendar day of the next
calendar month, if it exists. In other cases the ending calendar day has to be agreed on.
NOTE 2 In certain applications a month is considered as a duration of 30 calendar days.

PHP Version

8.4.5

Operating System

No response

@heiglandreas
Copy link
Contributor

Yes. This is a know problem of the logic you try to apply.

If you want to add one month to the 31st of January: Where do you end up?

31.01.2025 plus 1 month is 31.02.2025. Which then brings you to the problem that that day doesn't exist.

So how do you handle that?

  • Throw an exception?
  • Convert that to the 28th Feb plus 3 days => 3rd of March
  • Convert that to the 28th of Februar... Wait! that is not adding a Month! That is adding 28 days!

Adding the overflowing days to the following month is the only sensible and logical way to handle this case.

If you want the last day of the following month (instead of adding one month) do something like

$og = new DateTime(date('2025-03-31'));
$og->modify(`last day of next month`);

https://3v4l.org/YPUFa

@derickr
Copy link
Member

derickr commented Apr 10, 2025

This is as expected, and also documented, so I'm closing this.

@derickr derickr closed this as completed Apr 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants