Elegant way to get the count of months between two dates?

PhpDate

Php Problem Overview


Let's assume I have two dates in variables, like

$date1 = "2009-09-01";
$date2 = "2010-05-01";

I need to get the count of months between $date2 and $date1($date2 >= $date1). I.e. i need to get 8.

Is there a way to get it by using date function, or I have to explode my strings and do required calculations?

Thanks.

Php Solutions


Solution 1 - Php

For PHP >= 5.3

$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-05-01");

var_dump($d1->diff($d2)->m); // int(4)
var_dump($d1->diff($d2)->m + ($d1->diff($d2)->y*12)); // int(8)

DateTime::diff returns a DateInterval object

If you don't run with PHP 5.3 or higher, I guess you'll have to use unix timestamps :

$d1 = "2009-09-01";
$d2 = "2010-05-01";

echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8

But it's not very precise (there isn't always 30 days per month).

Last thing : if those dates come from your database, then use your DBMS to do this job, not PHP.

Edit: This code should be more precise if you can't use DateTime::diff or your RDBMS :

$d1 = strtotime("2009-09-01");
$d2 = strtotime("2010-05-01");
$min_date = min($d1, $d2);
$max_date = max($d1, $d2);
$i = 0;

while (($min_date = strtotime("+1 MONTH", $min_date)) <= $max_date) {
    $i++;
}
echo $i; // 8

Solution 2 - Php

Or, if you want the procedural style:

$date1 = new DateTime("2009-09-01");
$date2 = new DateTime("2010-05-01");
$interval = date_diff($date1, $date2);
echo $interval->m + ($interval->y * 12) . ' months';

UPDATE: Added the bit of code to account for the years.

Solution 3 - Php

Or a simple calculation would give :

$numberOfMonths = abs((date('Y', $endDate) - date('Y', $startDate))*12 + (date('m', $endDate) - date('m', $startDate)))+1;

Accurate and works in all cases.

Solution 4 - Php

This is another way to get the number of months between two dates:

// Set dates
$dateIni = '2014-07-01';
$dateFin = '2016-07-01';

// Get year and month of initial date (From)
$yearIni = date("Y", strtotime($dateIni));
$monthIni = date("m", strtotime($dateIni));

// Get year an month of finish date (To)
$yearFin = date("Y", strtotime($dateFin));
$monthFin = date("m", strtotime($dateFin));
  
// Checking if both dates are some year

if ($yearIni == $yearFin) {
   $numberOfMonths = ($monthFin-$monthIni) + 1;
} else {
   $numberOfMonths = ((($yearFin - $yearIni) * 12) - $monthIni) + 1 + $monthFin;
}

Solution 5 - Php

I use this:

$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-09-01");
$months = 0;

$d1->add(new \DateInterval('P1M'));
while ($d1 <= $d2){
    $months ++;
    $d1->add(new \DateInterval('P1M'));
}

print_r($months);

Solution 6 - Php

Using DateTime, this will give you a more accurate solution for any amount of months:

$d1 = new DateTime("2011-05-14");
$d2 = new DateTime();
$d3 = $d1->diff($d2);
$d4 = ($d3->y*12)+$d3->m;
echo $d4;

You would still need to handle the leftover days $d3->d if your real world problem is not as simple and cut and dry as the original question where both dates are on the first of the month.

Solution 7 - Php

This is a simple method I wrote in my class to count the number of months involved into two given dates :

public function nb_mois($date1, $date2)
{
	$begin = new DateTime( $date1 );
	$end = new DateTime( $date2 );
	$end = $end->modify( '+1 month' );

	$interval = DateInterval::createFromDateString('1 month');

	$period = new DatePeriod($begin, $interval, $end);
	$counter = 0;
	foreach($period as $dt) {
		$counter++;
	}

	return $counter;
}

Solution 8 - Php

In case the dates are part of a resultset from a mySQL query, it is much easier to use the TIMESTAMPDIFF function for your date calculations and you can specify return units eg. Select TIMESTAMPDIFF(MONTH, start_date, end_date)months_diff from table_name

Solution 9 - Php

strtotime is not very precise, it makes an approximate count, it does not take into account the actual days of the month.

it's better to bring the dates to a day that is always present in every month.

$date1 = "2009-09-01";
$date2 = "2010-05-01";

$d1 = mktime(0, 0, 1, date('m', strtotime($date1)), 1, date('Y', strtotime($date1)));
$d2 = mktime(0, 0, 1, date('m', strtotime($date2)), 1, date('Y', strtotime($date2)));

 $total_month = 0;
 while (($d1 = strtotime("+1 MONTH", $d1)) <= $d2) {
     $total_month++;
 }
echo $total_month;

Solution 10 - Php

I have used this and works in all conditions

$fiscal_year = mysql_fetch_row(mysql_query("SELECT begin,end,closed FROM fiscal_year WHERE id = '2'"));
                                                  
          
            $date1 = $fiscal_year['begin'];
            $date2 = $fiscal_year['end'];
        
            $ts1 = strtotime($date1);
            $ts2 = strtotime($date2);
         
         
            $te=date('m',$ts2-$ts1);
            
            echo $te;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSimonView Question on Stackoverflow
Solution 1 - PhpVincent SavardView Answer on Stackoverflow
Solution 2 - PhpChuck BurgessView Answer on Stackoverflow
Solution 3 - PhpMicView Answer on Stackoverflow
Solution 4 - PhpJesus VelazquezView Answer on Stackoverflow
Solution 5 - PhpmanixView Answer on Stackoverflow
Solution 6 - PhppathfinderView Answer on Stackoverflow
Solution 7 - Phppollux1erView Answer on Stackoverflow
Solution 8 - PhpPolyView Answer on Stackoverflow
Solution 9 - PhpClaudioView Answer on Stackoverflow
Solution 10 - PhpranojanView Answer on Stackoverflow