优雅的方式来计算两个date之间的月数?

假设我有两个variables的date,比如

$date1 = "2009-09-01"; $date2 = "2010-05-01"; 

我需要得到$date2$date1之间的月数( $date2 >= $date1 )。 即我需要得到8

有没有办法通过使用date函数来获取它,或者我必须爆炸我的string,并做一些计算?

非常感谢

对于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天)。

最后一件事:如果这些date来自你的数据库,那么使用你的DBMS做这个工作,而不是PHP。

编辑:这段代码应该更精确,如果你不能使用DateTime :: diff或你的RDBMS:

 $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 

或者,如果你想要的程序风格:

 $date1 = new DateTime("2009-09-01"); $date2 = new DateTime("2010-05-01"); $interval = date_diff($date1, $date2); echo $interval->m + ($interval->y * 12) . ' months'; 

更新 :增加了一些代码帐户多年。

或者一个简单的计算会给:

 $numberOfMonths = abs((date('Y', $endDate) - date('Y', $startDate))*12 + (date('m', $endDate) - date('m', $startDate)))+1; 

准确,并在所有情况下工作。

在testing了大量的解决scheme之后,把所有的东西都放在一个unit testing中,这就是我所提出的:

 /** * 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 testing中的testing用例):

  • 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个月

注意:由于四舍五入的原因,即使是半个月也会四舍五入,如果在某些情况下使用,可能会导致问题。 所以不要在这种情况下使用它,它会导致你的问题。

例如:

  • 2013年11月2日 – 2013年12月31日将返回2,而不是1(如预期)。

我使用这个:

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

这是获得两个date之间的月份的另一种方式:

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

使用date时间,这将为您提供任何数量的月份更准确的解决scheme:

 $d1 = new DateTime("2011-05-14"); $d2 = new DateTime(); $d3 = $d1->diff($d2); $d4 = ($d3->y*12)+$d3->m; echo $d4; 

如果你的现实世界的问题不是那么简单,如果两个date都是一个月的第一个问题的原始问题,那么你仍然需要处理剩余的天数$d3->d

这是我在class上写的一个简单的方法来计算两个给定date所涉及的月数:

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

我已经使用这个,并在所有条件下工作

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