Рассчитать количество месяцев между двумя датами в PHP?


Без использования функции PHP 5.3 date_diff (я использую PHP 5.2.17), есть ли простой и точный способ сделать это? Я думаю о чем-то вроде кода ниже, но я не знаю, как учитывать високосные годы:

$days = ceil(abs( strtotime('2000-01-25') - strtotime('2010-02-20') ) / 86400);
$months = ???;

Я пытаюсь определить, сколько месяцев человеку.

 21
Author: cronoklee, 2012-11-16

8 answers

$date1 = '2000-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);

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

Возможно, вы тоже захотите включить дни где-нибудь, в зависимости от того, имеете ли вы в виду целые месяцы или нет. Надеюсь, вы все же поймете эту идею.

 63
Author: deceze, 2012-11-16 12:52:17

Это простой метод, который я написал в своем классе, чтобы подсчитать количество месяцев, связанных с двумя заданными датами:

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;
}
 13
Author: pollux1er, 2014-09-05 11:24:52

Вот так:

$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');
$months = 0;

while (($date1 = strtotime('+1 MONTH', $date1)) <= $date2)
    $months++;

echo $months;

Если вы хотите включить дни до, то используйте это:

$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');

$months = 0;

while (strtotime('+1 MONTH', $date1) < $date2) {
    $months++;
    $date1 = strtotime('+1 MONTH', $date1);
}

echo $months, ' month, ', ($date2 - $date1) / (60*60*24), ' days'; // 120 month, 26 days
 2
Author: Adam, 2012-11-16 13:17:10

Недавно мне понадобилось рассчитать возраст в месяцах от пренатального до 5 лет (60+ месяцев).

Ни один из приведенных выше ответов не сработал для меня. Первый, который я попробовал, который в основном представляет собой 1 лайнер для ответа deceze

$bdate = strtotime('2011-11-04'); 
$edate = strtotime('2011-12-03');
$age = ((date('Y',$edate) - date('Y',$bdate)) * 12) + (date('m',$edate) - date('m',$bdate));
. . .

Это не удается с установленными датами, очевидно, ответ должен быть 0, так как отметка месяца (2011-12-04) еще не достигнута, как бы код ни возвращал 1.

Второй метод, который я попробовал, используя код Адама

$bdate = strtotime('2011-01-03'); 
$edate = strtotime('2011-02-03');
$age = 0;

while (strtotime('+1 MONTH', $bdate) < $edate) {
    $age++;
    $bdate = strtotime('+1 MONTH', $bdate);
}
. . .

Это не удается и говорит 0 месяцев, когда должно быть 1.

Что действительно сработало для меня, так это небольшое расширение этого кода. Я использовал следующее:

$bdate = strtotime('2011-11-04');
$edate = strtotime('2012-01-04');
$age = 0;

if($edate < $bdate) {
    //prenatal
    $age = -1;
} else {
    //born, count months.
    while($bdate < $edate) {
        $age++;
        $bdate = strtotime('+1 MONTH', $bdate);
        if ($bdate > $edate) {
            $age--;
        }
    }
}
 1
Author: gattsbr, 2016-07-06 15:58:08

Следите за ответом @deceze (я поддержал его ответ). Месяц все равно будет засчитываться в целом, даже если день первого числа не достиг дня второго числа.

Вот мое простое решение по включению дня:

$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); /* I'VE ADDED THE DAY VARIABLE OF DATE1 AND DATE2 */
$day2 = date('d', $ts2);

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

/* IF THE DAY2 IS LESS THAN DAY1, IT WILL LESSEN THE $diff VALUE BY ONE */

if($day2<$day1){ $diff=$diff-1; }

Логика заключается в том, что если день второй даты меньше дня первой даты, это уменьшит значение переменной $diff на единицу.

 0
Author: Logan Wayne, 2014-11-25 06:27:42

Как насчет этого:

$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);
 0
Author: manix, 2015-01-24 23:17:24

Моя функция для решения проблемы

function diffMonth($from, $to) {

        $fromYear = date("Y", strtotime($from));
        $fromMonth = date("m", strtotime($from));
        $toYear = date("Y", strtotime($to));
        $toMonth = date("m", strtotime($to));
        if ($fromYear == $toYear) {
            return ($toMonth-$fromMonth)+1;
        } else {
            return (12-$fromMonth)+1+$toMonth;
        }

    }
 0
Author: Khuat Huu Vinh, 2015-10-09 04:18:55

Вот мое решение. Это всего лишь проверка дат за несколько лет и месяцев. Итак, если одна дата "31.10.15", а другая "02.11.15", она возвращает 1 месяц.

function get_interval_in_month($from, $to) {
    $month_in_year = 12;
    $date_from = getdate(strtotime($from));
    $date_to = getdate(strtotime($to));
    return ($date_to['year'] - $date_from['year']) * $month_in_year -
        ($month_in_year - $date_to['mon']) +
        ($month_in_year - $date_from['mon']);
}
 0
Author: Evgeny, 2015-12-29 13:42:30