Is there any way to find the month difference in PHP? I have the input of from-date 2003-10-17 and to-date 2004-03-24. I need to find how many months there are within these two days. Say if 6 months, I need the output in months only. Thanks for guiding me for day difference.
I find the solution through MySQL but I need it in PHP. Anyone help me, Thanks in advance.
S.L. Barth
8,08971 gold badges50 silver badges63 bronze badges
asked Apr 21, 2010 at 9:08
2
The easiest way without reinventing the wheel. This'll give you the full months difference. I.e. the below two dates are almost 76 months apart, but the result is 75 months.
date_default_timezone_set['Asia/Tokyo']; // you are required to set a timezone
$date1 = new DateTime['2009-08-12'];
$date2 = new DateTime['2003-04-14'];
$diff = $date1->diff[$date2];
echo [[$diff->format['%y'] * 12] + $diff->format['%m']] . " full months difference";
answered Apr 21, 2010 at 9:52
deceze♦deceze
497k81 gold badges718 silver badges865 bronze badges
10
After testing tons of solutions, putting all in a unit test, this is what I come out with:
/**
* Calculate the difference in months between two dates [v1 / 18.11.2013]
*
* @param \DateTime $date1
* @param \DateTime $date2
* @return int
*/
public static function diffInMonths[\DateTime $date1, \DateTime $date2]
{
$diff = $date1->diff[$date2];
$months = $diff->y * 12 + $diff->m + $diff->d / 30;
return [int] round[$months];
}
For example it will return [test cases from the unit test]:
- 01.11.2013 - 30.11.2013 - 1 month
- 01.01.2013 - 31.12.2013 - 12 months
- 31.01.2011 - 28.02.2011 - 1 month
- 01.09.2009 - 01.05.2010 - 8 months
- 01.01.2013 - 31.03.2013 - 3 months
- 15.02.2013 - 15.04.2013 - 2 months
- 01.02.1985 - 31.12.2013 - 347 months
Notice: Because of the rounding it does with the days, even a half of a month will be rounded, which may lead to issue if you use it with some cases. So DO NOT USE it for such cases, it will cause you issues.
For example:
- 02.11.2013 - 31.12.2013 will return 2, not 1 [as expected].
answered Nov 18, 2013 at 11:53
Valentin DespaValentin Despa
38.1k18 gold badges79 silver badges103 bronze badges
2
I just wanted to add this if anyone is looking for a simple solution that counts each touched-upon month in stead of complete months, rounded months or something like that.
// Build example data
$timeStart = strtotime["2003-10-17"];
$timeEnd = strtotime["2004-03-24"];
// Adding current month + all months in each passed year
$numMonths = 1 + [date["Y",$timeEnd]-date["Y",$timeStart]]*12;
// Add/subtract month difference
$numMonths += date["m",$timeEnd]-date["m",$timeStart];
echo $numMonths;
answered Mar 13, 2015 at 8:05
MaXMaX
1,68513 silver badges17 bronze badges
Wow, way to overthink the problem... How about this version:
function monthsBetween[$startDate, $endDate] {
$retval = "";
// Assume YYYY-mm-dd - as is common MYSQL format
$splitStart = explode['-', $startDate];
$splitEnd = explode['-', $endDate];
if [is_array[$splitStart] && is_array[$splitEnd]] {
$difYears = $splitEnd[0] - $splitStart[0];
$difMonths = $splitEnd[1] - $splitStart[1];
$difDays = $splitEnd[2] - $splitStart[2];
$retval = [$difDays > 0] ? $difMonths : $difMonths - 1;
$retval += $difYears * 12;
}
return $retval;
}
NB: unlike several of the other solutions, this doesn't depend on the date functions added in PHP 5.3, since many shared hosts aren't there yet.
answered Mar 11, 2012 at 22:21
CLWillCLWill
1481 silver badge5 bronze badges
2
$datetime1 = date_create['2009-10-11'];
$datetime2 = date_create['2013-1-13'];
$interval = date_diff[$datetime1, $datetime2];
echo $interval->format['%a day %m month %y year'];
answered Oct 6, 2016 at 6:41
2
// get year and month difference
$a1 = '20170401';
$a2 = '20160101'
$yearDiff = [substr[$a1, 0, 4] - substr[$a2, 0, 4]];
$monthDiff = [substr[$a1, 4, 2] - substr[$a2, 4, 2]];
$fullMonthDiff = [$yearDiff * 12] + $monthDiff;
// fullMonthDiff = 16
Mikhail_Sam
9,55611 gold badges57 silver badges87 bronze badges
answered Dec 17, 2015 at 10:43
This is my enhanced version of @deceze answer:
/**
* @param string $startDate
* Current date is considered if empty string is passed
* @param string $endDate
* Current date is considered if empty string is passed
* @param bool $unsigned
* If $unsigned is true, difference is always positive, otherwise the difference might be negative
* @return int
*/
public static function diffInFullMonths[$startDate, $endDate, $unsigned = false]
{
$diff = [new DateTime[$startDate]]->diff[new DateTime[$endDate]];
$reverse = $unsigned === true ? '' : '%r';
return [[int] $diff->format["{$reverse}%y"] * 12] + [[int] $diff->format["{$reverse}%m"]];
}
answered Jan 6, 2016 at 2:39
EhsanEhsan
99210 silver badges19 bronze badges
The best way.
function getIntervals[DateTime $from, DateTime $to]
{
$intervals = [];
$startDate = $from->modify['first day of this month'];
$endDate = $to->modify['last day of this month'];
while[$startDate < $endDate]{
$firstDay = $startDate->format['Y-m-d H:i:s'];
$startDate->modify['last day of this month']->modify['+1 day'];
$intervals[] = [
'firstDay' => $firstDay,
'lastDay' => $startDate->modify['-1 second']->format['Y-m-d H:i:s'],
];
$startDate->modify['+1 second'];
}
return $intervals;
}
$dateTimeFirst = new \DateTime['2013-01-01'];
$dateTimeSecond = new \DateTime['2013-03-31'];
$interval = getIntervals[$dateTimeFirst, $dateTimeSecond];
print_r[$interval];
Result:
Array
[
[0] => Array
[
[firstDay] => 2013-01-01 00:00:00
[lastDay] => 2013-01-31 23:59:59
]
[1] => Array
[
[firstDay] => 2013-02-01 00:00:00
[lastDay] => 2013-02-28 23:59:59
]
[2] => Array
[
[firstDay] => 2013-03-01 00:00:00
[lastDay] => 2013-03-31 23:59:59
]
]
answered Feb 18, 2016 at 8:56
LebnikLebnik
6318 silver badges11 bronze badges
In my case I needed to count full months and day leftovers as month as well to build a line chart labels.
/**
* Calculate the difference in months between two dates
*
* @param \DateTime $from
* @param \DateTime $to
* @return int
*/
public static function diffInMonths[\DateTime $from, \DateTime $to]
{
// Count months from year and month diff
$diff = $to->diff[$from]->format['%y'] * 12 + $to->diff[$from]->format['%m'];
// If there is some day leftover, count it as the full month
if [$to->diff[$from]->format['%d'] > 0] $diff++;
// The month count isn't still right in some cases. This covers it.
if [$from->format['d'] >= $to->format['d']] $diff++;
}
answered Mar 11, 2016 at 8:30
John LinhartJohn Linhart
1,61619 silver badges21 bronze badges
Reference: //au.php.net/manual/en/function.mktime.php#86916
answered Apr 21, 2010 at 9:32
Russell DiasRussell Dias
68.4k5 gold badges50 silver badges71 bronze badges
1
function monthsDif[$start, $end]
{
// Assume YYYY-mm-dd - as is common MYSQL format
$splitStart = explode['-', $start];
$splitEnd = explode['-', $end];
if [is_array[$splitStart] && is_array[$splitEnd]] {
$startYear = $splitStart[0];
$startMonth = $splitStart[1];
$endYear = $splitEnd[0];
$endMonth = $splitEnd[1];
$difYears = $endYear - $startYear;
$difMonth = $endMonth - $startMonth;
if [0 == $difYears && 0 == $difMonth] { // month and year are same
return 0;
}
else if [0 == $difYears && $difMonth > 0] { // same year, dif months
return $difMonth;
}
else if [1 == $difYears] {
$startToEnd = 13 - $startMonth; // months remaining in start year[13 to include final month
return [$startToEnd + $endMonth]; // above + end month date
}
else if [$difYears > 1] {
$startToEnd = 13 - $startMonth; // months remaining in start year
$yearsRemaing = $difYears - 2; // minus the years of the start and the end year
$remainingMonths = 12 * $yearsRemaing; // tally up remaining months
$totalMonths = $startToEnd + $remainingMonths + $endMonth; // Monthsleft + full years in between + months of last year
return $totalMonths;
}
}
else {
return false;
}
}
answered Jan 11, 2012 at 17:14
1
Here's a quick one:
$date1 = mktime[0,0,0,10,0,2003]; // m d y, use 0 for day
$date2 = mktime[0,0,0,3,0,2004]; // m d y, use 0 for day
echo round[[$date2-$date1] / 60 / 60 / 24 / 30];
answered Apr 21, 2010 at 9:19
TowerTower
94.9k126 gold badges346 silver badges502 bronze badges
2