如何计算使用PHP的两个date之间的差异?

我有两个表格的date:

Start Date: 2007-03-24 End Date: 2009-06-26 

现在我需要find这两者之间的区别在以下forms:

 2 years, 3 months and 2 days 

我怎样才能在PHP中做到这一点?

对于PHP <5.3,否则请参阅下面的jurka的答案

您可以使用strtotime()将两个date转换为unix时间,然后计算它们之间的秒数。 由此计算不同的时间段相当容易。

 $date1 = "2007-03-24"; $date2 = "2009-06-26"; $diff = abs(strtotime($date2) - strtotime($date1)); $years = floor($diff / (365*60*60*24)); $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24)); $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24)); printf("%d years, %d months, %d days\n", $years, $months, $days); 

编辑:显然这样做的首选方式就像下面描述的jurka。 我的代码通常只build议如果你没有PHP 5.3或更好的。

在评论中有几个人指出,上面的代码只是一个近似值。 我仍然相信,对于大多数目的来说,这很好,因为范围的使用更多的是提供一个已经过去或已经过了多less时间的感觉,而不是提供精度 – 如果你想这样做,只需要输出date。

尽pipe如此,我已决定处理这些投诉。 如果你真的需要一个确切的范围,但没有访问PHP 5.3,使用下面的代码(它也应该在PHP 4中工作)。 这是PHP在内部用于计算范围的代码的直接端口,但不考虑夏令时。 这意味着它最多只能停一个小时,但除此之外它应该是正确的。

 <?php /** * Calculate differences between two dates with precise semantics. Based on PHPs DateTime::diff() * implementation by Derick Rethans. Ported to PHP by Emil H, 2011-05-02. No rights reserved. * * See here for original code: * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/tm2unixtime.c?revision=302890&view=markup * http://svn.php.net/viewvc/php/php-src/trunk/ext/date/lib/interval.c?revision=298973&view=markup */ function _date_range_limit($start, $end, $adj, $a, $b, $result) { if ($result[$a] < $start) { $result[$b] -= intval(($start - $result[$a] - 1) / $adj) + 1; $result[$a] += $adj * intval(($start - $result[$a] - 1) / $adj + 1); } if ($result[$a] >= $end) { $result[$b] += intval($result[$a] / $adj); $result[$a] -= $adj * intval($result[$a] / $adj); } return $result; } function _date_range_limit_days($base, $result) { $days_in_month_leap = array(31, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); $days_in_month = array(31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); _date_range_limit(1, 13, 12, "m", "y", &$base); $year = $base["y"]; $month = $base["m"]; if (!$result["invert"]) { while ($result["d"] < 0) { $month--; if ($month < 1) { $month += 12; $year--; } $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0); $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month]; $result["d"] += $days; $result["m"]--; } } else { while ($result["d"] < 0) { $leapyear = $year % 400 == 0 || ($year % 100 != 0 && $year % 4 == 0); $days = $leapyear ? $days_in_month_leap[$month] : $days_in_month[$month]; $result["d"] += $days; $result["m"]--; $month++; if ($month > 12) { $month -= 12; $year++; } } } return $result; } function _date_normalize($base, $result) { $result = _date_range_limit(0, 60, 60, "s", "i", $result); $result = _date_range_limit(0, 60, 60, "i", "h", $result); $result = _date_range_limit(0, 24, 24, "h", "d", $result); $result = _date_range_limit(0, 12, 12, "m", "y", $result); $result = _date_range_limit_days(&$base, &$result); $result = _date_range_limit(0, 12, 12, "m", "y", $result); return $result; } /** * Accepts two unix timestamps. */ function _date_diff($one, $two) { $invert = false; if ($one > $two) { list($one, $two) = array($two, $one); $invert = true; } $key = array("y", "m", "d", "h", "i", "s"); $a = array_combine($key, array_map("intval", explode(" ", date("Y md H is", $one)))); $b = array_combine($key, array_map("intval", explode(" ", date("Y md H is", $two)))); $result = array(); $result["y"] = $b["y"] - $a["y"]; $result["m"] = $b["m"] - $a["m"]; $result["d"] = $b["d"] - $a["d"]; $result["h"] = $b["h"] - $a["h"]; $result["i"] = $b["i"] - $a["i"]; $result["s"] = $b["s"] - $a["s"]; $result["invert"] = $invert ? 1 : 0; $result["days"] = intval(abs(($one - $two)/86400)); if ($invert) { _date_normalize(&$a, &$result); } else { _date_normalize(&$b, &$result); } return $result; } $date = "1986-11-10 19:37:22"; print_r(_date_diff(strtotime($date), time())); print_r(_date_diff(time(), strtotime($date))); 

我build议使用DateTime和DateInterval对象。

 $date1 = new DateTime("2007-03-24"); $date2 = new DateTime("2009-06-26"); $interval = $date1->diff($date2); echo "difference " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; // shows the total amount of days (not divided into years, months and days like above) echo "difference " . $interval->days . " days "; 

