Поэтому у меня есть эта функция, которая показывает, сколько времени прошло с момента времени.
Прямо сейчас, если скажем 60 минут, это пройдет и покажет «1 час назад». Если прошло 24 часа, это перейдет к «1 день назад» и так далее. Как я мог сделать так, чтобы, если это было, например, 1 час, также показывайте минуты?
подобно
Event occured 58 minutes ago 3 minutes later Event occured 1 hour 1 minute ago 26 hours later Event occured 1 day 2 hour ago function humanTiming($time) { $time = time() - $time; // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); foreach ($tokens as $unit => $text) { if ($time < $unit) continue; $numberOfUnits = floor($time / $unit); return $numberOfUnits.$text.' ago'; } }
Вам нужно изменить свою функцию следующим образом:
function humanTiming($time) { $time = time() - $time; // to get the time since that moment $tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); $result = ''; $counter = 1; foreach ($tokens as $unit => $text) { if ($time < $unit) continue; if ($counter > 2) break; $numberOfUnits = floor($time / $unit); $result .= "$numberOfUnits $text "; $time -= $numberOfUnits * $unit; ++$counter; } return "{$result}ago"; }
Проверьте результат на codepad.org .
Вы можете использовать прогрессивный метод расчета, например:
$tokens = array ( 31536000 => 'year', 2592000 => 'month', 604800 => 'week', 86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second' ); $tokenValues = array(); foreach($tokens as $tokenValue => $tokenName) { if($time > $tokenValue) { $tokenValues[$tokenName] = floor($time \ $tokenValue); $time -= $tikenValue; } if(count($tokenValues) == 2) { break; } }
У вас должно быть только 2 элемента в tokenValues, адаптируйте, как вы считаете нужным!
Вы можете найти время и текущую разницу во времени, используя diff. Например, см. Следующий код
$time1 = new DateTime('2013-11-21 12:59:00'); // Event occurred time $time2 = new DateTime(date('Ymd H:i:s')); // Current time $interval = $time1->diff($time2); echo $interval->y . " Year " .$interval->m . " Month " .$interval->d ." Days ". $interval->h . " Hours, " . $interval->i." Mintues, ".$interval->s." seconds <br/>";
У меня нет времени объяснять, но эта функция работает, когда я ее тестировал. Кроме того, я добавляю функцию для обработки времени с текущего времени и будущего. Если вы будете снабжать эту функцию точным текущим временем, она вернется 'just now'
. Если вы снабдите его временем из прошлого, он вернет строку, закончившуюся 'ago'
. Если вы предоставите его со временем из будущего, он вернет строку, закончившуюся 'later'
. Другая особенность – автоматическая сингулярная / множественная форма для единицы времени. Попробуй сам!
function timeEllapsedFrom($from) { $time = time() - $from; $diff = abs($time); $tokens = array ( 'year' => 31536000, 'month' => 2592000, 'week' => 604800, 'day' => 86400, 'hour' => 3600, 'minute' => 60, 'second' => 1 ); $result = array(); foreach ($tokens as $id => $length) { $value = floor($diff/$length); if ($value) $result[] = "$value $id" . ($value > 1 ? 's' : ''); $diff -= $length*$value; } if (!count($result)) return 'just now'; return join(', ', $result) . ($time < 0 ? ' later' : ' ago'); }
Вы можете проверить его с помощью этого кода:
echo timeEllapsedFrom(time() - 604800 - 7200 - 480 - 24);
и он будет выводить:
1 week, 2 hours, 8 minutes, 24 seconds ago
Надеюсь, поможет!
Использование класса DateTime
. Работает как с прошлыми, так и с будущими метками времени, и при необходимости исправляет плюрализацию:
function elapsedTime($time) { date_default_timezone_set('UTC'); $given_time = new DateTime("@$time"); $current_time = new DateTime(); $diff = $given_time->diff($current_time); $timemap = array('y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second'); $timefmt = array(); foreach ($timemap as $prop => $desc) { if ($diff->$prop > 0) { $timefmt[] = ($diff->$prop > 1) ? "{$diff->$prop} {$desc}s" : "{$diff->$prop} $desc"; } } return (!$timefmt) ? 'just now' : ((count($timefmt) > 1) ? $diff->format(sprintf('%s and %s', implode(', ', array_slice($timefmt, 0, -1)), end($timefmt))) : end($timefmt)) . (($given_time < $current_time) ? ' ago' : ' later'); }
Тестирование:
var_dump(elapsedTime(strtotime('1987-11-25 11:40'))); # string(69) "25 years, 11 months, 29 days, 17 hours, 50 minutes and 42 seconds ago" var_dump(elapsedTime(time())); # string(8) "just now" var_dump(elapsedTime(strtotime('2013-11-25'))); # string(41) "18 hours, 29 minutes and 18 seconds later"
В PHP 5.2.0 представлен объект DateTime
, который обеспечит лучшее решение проблемы.
Я собираюсь использовать свой ответ на другой вопрос, чтобы показать, насколько это просто, хотя немного изменит код:
$create_time = "2016-08-02 12:35:04"; $current_time="2016-08-02 16:16:02"; $dtCurrent = DateTime::createFromFormat('Ymd H:i:s', $current_time); // to use current timestamp, use the following: //$dtCurrent = new DateTime(); $dtCreate = DateTime::createFromFormat('Ymd H:i:s', $create_time); $diff = $dtCurrent->diff($dtCreate); $interval = $diff->format("%y years %m months %d days %h hours %i minutes %s seconds");
$interval
вернется 0 years 0 months 0 days 3 hours 40 minutes 58 seconds
Давайте теперь избавимся от этих нулевых значений. Хорошее старое регулярное выражение здесь очень полезно:
$interval = preg_replace('/(^0| 0) (years|months|days|hours|minutes|seconds)/', '', $interval);
В итоге мы получаем именно то, что нам нужно: 3 hours 40 minutes 58 seconds