php - Carbon Objects diffInMonths showing 0 when one date is 1st Nov and the other 1st Dec

I have two carbon objects

//$startDate
Carbon\Carbon @1667250000 {#3093 ?�?
  date: 2022-11-01 00:00:00.0 Africa/Nairobi (+03:00)
}

and

//$endDate
Carbon\Carbon @1669842000 {#2920 ?�?
  date: 2022-12-01 00:00:00.0 Africa/Nairobi (+03:00)
}

when I run dateDiffInMonths() on them I get 0 but I expect 1

$startDate->diffInMonths($endDate); //0

I have tried adding floorMonth() to objects but the answer is still the same.

When I get $startDate->diff($endDate) I get the following with days difference as 30

DateInterval {#3102 ?�?
  interval: + 30d
  +"y": 0
  +"m": 0
  +"d": 30
  +"h": 0
  +"i": 0
  +"s": 0
  +"f": 0.0
}

What am I doing wrong?

Answer

Solution:

There are always bugs with DateTime in various PHP versions. These also affect carbon. I've been using this algorithm for years (from https://github.com/jspit-de/dt/blob/master/Dt.php#L1284):

function diffInMonth(DateTime $start,DateTime $end): int {
  $endDate = (clone $end)->setTimeZone($start->getTimeZone());
  list($yearStart,$monthStart,$dayStart) = explode(" ",$start->format("Y m dHis"));
  list($yearEnd,$monthEnd, $dayEnd) = explode(" ",$endDate->format("Y m dHis"));
  $mothDiff = ($yearEnd - $yearStart) * 12 + $monthEnd - $monthStart;
  if($dayStart > $dayEnd && $end >= $start) --$mothDiff;
  elseif($dayStart < $dayEnd && $end < $start) ++$mothDiff;
  return $mothDiff;
}

$startDate = new DateTime('2022-11-01 00:00:00.0', new DateTimeZone('Africa/Nairobi'));
$endDate = new DateTime('2022-12-01 00:00:00.0',  new DateTimeZone('Africa/Nairobi'));

$month = diffInMonth($startDate, $endDate);
echo ' Positve: '.$month."\n";  //1

$month = diffInMonth($endDate,$startDate);
echo " Negative: ".$month;  //-1

Demo + Test: https://3v4l.org/Tgqcf

This function works the same way with carbon objects.

Source