PHP рассчитывает количество полных месяцев между двумя датами
Я пытаюсь посчитать разницу в месяцах между двумя датами, но более конкретно.
Например, у меня есть две даты: 2017-11-01 а также 2018-01-31
Что мне нужно в результате 3 месяца. Это означает, что между этими двумя датами есть 3 полных месяца выставления счетов.
Вот как это должно работать:
- Месяц 1: 2017-11-01 до 2017-11-30
- Месяц 2: 2017-12-01 до 2017-12-31
- Месяц 3: 2018-01-01 до 2018-01-31
Я попробовал метод diff в классе DateTime, он производит что-то, что мало помогает. Вот пример
diff($date2); print_r($diff) result: DateInterval Object ( [y] => 0 [m] => 2 [d] => 30 [h] => 0 [i] => 0 [s] => 0 [weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 [invert] => 0 [days] => 91 [special_type] => 0 [special_amount] => 0 [have_weekday_relative] => 0 [have_special_relative] => 0 )
Показывает 2 месяца и 30 дней.
Однако в несколько ином сценарии
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00'); $date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-30 00:00:00');
Разница между этими двумя датами должна показывать 2 месяца и 30 дней, а не 3 месяца.
Любая помощь или идеи будут с благодарностью.
Решение
Добавьте один день к вашей дате окончания, прежде чем делать сравнение. Если исходная дата окончания была последним днем месяца, то новая дата окончания переносится на следующий месяц, и вы получите правильное количество «полных» месяцев в объекте diff. Если оригинал был в любой день но последний день месяца, это не изменит результат.
$start = '2017-11-01'; $end = '2018-01-31'; $date1 = DateTime::createFromFormat('Y-m-d', $start); $date2 = DateTime::createFromFormat('Y-m-d', $end)->add(new DateInterval('P1D')); echo $date1->diff($date2)->m, "\n";
Другие решения
Кажется, вы потеряли один день во время расчета. Потому что вам нужен интервал в месяцах, включая первый / последний день — тогда вы должны добавить этот день к интервалу.
Итак, решение в этом случае будет:
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00'); $date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-31 23:59:59'); $diff = $date1->diff($date2);
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-10-31 00:00:00'); $date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-01-31 00:00:00'); $diff = $date1->diff($date2);
$date1 = DateTime::createFromFormat('Y-m-d H:i:s', '2017-11-01 00:00:00'); $date2 = DateTime::createFromFormat('Y-m-d H:i:s', '2018-02-01 00:00:00'); $diff = $date1->diff($date2);
Рассчитать количество месяцев между двумя датами в PHP?
Без использования PHP 5.3 функция date_diff (я использую PHP 5.2.17), есть ли простой и точный способ сделать это? Я думаю о чем-то вроде кода ниже, но я не знаю, как учитывать високосные годы:
$days = ceil(abs( strtotime('2000-01-25') - strtotime('2010-02-20') ) / 86400); $months = . ;
По какой причине вам не понравилось решение на php.net? php.net/manual/en/datetime.diff.php#107434 этот
Что именно вы имеете в виду под количеством месяцев? Какая разница месяцев между 5 октября и 3 ноября того же года? А как насчет 31 октября и 1 ноября?
Подсчитайте количество лет, умножьте его на 12, вычтите начальный месяц из последнего месяца, затем сделайте то же самое с днями. -адить- или делать то, что предложила децез;)
Спасибо всем, я обновил вопрос сейчас, который должен ответить на ваши вопросы. @NappingRabbit, это очень долго!
11 ответов
$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);
Возможно, вы захотите также включить туда дни, в зависимости от того, имеете ли вы целые месяцы или нет. Надеюсь, вы поняли эту идею.
Большое спасибо @deceze, выглядит хорошо! Как вы предлагаете, он должен учитывать дни, чтобы быть точным для возраста людей. Можете ли вы предложить, как это сделать?
На самом деле этот подход работает лучше, чем другие. Например, date_diff() создает date_diff() «7 месяцев и 30 дней» между 2009-09-01 и 2010-05-01 то время как это решение всегда выдает «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; >
$date1 = strtotime('2000-01-25'); $date2 = strtotime('2010-02-20'); $months = 0; while (($date1 = strtotime('+1 MONTH', $date1))
Если вы хотите включить дни, то используйте это:
$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
Это скажет вам, что между 2012-01-01 и 2012-02-01 есть два месяца. Даже если вы измените <= на <, это даст два месяца для промежутка времени январь-1 ->февраль-2, что может быть не лучшим решением.=>
Используя указанные вами даты, я возвращаю 1, потому что он обновляет $ date1, прежде чем проверяет, меньше ли он, и добавляет месяц.
Все, кто использует это, позаботятся об операторе while с некоторым ограничивающим значением для его итерации. Я не говорю, что если код неправильный, он просто безопасен с предосторожностями с помощью итеративных операторов.
Мне недавно нужно было рассчитывать возраст в месяцах от пренатального до 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--; >> >
Рассчитать количество месяцев между двумя датами в PHP?
Без использования функции PHP 5.3 date_diff (я использую PHP 5.2.17), есть ли простой и точный способ сделать это? Я думаю о чем-то вроде кода ниже, но я не знаю, как учитывать високосные годы:
$days = ceil(abs( strtotime('2000-01-25') - strtotime('2010-02-20') ) / 86400); $months = . ;
Я пытаюсь определить, сколько месяцев человеку.
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);
Возможно, вы тоже захотите включить дни где-нибудь, в зависимости от того, имеете ли вы в виду целые месяцы или нет. Надеюсь, вы все же поймете эту идею.
Это простой метод, который я написал в своем классе, чтобы подсчитать количество месяцев, связанных с двумя заданными датами:
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; >
$date1 = strtotime('2000-01-25'); $date2 = strtotime('2010-02-20'); $months = 0; while (($date1 = strtotime('+1 MONTH', $date1))
Если вы хотите включить дни до, то используйте это:
$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
Недавно мне понадобилось рассчитать возраст в месяцах от пренатального до 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--; >> >