-4

I have the following code that is returning an unexpected answer. Please let me know what's wrong.

$start_date  = new DateTime('31-03-2019');
$end_date    = new DateTime('01-05-2019');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";

It is returning the following output:

day: 0 month: 1

I expect the output to be:

day: 1 month: 1
Wulf
  • 3,878
  • 2
  • 22
  • 36
moeseth
  • 1,855
  • 5
  • 23
  • 47
  • Not sure but 1 month seems correct? Where do you want to get that 1 day from – Tomm Mar 01 '19 at 13:49
  • 1
    01-05-2019 ...is that 1st May or 5th Jan? I ask this regardless of the result you're seeing: it's always better to supply unambiguous date strings to avoid confusion (not least on the part of the computer which is trying to process it). (P.S.I realise it's probably 1st May since the date above it is clearly in dd/mm/yyyy format but the computer won't take that into account) – ADyson Mar 01 '19 at 13:49
  • 3
    When you add 1 month to `2019-03-31` (=increment the month number), you would get the `2019-04-31`. As April has only 30 days, `2019-04-31` is the same representation as `2019-05-01`. So you have to add exactly 1 month (and 0 days) to your initial date to get the target date. – Wulf Mar 01 '19 at 13:52
  • 2
    The problem is there's no clear definition of a month. There's some internal definition PHP uses to come up with the month number, but it's wishy-washy. It's not simply the difference between `03` and `05`, 'cause that'd be `2`, and it also doesn't really help if it's from the middle of February to middle of April; is that more or less than two months if February is short…? So, if you want to figure out a difference in months, you better use your own calculations that match what you expect. Or it's better to simply not try to find such a badly defined number in the first place. – deceze Mar 01 '19 at 13:54

2 Answers2

0

This will give you one day and one month https://3v4l.org/q0T8r

$start_date  = new DateTime('31-03-2019 00:00:00');
$end_date    = new DateTime('01-05-2019 24:00:00');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";
Andrei Lupuleasa
  • 2,677
  • 3
  • 14
  • 32
0

When you add 1 month to 2019-03-31, PHP will internally just increment the month value 03 to 04. The result is 2019-04-31.

As April has only 30 days, 2019-04-31 has the same meaning as 2019-05-01 has. And that's the reason, why you get one month and zero days as the result.


The DateInterval class has another handy property: days instead of m and d. It will contain the total number of days between the two dates, which equals to 31 (you have to add 31 days to 2019-03-31 to get to the 2019-05-01.

On this value you can implement your own logic, what "one month" is. If you define it as "one month = 30 days", this could be your whished result:

$start_date  = new DateTime('31-03-2019');
$end_date    = new DateTime('01-05-2019');
$diff = $start_date->diff($end_date);

$months = floor($diff->days / 30);
$days = $diff->days % 30;

echo "day: " . $days . " month: " . $months . "\n";
Wulf
  • 3,878
  • 2
  • 22
  • 36