Search code examples
phpphp-carbon

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?


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.