我有兩個日期格式: php
Start Date: 2007-03-24 End Date: 2009-06-26
如今,我須要以如下形式查找這二者之間的區別: 服務器
2 years, 3 months and 2 days
如何在PHP中作到這一點? 函數
前段時間,我編寫了format_date
函數,由於它爲您提供瞭如何選擇日期的許多選項 : spa
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("Y-m-d 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); }
DateInterval
很棒,但有一些警告: .net
爲了克服這個問題,我編寫了如下代碼(從@enobrev answer改進): code
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; }
它運行兩個循環。 第一個經過蠻力處理相對間隔(年和月),第二個經過簡單的算術計算額外的絕對間隔(所以更快): component
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); }
最好的作法是使用PHP的DateTime
(和DateInterval
)對象。 每一個日期都封裝在DateTime
對象中,而後可使二者之間有所不一樣: orm
$first_date = new DateTime("2012-11-30 17:03:30"); $second_date = new DateTime("2012-12-21 00:00:00");
DateTime
對象將接受任何strtotime()
格式。 若是須要更特定的日期格式,則可使用DateTime::createFromFormat()
建立DateTime
對象。 對象
實例化兩個對象後,可使用DateTime::diff()
減去另外一個。 get
$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);
一個簡單的功能
function time_difference($time_1, $time_2, $limit = null) { $val_1 = new DateTime($time_1); $val_2 = new DateTime($time_2); $interval = $val_1->diff($val_2); $output = array( "year" => $interval->y, "month" => $interval->m, "day" => $interval->d, "hour" => $interval->h, "minute" => $interval->i, "second" => $interval->s ); $return = ""; foreach ($output AS $key => $value) { if ($value == 1) $return .= $value . " " . $key . " "; elseif ($value >= 1) $return .= $value . " " . $key . "s "; if ($key == $limit) return trim($return); } return trim($return); }
使用方式
echo time_difference ($time_1, $time_2, "day");
會像2 years 8 months 2 days
同樣返回
您還可使用如下代碼按$ date1 = $ duedate的舍入分數返回日期差別。 //指定到期日echo $ date2 = date(「 Ymd」); //當前日期$ ts1 = strtotime($ date1); $ ts2 = strtotime($ date2); $ seconds_diff = $ ts1-$ ts2; echo $ datediff = ceil(($ seconds_diff / 3600)/ 24); //幾天後返回
若是您使用php的floor方法而不是ceil,它將使您的舍入分數下降。 若是您的登臺服務器時區與實時站點時區不一樣,請有時在此處檢查差別,在這種狀況下,您可能會獲得不一樣的結果,所以請相應地更改條件。