我有两个日期格式: 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,它将使您的舍入分数下降。 若是您的登台服务器时区与实时站点时区不一样,请有时在此处检查差别,在这种状况下,您可能会获得不一样的结果,所以请相应地更改条件。