阅读更多的PHP DateTime :: diff手册

从手册:

从PHP 5.2.2开始,可以使用比较运算符来比较DateTime对象。

 $date1 = new DateTime("now"); $date2 = new DateTime("tomorrow"); var_dump($date1 == $date2); // bool(false) var_dump($date1 < $date2); // bool(true) var_dump($date1 > $date2); // bool(false) 

最好的方法是使用PHP的DateTime (和DateInterval )对象。 每个date都封装在一个DateTime对象中,然后可以做出两者之间的区别:

 $first_date = new DateTime("2012-11-30 17:03:30"); $second_date = new DateTime("2012-12-21 00:00:00"); 

DateTime对象将接受任何格式strtotime()会。 如果需要更具体的date格式,则可以使用DateTime::createFromFormat()来创buildDateTime对象。

在两个对象被实例化之后,用DateTime::diff()减去另一个对象。

 $difference = $first_date->diff($second_date); 

$difference现在持有一个DateInterval对象与差异信息。 一个var_dump()如下所示:

 object(DateInterval) public 'y' => int 0 public 'm' => int 0 public 'd' => int 20 public 'h' => int 6 public 'i' => int 56 public 's' => int 30 public 'invert' => int 0 public 'days' => int 20 

为了格式化DateInterval对象,我们需要检查每个值,并将其排除,如果它是0:

 /** * Format an interval to show all existing components. * If the interval doesn't have a time component (years, months, etc) * That component won't be displayed. * * @param DateInterval $interval The interval * * @return string Formatted interval string. */ function format_interval(DateInterval $interval) { $result = ""; if ($interval->y) { $result .= $interval->format("%y years "); } if ($interval->m) { $result .= $interval->format("%m months "); } if ($interval->d) { $result .= $interval->format("%d days "); } if ($interval->h) { $result .= $interval->format("%h hours "); } if ($interval->i) { $result .= $interval->format("%i minutes "); } if ($interval->s) { $result .= $interval->format("%s seconds "); } return $result; } 

现在剩下的就是在$difference DateInterval对象上调用我们的函数:

 echo format_interval($difference); 

我们得到正确的结果:

20天6小时56分30秒

用于实现目标的完整代码:

 /** * Format an interval to show all existing components. * If the interval doesn't have a time component (years, months, etc) * That component won't be displayed. * * @param DateInterval $interval The interval * * @return string Formatted interval string. */ function format_interval(DateInterval $interval) { $result = ""; if ($interval->y) { $result .= $interval->format("%y years "); } if ($interval->m) { $result .= $interval->format("%m months "); } if ($interval->d) { $result .= $interval->format("%d days "); } if ($interval->h) { $result .= $interval->format("%h hours "); } if ($interval->i) { $result .= $interval->format("%i minutes "); } if ($interval->s) { $result .= $interval->format("%s seconds "); } return $result; } $first_date = new DateTime("2012-11-30 17:03:30"); $second_date = new DateTime("2012-12-21 00:00:00"); $difference = $first_date->diff($second_date); echo format_interval($difference); 

查看时间和Minuts和秒..

 $date1 = "2008-11-01 22:45:00"; $date2 = "2009-12-04 13:44:01"; $diff = abs(strtotime($date2) - strtotime($date1)); $years = floor($diff / (365*60*60*24)); $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24)); $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24)); $hours = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24)/ (60*60)); $minuts = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60)/ 60); $seconds = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24 - $days*60*60*24 - $hours*60*60 - $minuts*60)); printf("%d years, %d months, %d days, %d hours, %d minuts\n, %d seconds\n", $years, $months, $days, $hours, $minuts, $seconds); 

