Number of decimal months between two dates

Viewed 1975

How do you find the number of decimal months between two dates in php?

I tried the code below:

$date1 = '2010-01-25';
$date2 = '2010-02-20';

$ts1 = strtotime($date1);
$ts2 = strtotime($date2);

$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);

$month1 = date('m', $ts1);
$month2 = date('m', $ts2);

$day1 = date('d', $ts1);
$day2 = date('d', $ts2);

$diff = (($year2 - $year1) * 12) + ($month2 - $month1);

but it only gives me whole months. I want with decimals. Like 1.5 months or 1.4 months.

3 Answers

First off use DateTime::diff to compare your dates. This will give you a DateInterval result object.

Then I would do something like this:

$months = ($interval->y * 12) + $interval->m; // Total number of whole months
$months += number_format($interval->d / 30, 1); // Add the month fraction

Working example: http://3v4l.org/f6n3r

Dividing amount of days by 30 days is an easy implementation. It is not acceptable for sensitive calculations such as invoices or other finance related stuff.

There is an awesome DateTime extension called Carbon

$start = Carbon::create(2010, 1, 25, 0, 0, 0);
$end = Carbon::create(2010, 2, 20, 0, 0, 0);

echo $start->floatDiffInMonths($end); // "0.90437788018433"

It considers amount of days in a month, leap year and other things.

Keep in mind that calculation happens including time, so if you add 24 hours to $end, then 20 Feb 2010 will also be included:

$start = Carbon::create(2010, 1, 25, 0, 0, 0);
$end = Carbon::create(2010, 2, 20, 24, 0, 0);

echo $start->floatDiffInMonths($end); // "0.94009216589862"

It also supports daylight saving times in different timezones, for that, you'll need to use floatDiffInRealMonths

try this:

function monthNb ($vStartDate,$vEndDate) // dates are of format 2013-11-27
 {$vStart = strtotime($vStartDate);
  $vEnd = strtotime($vEndDate);
  $vDiff = abs($vEnd - $vStart); // here abs in case theres a mix in the dates
  $vMonths = $vDiff / 1036800; // number of seconds in a month of 30 days
  return $vMonths;}

this will give you roughly the difference in months if all months would have 30 days. It can't really get more precise since months don't all have the same number of days. you could do a custom fonction to divide by the number of seconds corresponding to the number of days in the month of the end date, but then 1,5 month ending in january would not mean the same as 1,5 months ending in april. Understand that like Marc B pointed out in his comment, this value can never be precise since months do not have the same number of days.

Related