Найти разницу в месяц в php? - PullRequest
11 голосов
/ 21 апреля 2010

Есть ли способ найти разницу в месяце в PHP? У меня есть данные от 2003-10-17 и 2004-03-24. Мне нужно выяснить, сколько месяцев осталось в течение этих двух дней. Скажем, если 6 месяцев, мне нужен выход только в месяцах. Спасибо, что направил меня на разницу в день.

Я нахожу решение через MySQL, но оно мне нужно на PHP. Кто-нибудь, помогите мне, спасибо заранее.

Ответы [ 13 ]

64 голосов
/ 21 апреля 2010

Самый простой способ без изобретать велосипед. Это даст вам полную месячную разницу. То есть следующие две даты - почти 76 месяцев, но результат составляет 75 месяцев.

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";
19 голосов
/ 18 ноября 2013

После тестирования множества решений, сдачи всех в модульное тестирование, вот что я получаю:

/**
 * 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);
}

Например, он вернется (контрольные примеры из модульного теста):

  • 01.11.2013 - 30.11.2013 - 1 месяц
  • 01.01.2013 - 31.12.2013 - 12 месяцев
  • 31.01.2011 - 28.02.2011 - 1 месяц
  • 01.09.2009 - 01.05.2010 - 8 месяцев
  • 01.01.2013 - 31.03.2013 - 3 месяца
  • 15.02.2013 - 15.04.2013 - 2 месяца
  • 01.02.1985 - 31.12.2013 - 347 месяцев

Примечание. Из-за округления со днями округляется даже половина месяца, что может привести к проблемам, если вы используете его в некоторых случаях. Поэтому НЕ ИСПОЛЬЗУЙТЕ его в таких случаях, это вызовет у вас проблемы.

Например:

  • 02.11.2013 - 31.12.2013 вернет 2, а не 1 (как и ожидалось).
7 голосов
/ 13 марта 2015

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

// 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;
6 голосов
/ 12 марта 2012

Ух ты, способ переосмыслить проблему ... Как насчет этой версии:

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;
}

Примечание: в отличие от некоторых других решений, это не зависит от функций даты, добавленных в PHP 5.3, так как многих общих хостов еще нет.

2 голосов
/ 21 апреля 2010

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

Возвращает объект DateInterval, который имеет метод форматирования.

0 голосов
/ 06 октября 2016
$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');
0 голосов
/ 11 марта 2016

В моем случае мне нужно было считать полные месячные и дневные остатки как месяцы, а также строить метки линейного графика.

/**
 * 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++;
}
0 голосов
/ 18 февраля 2016

Лучший способ.

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);

Результат:

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
        )

)
0 голосов
/ 06 января 2016

Это моя расширенная версия ответа @deceze:

 /**
 * @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"));
}
0 голосов
/ 17 декабря 2015
// 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
...