看看下面的链接。 这是迄今为止我find的最好的答案.. 🙂

 function dateDiff ($d1, $d2) { // Return the number of days between the two dates: return round(abs(strtotime($d1) - strtotime($d2))/86400); } // end function dateDiff 

传递date参数时,哪个date早于或晚于date并不重要。 该函数使用PHP ABS()绝对值总是返回一个阳性数字作为两个date之间的天数。

请记住,两个date之间的天数不包括两个date。 因此,如果您正在查找inputdate之间的所有date所代表的天数,则需要在此函数的结果中添加一个(1)。

例如,2013-02-09和2013-02-14之间的差异(由上述函数返回)是5.但date范围2013-02-09 – 2013-02- 14是6。

http://www.bizinfosys.com/php/date-difference.html

我投了jurka的答案,因为这是我最喜欢的,但我有一个前php.5.3版本…

我发现自己也在处理类似的问题 – 这就是我首先遇到这个问题的原因 – 但只是需要几小时的时间。 但是我的function也很好地解决了这个问题,我自己的库里没有任何地方可以保存它,不会丢失和遗忘的地方,所以…希望这对别人有用。

 /** * * @param DateTime $oDate1 * @param DateTime $oDate2 * @return array */ function date_diff_array(DateTime $oDate1, DateTime $oDate2) { $aIntervals = array( 'year' => 0, 'month' => 0, 'week' => 0, 'day' => 0, 'hour' => 0, 'minute' => 0, 'second' => 0, ); foreach($aIntervals as $sInterval => &$iInterval) { while($oDate1 <= $oDate2){ $oDate1->modify('+1 ' . $sInterval); if ($oDate1 > $oDate2) { $oDate1->modify('-1 ' . $sInterval); break; } else { $iInterval++; } } } return $aIntervals; } 

和testing:

 $oDate = new DateTime(); $oDate->modify('+111402189 seconds'); var_dump($oDate); var_dump(date_diff_array(new DateTime(), $oDate)); 

结果是:

 object(DateTime)[2] public 'date' => string '2014-04-29 18:52:51' (length=19) public 'timezone_type' => int 3 public 'timezone' => string 'America/New_York' (length=16) array 'year' => int 3 'month' => int 6 'week' => int 1 'day' => int 4 'hour' => int 9 'minute' => int 3 'second' => int 8 

我从这里得到了原来的想法,我修改了我的用法(我希望我的修改也会显示在该页面上)。

通过从$aIntervals数组中删除它们,或者可以添加一个$aExclude参数,或者只是在输出string时将其过滤掉,您可以非常容易地删除不想要的时间间隔(比如说“星期”)。

我不知道你是否在使用PHP框架,但是很多PHP框架都有date/时间库和帮助程序来帮助你避免重蹈覆辙。

例如CodeIgniter有timespan()函数。 只需input两个Unix时间戳,它将自动生成如下结果:

 1 Year, 10 Months, 2 Weeks, 5 Days, 10 Hours, 16 Minutes 

http://codeigniter.com/user_guide/helpers/date_helper.html

 <?php $today = strtotime("2011-02-03 00:00:00"); $myBirthDate = strtotime("1964-10-30 00:00:00"); printf("Days since my birthday: ", ($today - $myBirthDate)/60/60/24); ?> 

你可以使用

 getdate() 

函数返回一个包含所有提供的date/时间元素的数组:

 $diff = abs($endDate - $startDate); $my_t=getdate($diff); print("$my_t[year] years, $my_t[month] months and $my_t[mday] days"); 

如果你的开始和结束date是string格式然后使用

 $startDate = strtotime($startDateStr); $endDate = strtotime($endDateStr); 

之前的代码

我有一些简单的逻辑:

 <?php per_days_diff('2011-12-12','2011-12-29') function per_days_diff($start_date, $end_date) { $per_days = 0; $noOfWeek = 0; $noOfWeekEnd = 0; $highSeason=array("7", "8"); $current_date = strtotime($start_date); $current_date += (24 * 3600); $end_date = strtotime($end_date); $seassion = (in_array(date('m', $current_date), $highSeason))?"2":"1"; $noOfdays = array(''); while ($current_date <= $end_date) { if ($current_date <= $end_date) { $date = date('N', $current_date); array_push($noOfdays,$date); $current_date = strtotime('+1 day', $current_date); } } $finalDays = array_shift($noOfdays); //print_r($noOfdays); $weekFirst = array("week"=>array(),"weekEnd"=>array()); for($i = 0; $i < count($noOfdays); $i++) { if ($noOfdays[$i] == 1) { //echo "This is week"; //echo "<br/>"; if($noOfdays[$i+6]==7) { $noOfWeek++; $i=$i+6; } else { $per_days++; } //array_push($weekFirst["week"],$day); } else if($noOfdays[$i]==5) { //echo "This is weekend"; //echo "<br/>"; if($noOfdays[$i+2] ==7) { $noOfWeekEnd++; $i = $i+2; } else { $per_days++; } //echo "After weekend value:- ".$i; //echo "<br/>"; } else { $per_days++; } } /*echo $noOfWeek; echo "<br/>"; echo $noOfWeekEnd; echo "<br/>"; print_r($per_days); echo "<br/>"; print_r($weekFirst); */ $duration = array("weeks"=>$noOfWeek, "weekends"=>$noOfWeekEnd, "perDay"=>$per_days, "seassion"=>$seassion); return $duration; ?> 
 // If you just want to see the year difference then use this function. // Using the logic I've created you may also create month and day difference // which I did not provide here so you may have the efforts to use your brain. // :) $date1='2009-01-01'; $date2='2010-01-01'; echo getYearDifference ($date1,$date2); function getYearDifference($date1=strtotime($date1),$date2=strtotime($date2)){ $year = 0; while($date2 > $date1 = strtotime('+1 year', $date1)){ ++$year; } return $year; } 

这是我的function。 必需的PHP> = 5.3.4。 它使用DateTime类。 非常快,很快,可以做两个date甚至所谓的“时间以来”之间的差异。

 if(function_exists('grk_Datetime_Since') === FALSE){ function grk_Datetime_Since($From, $To='', $Prefix='', $Suffix=' ago', $Words=array()){ # Est-ce qu'on calcul jusqu'à un moment précis ? Probablement pas, on utilise maintenant if(empty($To) === TRUE){ $To = time(); } # On va s'assurer que $From est numérique if(is_int($From) === FALSE){ $From = strtotime($From); }; # On va s'assurer que $To est numérique if(is_int($To) === FALSE){ $To = strtotime($To); } # On a une erreur ? if($From === FALSE OR $From === -1 OR $To === FALSE OR $To === -1){ return FALSE; } # On va créer deux objets de date $From = new DateTime(@date('Ymd H:i:s', $From), new DateTimeZone('GMT')); $To = new DateTime(@date('Ymd H:i:s', $To), new DateTimeZone('GMT')); # On va calculer la différence entre $From et $To if(($Diff = $From->diff($To)) === FALSE){ return FALSE; } # On va merger le tableau des noms (par défaut, anglais) $Words = array_merge(array( 'year' => 'year', 'years' => 'years', 'month' => 'month', 'months' => 'months', 'week' => 'week', 'weeks' => 'weeks', 'day' => 'day', 'days' => 'days', 'hour' => 'hour', 'hours' => 'hours', 'minute' => 'minute', 'minutes' => 'minutes', 'second' => 'second', 'seconds' => 'seconds' ), $Words); # On va créer la chaîne maintenant if($Diff->y > 1){ $Text = $Diff->y.' '.$Words['years']; } elseif($Diff->y == 1){ $Text = '1 '.$Words['year']; } elseif($Diff->m > 1){ $Text = $Diff->m.' '.$Words['months']; } elseif($Diff->m == 1){ $Text = '1 '.$Words['month']; } elseif($Diff->d > 7){ $Text = ceil($Diff->d/7).' '.$Words['weeks']; } elseif($Diff->d == 7){ $Text = '1 '.$Words['week']; } elseif($Diff->d > 1){ $Text = $Diff->d.' '.$Words['days']; } elseif($Diff->d == 1){ $Text = '1 '.$Words['day']; } elseif($Diff->h > 1){ $Text = $Diff->h.' '.$Words['hours']; } elseif($Diff->h == 1){ $Text = '1 '.$Words['hour']; } elseif($Diff->i > 1){ $Text = $Diff->i.' '.$Words['minutes']; } elseif($Diff->i == 1){ $Text = '1 '.$Words['minute']; } elseif($Diff->s > 1){ $Text = $Diff->s.' '.$Words['seconds']; } else { $Text = '1 '.$Words['second']; } return $Prefix.$Text.$Suffix; } } 

使用示例:

 echo time_diff_string('2013-05-01 00:22:35', 'now'); echo time_diff_string('2013-05-01 00:22:35', 'now', true); 

输出:

 4 months ago 4 months, 2 weeks, 3 days, 1 hour, 49 minutes, 15 seconds ago 

function:

 function time_diff_string($from, $to, $full = false) { $from = new DateTime($from); $to = new DateTime($to); $diff = $to->diff($from); $diff->w = floor($diff->d / 7); $diff->d -= $diff->w * 7; $string = array( 'y' => 'year', 'm' => 'month', 'w' => 'week', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second', ); foreach ($string as $k => &$v) { if ($diff->$k) { $v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : ''); } else { unset($string[$k]); } } if (!$full) $string = array_slice($string, 0, 1); return $string ? implode(', ', $string) . ' ago' : 'just now'; } 

这将尝试检测是否给出了时间戳,还将以未来的date/时间作为负值返回:

 <?php function time_diff($start, $end = NULL, $convert_to_timestamp = FALSE) { // If $convert_to_timestamp is not explicitly set to TRUE, // check to see if it was accidental: if ($convert_to_timestamp || !is_numeric($start)) { // If $convert_to_timestamp is TRUE, convert to timestamp: $timestamp_start = strtotime($start); } else { // Otherwise, leave it as a timestamp: $timestamp_start = $start; } // Same as above, but make sure $end has actually been overridden with a non-null, // non-empty, non-numeric value: if (!is_null($end) && (!empty($end) && !is_numeric($end))) { $timestamp_end = strtotime($end); } else { // If $end is NULL or empty and non-numeric value, assume the end time desired // is the current time (useful for age, etc): $timestamp_end = time(); } // Regardless, set the start and end times to an integer: $start_time = (int) $timestamp_start; $end_time = (int) $timestamp_end; // Assign these values as the params for $then and $now: $start_time_var = 'start_time'; $end_time_var = 'end_time'; // Use this to determine if the output is positive (time passed) or negative (future): $pos_neg = 1; // If the end time is at a later time than the start time, do the opposite: if ($end_time <= $start_time) { $start_time_var = 'end_time'; $end_time_var = 'start_time'; $pos_neg = -1; } // Convert everything to the proper format, and do some math: $then = new DateTime(date('Ymd H:i:s', $$start_time_var)); $now = new DateTime(date('Ymd H:i:s', $$end_time_var)); $years_then = $then->format('Y'); $years_now = $now->format('Y'); $years = $years_now - $years_then; $months_then = $then->format('m'); $months_now = $now->format('m'); $months = $months_now - $months_then; $days_then = $then->format('d'); $days_now = $now->format('d'); $days = $days_now - $days_then; $hours_then = $then->format('H'); $hours_now = $now->format('H'); $hours = $hours_now - $hours_then; $minutes_then = $then->format('i'); $minutes_now = $now->format('i'); $minutes = $minutes_now - $minutes_then; $seconds_then = $then->format('s'); $seconds_now = $now->format('s'); $seconds = $seconds_now - $seconds_then; if ($seconds < 0) { $minutes -= 1; $seconds += 60; } if ($minutes < 0) { $hours -= 1; $minutes += 60; } if ($hours < 0) { $days -= 1; $hours += 24; } $months_last = $months_now - 1; if ($months_now == 1) { $years_now -= 1; $months_last = 12; } // "Thirty days hath September, April, June, and November" ;) if ($months_last == 9 || $months_last == 4 || $months_last == 6 || $months_last == 11) { $days_last_month = 30; } else if ($months_last == 2) { // Factor in leap years: if (($years_now % 4) == 0) { $days_last_month = 29; } else { $days_last_month = 28; } } else { $days_last_month = 31; } if ($days < 0) { $months -= 1; $days += $days_last_month; } if ($months < 0) { $years -= 1; $months += 12; } // Finally, multiply each value by either 1 (in which case it will stay the same), // or by -1 (in which case it will become negative, for future dates). // Note: 0 * 1 == 0 * -1 == 0 $out = new stdClass; $out->years = (int) $years * $pos_neg; $out->months = (int) $months * $pos_neg; $out->days = (int) $days * $pos_neg; $out->hours = (int) $hours * $pos_neg; $out->minutes = (int) $minutes * $pos_neg; $out->seconds = (int) $seconds * $pos_neg; return $out; } 

用法示例:

 <?php $birthday = 'June 2, 1971'; $check_age_for_this_date = 'June 3, 1999 8:53pm'; $age = time_diff($birthday, $check_age_for_this_date)->years; print $age;// 28 

要么:

 <?php $christmas_2020 = 'December 25, 2020'; $countdown = time_diff($christmas_2020); print_r($countdown); 

“如果”date存储在MySQL中,我发现在数据库级别进行差异计算更容易…然后基于日,小时,分钟,秒输出,parsing并显示适当的结果…

 mysql> select firstName, convert_tz(loginDate, '+00:00', '-04:00') as loginDate, TIMESTAMPDIFF(DAY, loginDate, now()) as 'Day', TIMESTAMPDIFF(HOUR, loginDate, now())+4 as 'Hour', TIMESTAMPDIFF(MINUTE, loginDate, now())+(60*4) as 'Min', TIMESTAMPDIFF(SECOND, loginDate, now())+(60*60*4) as 'Sec' from User_ where userId != '10158' AND userId != '10198' group by emailAddress order by loginDate desc; +-----------+---------------------+------+------+------+--------+ | firstName | loginDate | Day | Hour | Min | Sec | +-----------+---------------------+------+------+------+--------+ | Peter | 2014-03-30 18:54:40 | 0 | 4 | 244 | 14644 | | Keith | 2014-03-30 18:54:11 | 0 | 4 | 244 | 14673 | | Andres | 2014-03-28 09:20:10 | 2 | 61 | 3698 | 221914 | | Nadeem | 2014-03-26 09:33:43 | 4 | 109 | 6565 | 393901 | +-----------+---------------------+------+------+------+--------+ 4 rows in set (0.00 sec) 

我在下面的页面上find了你的文章,其中包含许多PHPdate时间计算的参考。

使用PHP计算两个date(和时间)之间的差异。 以下页面提供了使用PHP执行date/时间计算的一​​系列不同方法(共7个),以确定两个date之间的时间差(小时数,天数),天数,月数或年数。

请参阅PHPdate时间 – 7个计算两个date之间差异的方法 。

你也可以使用下面的代码来返回date差异$ sum1 = $ duedate; //赋值dateecho $ date2 = date(“Ymd”); //当前date$ ts1 = strtotime($ date1); $ ts2 = strtotime($ date2); $ seconds_diff = $ ts1 – $ ts2; echo $ datediff = ceil(($ seconds_diff / 3600)/ 24); //以天为单位

如果你使用php的floor方法而不是ceil,它会把你的回合分数下降。 请检查这里的差异,有些时候,如果您的登台服务器时区不同,那么在这种情况下,您可能会得到不同的结果,所以相应地改变条件。

对于PHP版本> = 5.3:创build两个date对象,然后使用date_diff()函数。 它将返回php DateInterval对象。 见文档

 $date1=date_create("2007-03-24"); $date2=date_create("2009-06-26"); $diff=date_diff($date1,$date2); echo $diff->format("%R%a days"); 

一个简单的function

 function time_difference ($time_1, $time_2) { $val_1 = new DateTime($time_1); $val_2 = new DateTime($time_2); $interval = $val_1->diff($val_2); $year = $interval->y; $month = $interval->m; $day = $interval->d; $hour = $interval->h; $minute = $interval->i; $second = $interval->s; $output = ''; if($year > 0){ if ($year > 1){ $output .= $year." years "; } else { $output .= $year." year "; } } if($month > 0){ if ($month > 1){ $output .= $month." months "; } else { $output .= $month." month "; } } if($day > 0){ if ($day > 1){ $output .= $day." days "; } else { $output .= $day." day "; } } if($hour > 0){ if ($hour > 1){ $output .= $hour." hours "; } else { $output .= $hour." hour "; } } if($minute > 0){ if ($minute > 1){ $output .= $minute." minutes "; } else { $output .= $minute." minute "; } } if($second > 0){ if ($second > 1){ $output .= $second." seconds"; } else { $output .= $second." second"; } } return $output; } 

使用像

echo time_difference ($time_1, $time_2);

 $date1 = date_create('2007-03-24'); $date2 = date_create('2009-06-26'); $interval = date_diff($date1, $date2); echo "difference : " . $interval->y . " years, " . $interval->m." months, ".$interval->d." days "; 

我有与PHP 5.2相同的问题,并用MySQL解决它。 可能不完全是你正在寻找,但这将做的伎俩,并返回天数:

 $datediff_q = $dbh->prepare("SELECT DATEDIFF(:date2, :date1)"); $datediff_q->bindValue(':date1', '2007-03-24', PDO::PARAM_STR); $datediff_q->bindValue(':date2', '2009-06-26', PDO::PARAM_STR); $datediff = ($datediff_q->execute()) ? $datediff_q->fetchColumn(0) : false; 

更多信息在这里http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_datediff

由于每个人都张贴代码示例,这里是另一个版本。

我想要一个函数来显示从几秒到几年的差异(只有一个单位)。 在一天的时间里,我想让它在午夜时间(周一上午10点从周三上午9点到2点前,而不是1点)滚动。 And for periods over a month, I wanted the rollover to be on the same day of the month (including for 30/31 day months & leap years).

这就是我想到的:

 /** * Returns how long ago something happened in the past, showing it * as n seconds / minutes / hours / days / weeks / months / years ago. * * For periods over a day, it rolls over at midnight (so doesn't depend * on current time of day), and it correctly accounts for month-lengths * and leap-years (months and years rollover on current day of month). * * $param string $timestamp in DateTime format * $return string description of interval */ function ago($timestamp) { $then = date_create($timestamp); // for anything over 1 day, make it rollover on midnight $today = date_create('tomorrow'); // ie end of today $diff = date_diff($then, $today); if ($diff->y > 0) return $diff->y.' year'.($diff->y>1?'s':'').' ago'; if ($diff->m > 0) return $diff->m.' month'.($diff->m>1?'s':'').' ago'; $diffW = floor($diff->d / 7); if ($diffW > 0) return $diffW.' week'.($diffW>1?'s':'').' ago'; if ($diff->d > 1) return $diff->d.' day'.($diff->d>1?'s':'').' ago'; // for anything less than 1 day, base it off 'now' $now = date_create(); $diff = date_diff($then, $now); if ($diff->d > 0) return 'yesterday'; if ($diff->h > 0) return $diff->h.' hour'.($diff->h>1?'s':'').' ago'; if ($diff->i > 0) return $diff->i.' minute'.($diff->i>1?'s':'').' ago'; return $diff->s.' second'.($diff->s==1?'':'s').' ago'; } 

Some time ago I wrote a format_date function as this gives many options on how you want your date :

 function format_date($date, $type, $seperator="-") { if($date) { $day = date("j", strtotime($date)); $month = date("n", strtotime($date)); $year = date("Y", strtotime($date)); $hour = date("H", strtotime($date)); $min = date("i", strtotime($date)); $sec = date("s", strtotime($date)); switch($type) { case 0: $date = date("Y".$seperator."m".$seperator."d",mktime($hour, $min, $sec, $month, $day, $year)); break; case 1: $date = date("D, F j, Y",mktime($hour, $min, $sec, $month, $day, $year)); break; case 2: $date = date("d".$seperator."m".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break; case 3: $date = date("d".$seperator."M".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break; case 4: $date = date("d".$seperator."M".$seperator."Y h:i A",mktime($hour, $min, $sec, $month, $day, $year)); break; case 5: $date = date("m".$seperator."d".$seperator."Y",mktime($hour, $min, $sec, $month, $day, $year)); break; case 6: $date = date("M",mktime($hour, $min, $sec, $month, $day, $year)); break; case 7: $date = date("Y",mktime($hour, $min, $sec, $month, $day, $year)); break; case 8: $date = date("j",mktime($hour, $min, $sec, $month, $day, $year)); break; case 9: $date = date("n",mktime($hour, $min, $sec, $month, $day, $year)); break; case 10: $diff = abs(strtotime($date) - strtotime(date("Ymd h:i:s"))); $years = floor($diff / (365*60*60*24)); $months = floor(($diff - $years * 365*60*60*24) / (30*60*60*24)); $days = floor(($diff - $years * 365*60*60*24 - $months*30*60*60*24)/ (60*60*24)); $date = $years . " years, " . $months . " months, " . $days . "days"; } } return($date); } 

Very simple:

  <?php $date1 = date_create("2007-03-24"); echo "Start date: ".$date1->format("Ymd")."<br>"; $date2 = date_create("2009-06-26"); echo "End date: ".$date2->format("Ymd")."<br>"; $diff = date_diff($date1,$date2); echo "Difference between start date and end date: ".$diff->format("%y years, %m months and %d days")."<br>"; ?> 

Please checkout the following link for details:

PHP: date_diff – Manual

Note that it's for PHP 5.3.0 or greater.

you can always use the following function that can return the age in years and months (ie. 1 Year 4 Months)

 function getAge($dob, $age_at_date) { $d1 = new DateTime($dob); $d2 = new DateTime($age_at_date); $age = $d2->diff($d1); $years = $age->y; $months = $age->m; return $years.'.'.months; } 

or if you want the age to be calculated at the current date, you can use

 function getAge($dob) { $d1 = new DateTime($dob); $d2 = new DateTime(date()); $age = $d2->diff($d1); $years = $age->y; $months = $age->m; return $years.'.'.months; } 

I'm using the following function which I wrote, when PHP 5.3 (respectively date_diff()) is not available:

  function dateDifference($startDate, $endDate) { $startDate = strtotime($startDate); $endDate = strtotime($endDate); if ($startDate === false || $startDate < 0 || $endDate === false || $endDate < 0 || $startDate > $endDate) return false; $years = date('Y', $endDate) - date('Y', $startDate); $endMonth = date('m', $endDate); $startMonth = date('m', $startDate); // Calculate months $months = $endMonth - $startMonth; if ($months <= 0) { $months += 12; $years--; } if ($years < 0) return false; // Calculate the days $measure = ($months == 1) ? 'month' : 'months'; $days = $endDate - strtotime('+' . $months . ' ' . $measure, $startDate); $days = date('z', $days); return array($years, $months, $days); } 

DateInterval is great but it has a couple of caveats:

  1. only for PHP 5.3+ ( but that's really not a good excuse anymore )
  2. only supports years, months, days, hours, minutes and seconds (no weeks)
  3. it calculates the difference with all of the above + days (you can't get the difference in months only)

To overcome that, I coded the following (improved from @enobrev answer ):

 function date_dif($since, $until, $keys = 'year|month|week|day|hour|minute|second') { $date = array_map('strtotime', array($since, $until)); if ((count($date = array_filter($date, 'is_int')) == 2) && (sort($date) === true)) { $result = array_fill_keys(explode('|', $keys), 0); foreach (preg_grep('~^(?:year|month)~i', $result) as $key => $value) { while ($date[1] >= strtotime(sprintf('+%u %s', $value + 1, $key), $date[0])) { ++$value; } $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]); } foreach (preg_grep('~^(?:year|month)~i', $result, PREG_GREP_INVERT) as $key => $value) { if (($value = intval(abs($date[0] - $date[1]) / strtotime(sprintf('%u %s', 1, $key), 0))) > 0) { $date[0] = strtotime(sprintf('+%u %s', $result[$key] = $value, $key), $date[0]); } } return $result; } return false; } 

It runs two loops; the first one deals with the relative intervals (years and months) via brute-forcing, and the second one computes the additional absolute intervals with simple arithmetic (so it's faster):

 echo humanize(date_dif('2007-03-24', '2009-07-31', 'second')); // 74300400 seconds echo humanize(date_dif('2007-03-24', '2009-07-31', 'minute|second')); // 1238400 minutes, 0 seconds echo humanize(date_dif('2007-03-24', '2009-07-31', 'hour|minute|second')); // 20640 hours, 0 minutes, 0 seconds echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|day')); // 2 years, 129 days echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week')); // 2 years, 18 weeks echo humanize(date_dif('2007-03-24', '2009-07-31', 'year|week|day')); // 2 years, 18 weeks, 3 days echo humanize(date_dif('2007-03-24', '2009-07-31')); // 2 years, 4 months, 1 week, 0 days, 0 hours, 0 minutes, 0 seconds function humanize($array) { $result = array(); foreach ($array as $key => $value) { $result[$key] = $value . ' ' . $key; if ($value != 1) { $result[$key] .= 's'; } } return implode(', ', $result); } 

In for a penny, in for a pound: I have just reviewed several solutions, all providing a complex solution using floor() that then rounds up to a 26 years 12 month and 2 days solution, for what should have been 25 years, 11 months and 20 days!!!!

here is my version of this problem: may not be elegant, may not be well coded, but provides a more closer proximity to a answer if you do not count LEAP years, obviously leap years could be coded into this, but in this case – as someone else said, perhaps you could provide this answer:: I have included all TEST conditions and print_r so that you can see more clearly the construct of the results:: here goes,

// set your input dates/ variables::

 $ISOstartDate = "1987-06-22"; $ISOtodaysDate = "2013-06-22"; 

// We need to EXPLODE the ISO yyyy-mm-dd format into yyyy mm dd, as follows::

$yDate[ ] = explode('-', $ISOstartDate); print_r ($yDate);

$zDate[ ] = explode('-', $ISOtodaysDate); print_r ($zDate);

 // Lets Sort of the Years! // Lets Sort out the difference in YEARS between startDate and todaysDate :: $years = $zDate[0][0] - $yDate[0][0]; // We need to collaborate if the month = month = 0, is before or after the Years Anniversary ie 11 months 22 days or 0 months 10 days... if ($months == 0 and $zDate[0][1] > $ydate[0][1]) { $years = $years -1; } // TEST result echo "\nCurrent years => ".$years; // Lets Sort out the difference in MONTHS between startDate and todaysDate :: $months = $zDate[0][1] - $yDate[0][1]; // TEST result echo "\nCurrent months => ".$months; // Now how many DAYS has there been - this assumes that there is NO LEAP years, so the calculation is APPROXIMATE not 100% // Lets cross reference the startDates Month = how many days are there in each month IF mm = 0 which is a years anniversary // We will use a switch to check the number of days between each month so we can calculate days before and after the years anniversary switch ($yDate[0][1]){ case 01: $monthDays = '31'; break; // Jan case 02: $monthDays = '28'; break; // Feb case 03: $monthDays = '31'; break; // Mar case 04: $monthDays = '30'; break; // Apr case 05: $monthDays = '31'; break; // May case 06: $monthDays = '30'; break; // Jun case 07: $monthDays = '31'; break; // Jul case 08: $monthDays = '31'; break; // Aug case 09: $monthDays = '30'; break; // Sept case 10: $monthDays = '31'; break; // Oct case 11: $monthDays = '30'; break; // Nov case 12: $monthDays = '31'; break; // Dec }; // TEST return echo "\nDays in start month ".$yDate[0][1]." => ".$monthDays; // Lets correct the problem with 0 Months - is it 11 months + days, or 0 months +days??? $days = $zDate[0][2] - $yDate[0][2] +$monthDays; echo "\nCurrent days => ".$days."\n"; // Lets now Correct the months to being either 11 or 0 Months, depending upon being + or - the years Anniversary date // At the same time build in error correction for Anniversary dates not being 1yr 0m 31d... see if ($days == $monthDays ) if($days < $monthDays && $months == 0) { $months = 11; // If Before the years anniversary date } else { $months = 0; // If After the years anniversary date $years = $years+1; // Add +1 to year $days = $days-$monthDays; // Need to correct days to how many days after anniversary date }; // Day correction for Anniversary dates if ($days == $monthDays ) // if todays date = the Anniversary DATE! set days to ZERO { $days = 0; // days set toZERO so 1 years 0 months 0 days }; echo "\nTherefore, the number of years/ months/ days/ \nbetween start and todays date::\n\n"; printf("%d years, %d months, %d days\n", $years, $months, $days); 

the end result is:: 26 years, 0 months, 0 days

That's how long I have been in business for on the 22nd June 2013 – Ouch!

 $date = '2012.11.13'; $dateOfReturn = '2017.10.31'; $substract = str_replace('.', '-', $date); $substract2 = str_replace('.', '-', $dateOfReturn); $date1 = $substract; $date2 = $substract2; $ts1 = strtotime($date1); $ts2 = strtotime($date2); $year1 = date('Y', $ts1); $year2 = date('Y', $ts2); $month1 = date('m', $ts1); $month2 = date('m', $ts2); echo $diff = (($year2 - $year1) * 12) + ($month2 - $month1); 

I would prefer to use date_create and date_diff objects.

码:

 $date1 = date_create("2007-03-24"); $date2 = date_create("2009-06-26"); $dateDifference = date_diff($date1, $date2)->format('%y years, %m months and %d days'); echo $dateDifference; 

输出:

 2 years, 3 months and 2 days 

For more info read PHP date_diff manual

According to manual date_diff is an alias of DateTime::diff()