Элегантный способ получить количество месяцев между двумя датами?
Предположим, что у меня есть две даты в переменных, например
$date1 = "2009-09-01";
$date2 = "2010-05-01";
Мне нужно получить количество месяцев между $date2
и $date1
($date2 >= $date1
). То есть Мне нужно получить 8
.
Есть ли способ получить его с помощью функции date, или мне нужно взорвать мои строки и выполнить некоторые вычисления?
Спасибо большое
Ответы
Ответ 1
Для PHP >= 5.3
$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-05-01");
var_dump($d1->diff($d2)->m); // int(4)
var_dump($d1->diff($d2)->m + ($d1->diff($d2)->y*12)); // int(8)
DateTime:: diff возвращает объект DateInterval
Если вы не работаете с PHP 5.3 или выше, я думаю, вам придется использовать временные метки unix:
$d1 = "2009-09-01";
$d2 = "2010-05-01";
echo (int)abs((strtotime($d1) - strtotime($d2))/(60*60*24*30)); // 8
Но это не очень точно (не всегда 30 дней в месяц).
Последнее: если эти даты приходят из вашей базы данных, то используйте эту СУБД для выполнения этой задачи, а не PHP.
Изменить: Этот код должен быть более точным, если вы не можете использовать DateTime:: diff или ваши РСУБД:
$d1 = strtotime("2009-09-01");
$d2 = strtotime("2010-05-01");
$min_date = min($d1, $d2);
$max_date = max($d1, $d2);
$i = 0;
while (($min_date = strtotime("+1 MONTH", $min_date)) <= $max_date) {
$i++;
}
echo $i; // 8
Ответ 2
Или, если вам нужен процедурный стиль:
$date1 = new DateTime("2009-09-01");
$date2 = new DateTime("2010-05-01");
$interval = date_diff($date1, $date2);
echo $interval->m + ($interval->y * 12) . ' months';
UPDATE. Добавлен бит кода для учета лет.
Ответ 3
Или простой расчет даст:
$numberOfMonths = abs((date('Y', $endDate) - date('Y', $startDate))*12 + (date('m', $endDate) - date('m', $startDate)))+1;
Точная и работает во всех случаях.
Ответ 4
После тестирования множества решений, помещая все в unit test, я получаю следующее:
/**
* 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);
}
Например, он вернется (тестовые примеры из unit test):
- 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 (как и ожидалось).
Ответ 5
Я использую это:
$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);
Ответ 6
Это еще один способ получить количество месяцев между двумя датами:
// Set dates
$dateIni = '2014-07-01';
$dateFin = '2016-07-01';
// Get year and month of initial date (From)
$yearIni = date("Y", strtotime($dateIni));
$monthIni = date("m", strtotime($dateIni));
// Get year an month of finish date (To)
$yearFin = date("Y", strtotime($dateFin));
$monthFin = date("m", strtotime($dateFin));
// Checking if both dates are some year
if ($yearIni == $yearFin) {
$numberOfMonths = ($monthFin-$monthIni) + 1;
} else {
$numberOfMonths = ((($yearFin - $yearIni) * 12) - $monthIni) + 1 + $monthFin;
}
Ответ 7
Используя DateTime, это даст вам более точное решение за любое количество месяцев:
$d1 = new DateTime("2011-05-14");
$d2 = new DateTime();
$d3 = $d1->diff($d2);
$d4 = ($d3->y*12)+$d3->m;
echo $d4;
Вам все равно придется обрабатывать оставшиеся дни $d3->d
, если ваша проблема в реальном мире не такая простая и вырезанная и сухая, как исходный вопрос, где обе даты находятся в первой половине месяца.
Ответ 8
Это простой метод, который я написал в своем классе для подсчета количества месяцев, участвующих в двух датах:
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;
}
Ответ 9
Я использовал это и работал во всех условиях
$fiscal_year = mysql_fetch_row(mysql_query("SELECT begin,end,closed FROM fiscal_year WHERE id = '2'"));
$date1 = $fiscal_year['begin'];
$date2 = $fiscal_year['end'];
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$te=date('m',$ts2-$ts1);
echo $te;