Find Month difference in php? [duplicate]
Asked Answered
E

13

13

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.

Eparchy answered 21/4, 2010 at 9:8 Comment(2)
What exactly is a month in this case? THe calendar month? 30 days?Parsimony
Duplicates: stackoverflow.com/search?q=date+difference+phpOrganography
D
-8

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);
Digitalize answered 21/4, 2010 at 9:19 Comment(2)
This will become more and more inaccurate the farther apart the two dates are and may eventually round the wrong way...Heartily
What will happened if month has 31 days in case January, March, May, July, August, October, December or 28 days in case February, coz you divided by 30.Quezada
H
80

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";
Heartily answered 21/4, 2010 at 9:52 Comment(10)
great work:just a small question into this how to get number of days using this?Renee
@noobie Please RTFM for DateInterval::format to find all possible formatting options.Heartily
Weird results: From: 2013-03-01, Until: 2013-04-01, diff year: 0, diff month: 1, diff days: 3. Months with less then 31 days also give diff in months=0Cancellation
@Cancellation Interesting. But this is bound to be imprecise whatever you do, since "a month" is an terribly vague unit of time. Should it count as one month as soon as a month boundary is crossed between two dates? Or only if a full month lies between them? What is "a full month"? 28 days? 30? 31?Heartily
Use with caution! Difference in months between 01.01.2013 and 31.03.2013 will be 2 months (not 3 as maybe expected!)Lamoureux
@ValentinDespa Actually the difference between 01.01.2013 and 31.03.2013 is 2 months and 30 days, which is accurate. You would be kind of an optimistic person if you would expect a difference of exactly 3 months :-)Quirinus
To get rid of 'Wrong string concatenation operator' in PhpStorm cast string to int: (((int) $diff->format('%y') * 12) + (int) $diff->format('%m'));Amygdalate
2018-04-01 and 2018-07-01 Should be 3 months difference but got 2 months.Norling
Well, it comes down to how you define "one month". It's a wishy-washy definition. Apparently PHP's definition and yours differ. I'd inspect the remaining day difference and round up if necessary/close enough.Heartily
Would be nice to point out that you can add %R to the format to get negative values depending of which date is greater $diff->format('%R%y') * 12) + $diff->format('%R%m')Pillsbury
L
30

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).
Lamoureux answered 18/11, 2013 at 11:53 Comment(2)
nice solution, for example 01.06 - 01.07 gives 0 month (in m), but using days and rounding it works correctlyRamonramona
Very good solution.Brut
A
8

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;
Avatar answered 13/3, 2015 at 8:5 Comment(0)
M
6

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.

Menticide answered 11/3, 2012 at 22:21 Comment(2)
I just edited this line $retval = ($difDays > 0) ? $difMonths : $difMonths - 1; to $retval = ($difDays >= 0) ? $difMonths : $difMonths - 1; So the difference between 2017-02-01 and 2017-03-01 is just 1Lorislorita
not correct. bettwen 2022-06-15 2023-06-15 = 12 Months. Your code retunt value 11Downstream
G
2

http://www.php.net/manual/en/datetime.diff.php

This returns a DateInterval object which has a format method.

Gurgle answered 21/4, 2010 at 9:29 Comment(0)
S
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');
Shed answered 6/10, 2016 at 6:41 Comment(2)
Day Month Year Difference in phpShed
Hi, please add some explanation to why this is a solution. ThanksSurbeck
I
0
// 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
Impressionable answered 17/12, 2015 at 10:43 Comment(0)
A
0

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"));
}
Amygdalate answered 6/1, 2016 at 2:39 Comment(0)
Q
0

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
        )

)
Quadriceps answered 18/2, 2016 at 8:56 Comment(0)
N
0

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++;
}
Natation answered 11/3, 2016 at 8:30 Comment(0)
L
-1
<?php
  # end date is 2008 Oct. 11 00:00:00
  $_endDate = mktime(0,0,0,11,10,2008);
  # begin date is 2007 May 31 13:26:26
  $_beginDate = mktime(13,26,26,05,31,2007);

  $timestamp_diff= $_endDate-$_beginDate +1 ;
  # how many days between those two date
  $days_diff = $timestamp_diff/2635200;

?>

Reference: http://au.php.net/manual/en/function.mktime.php#86916

Lucilius answered 21/4, 2010 at 9:32 Comment(1)
Same problem as @Kai's solution, very optimistic assumption that a month has 30 days...Heartily
M
-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;
    }
}
Mediterranean answered 11/1, 2012 at 17:14 Comment(1)
Ammended - changed $startToEnd = 12 - $startMonth; to $startToEnd = 13 - $startMonth; As before it wasn't counting the duration of decemberMediterranean
D
-8

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);
Digitalize answered 21/4, 2010 at 9:19 Comment(2)
This will become more and more inaccurate the farther apart the two dates are and may eventually round the wrong way...Heartily
What will happened if month has 31 days in case January, March, May, July, August, October, December or 28 days in case February, coz you divided by 30.Quezada

© 2022 - 2024 — McMap. All rights reserved.