PHP Как найти время, прошедшее с даты?
Как найти время, прошедшее с даты, например, 2010-04-28 17:25:43
Окончательный текст должен быть как xx Minutes Ago
/xx Days Ago
17 ответов
Большинство ответов, кажется, сосредоточены на преобразовании даты из строки во время. Кажется, вы в основном думаете о том, чтобы перенести дату в формат "5 дней назад" и т. Д., Верно?
Вот как я это сделаю:
$time = strtotime('2010-04-28 17:25:43');
echo 'event happened '.humanTiming($time).' ago';
function humanTiming ($time)
{
$time = time() - $time; // to get the time since that moment
$time = ($time<1)? 1 : $time;
$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.(($numberOfUnits>1)?'s':'');
}
}
Я не проверял это, но это должно работать.
Результат будет выглядеть как
event happened 4 days ago
или же
event happened 1 minute ago
ура
Хотите поделиться функцией php, которая приводит к грамматически правильному Facebook, как читаемый человеком формат времени.
Пример:
echo get_time_ago(strtotime('now'));
Результат:
менее 1 минуты назад
function get_time_ago($time_stamp)
{
$time_difference = strtotime('now') - $time_stamp;
if ($time_difference >= 60 * 60 * 24 * 365.242199)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 365.242199 days/year
* This means that the time difference is 1 year or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 365.242199, 'year');
}
elseif ($time_difference >= 60 * 60 * 24 * 30.4368499)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 30.4368499 days/month
* This means that the time difference is 1 month or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 30.4368499, 'month');
}
elseif ($time_difference >= 60 * 60 * 24 * 7)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day * 7 days/week
* This means that the time difference is 1 week or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24 * 7, 'week');
}
elseif ($time_difference >= 60 * 60 * 24)
{
/*
* 60 seconds/minute * 60 minutes/hour * 24 hours/day
* This means that the time difference is 1 day or more
*/
return get_time_ago_string($time_stamp, 60 * 60 * 24, 'day');
}
elseif ($time_difference >= 60 * 60)
{
/*
* 60 seconds/minute * 60 minutes/hour
* This means that the time difference is 1 hour or more
*/
return get_time_ago_string($time_stamp, 60 * 60, 'hour');
}
else
{
/*
* 60 seconds/minute
* This means that the time difference is a matter of minutes
*/
return get_time_ago_string($time_stamp, 60, 'minute');
}
}
function get_time_ago_string($time_stamp, $divisor, $time_unit)
{
$time_difference = strtotime("now") - $time_stamp;
$time_units = floor($time_difference / $divisor);
settype($time_units, 'string');
if ($time_units === '0')
{
return 'less than 1 ' . $time_unit . ' ago';
}
elseif ($time_units === '1')
{
return '1 ' . $time_unit . ' ago';
}
else
{
/*
* More than "1" $time_unit. This is the "plural" message.
*/
// TODO: This pluralizes the time unit, which is done by adding "s" at the end; this will not work for i18n!
return $time_units . ' ' . $time_unit . 's ago';
}
}
Я думаю, у меня есть функция, которая должна делать то, что вы хотите:
function time2string($timeline) {
$periods = array('day' => 86400, 'hour' => 3600, 'minute' => 60, 'second' => 1);
foreach($periods AS $name => $seconds){
$num = floor($timeline / $seconds);
$timeline -= ($num * $seconds);
$ret .= $num.' '.$name.(($num > 1) ? 's' : '').' ';
}
return trim($ret);
}
Просто примените это к разнице между time()
а также strtotime('2010-04-28 17:25:43')
как так:
print time2string(time()-strtotime('2010-04-28 17:25:43')).' ago';
Чтобы улучшить ответ @arnorhs, я добавил возможность получать более точный результат, так что, если вы захотите, например, годы, месяцы, дни и часы с момента присоединения пользователя.
Я добавил новый параметр, чтобы вы могли указать количество точек точности, которые вы хотите вернуть.
function get_friendly_time_ago($distant_timestamp, $max_units = 3) {
$i = 0;
$time = time() - $distant_timestamp; // to get the time since that moment
$tokens = [
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
];
$responses = [];
while ($i < $max_units && $time > 0) {
foreach ($tokens as $unit => $text) {
if ($time < $unit) {
continue;
}
$i++;
$numberOfUnits = floor($time / $unit);
$responses[] = $numberOfUnits . ' ' . $text . (($numberOfUnits > 1) ? 's' : '');
$time -= ($unit * $numberOfUnits);
break;
}
}
if (!empty($responses)) {
return implode(', ', $responses) . ' ago';
}
return 'Just now';
}
Если вы используете класс php Datetime, вы можете использовать:
function time_ago(Datetime $date) {
$time_ago = '';
$diff = $date->diff(new Datetime('now'));
if (($t = $diff->format("%m")) > 0)
$time_ago = $t . ' months';
else if (($t = $diff->format("%d")) > 0)
$time_ago = $t . ' days';
else if (($t = $diff->format("%H")) > 0)
$time_ago = $t . ' hours';
else
$time_ago = 'minutes';
return $time_ago . ' ago (' . $date->format('M j, Y') . ')';
}
Имейте в виду, что большинство математически рассчитанных примеров имеют жесткий предел 2038-01-18
даты и не будут работать с фиктивными датами.
Как не хватало DateTime
а также DateInterval
На основе примеров, я хотел предоставить многоцелевую функцию, которая удовлетворяет потребности ОП и другие, желающие составные истекшие периоды, такие как 1 month 2 days ago
, Наряду со множеством других вариантов использования, таких как ограничение для отображения даты вместо истекшего времени или для фильтрации частей результата истекшего времени.
Кроме того, в большинстве примеров предполагается, что истекшее время относится к текущему времени, где приведенная ниже функция позволяет переопределить его с желаемой датой окончания.
/**
* multi-purpose function to calculate the time elapsed between $start and optional $end
* @param string|null $start the date string to start calculation
* @param string|null $end the date string to end calculation
* @param string $suffix the suffix string to include in the calculated string
* @param string $format the format of the resulting date if limit is reached or no periods were found
* @param string $separator the separator between periods to use when filter is not true
* @param null|string $limit date string to stop calculations on and display the date if reached - ex: 1 month
* @param bool|array $filter false to display all periods, true to display first period matching the minimum, or array of periods to display ['year', 'month']
* @param int $minimum the minimum value needed to include a period
* @return string
*/
function elapsedTimeString($start, $end = null, $limit = null, $filter = true, $suffix = 'ago', $format = 'Y-m-d', $separator = ' ', $minimum = 1)
{
$dates = (object) array(
'start' => new DateTime($start ? : 'now'),
'end' => new DateTime($end ? : 'now'),
'intervals' => array('y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second'),
'periods' => array()
);
$elapsed = (object) array(
'interval' => $dates->start->diff($dates->end),
'unknown' => 'unknown'
);
if ($elapsed->interval->invert === 1) {
return trim('0 seconds ' . $suffix);
}
if (false === empty($limit)) {
$dates->limit = new DateTime($limit);
if (date_create()->add($elapsed->interval) > $dates->limit) {
return $dates->start->format($format) ? : $elapsed->unknown;
}
}
if (true === is_array($filter)) {
$dates->intervals = array_intersect($dates->intervals, $filter);
$filter = false;
}
foreach ($dates->intervals as $period => $name) {
$value = $elapsed->interval->$period;
if ($value >= $minimum) {
$dates->periods[] = vsprintf('%1$s %2$s%3$s', array($value, $name, ($value !== 1 ? 's' : '')));
if (true === $filter) {
break;
}
}
}
if (false === empty($dates->periods)) {
return trim(vsprintf('%1$s %2$s', array(implode($separator, $dates->periods), $suffix)));
}
return $dates->start->format($format) ? : $elapsed->unknown;
}
Следует отметить одну вещь - извлеченные интервалы для предоставленных значений фильтра не переносятся на следующий период. Фильтр просто отображает итоговое значение предоставленных периодов и не пересчитывает периоды, чтобы отобразить только требуемый итог фильтра.
использование
Для ОП необходимо отобразить максимальный период (по состоянию на 2015-02-24).
echo elapsedTimeString('2010-04-26');
/** 4 years ago */
Для отображения составных периодов и предоставления пользовательской даты окончания (обратите внимание на отсутствие предоставленного времени и вымышленных дат).
echo elapsedTimeString('1920-01-01', '2500-02-24', null, false);
/** 580 years 1 month 23 days ago */
Чтобы отобразить результат отфильтрованных периодов (порядок массива не имеет значения).
echo elapsedTimeString('2010-05-26', '2012-02-24', null, ['month', 'year']);
/** 1 year 8 months ago */
Для отображения даты начала в предоставленном формате (по умолчанию Ymd), если достигнут предел.
echo elapsedTimeString('2010-05-26', '2012-02-24', '1 year');
/** 2010-05-26 */
Есть куча других вариантов использования. Он также может быть легко адаптирован для приема меток времени Unix и / или объектов DateInterval для аргументов start, end или limit.
Один вариант, который будет работать с любой версией PHP, это сделать то, что уже было предложено, что-то вроде этого:
$eventTime = '2010-04-28 17:25:43';
$age = time() - strtotime($eventTime);
Это даст вам возраст в секундах. Оттуда вы можете отобразить его так, как пожелаете.
Однако одной из проблем этого подхода является то, что он не учитывает причины сдвига во времени, вызванные летним временем. Если это не проблема, тогда дерзайте. В противном случае вы, вероятно, захотите использовать метод diff() в классе DateTime. К сожалению, это только вариант, если вы используете хотя бы PHP 5.3.
Мне понравился код Митхуна, но я немного подправил его, чтобы дать более разумные ответы.
function getTimeSince($eventTime)
{
$totaldelay = time() - strtotime($eventTime);
if($totaldelay <= 0)
{
return '';
}
else
{
$first = '';
$marker = 0;
if($years=floor($totaldelay/31536000))
{
$totaldelay = $totaldelay % 31536000;
$plural = '';
if ($years > 1) $plural='s';
$interval = $years." year".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($months=floor($totaldelay/2628000))
{
$totaldelay = $totaldelay % 2628000;
$plural = '';
if ($months > 1) $plural='s';
$interval = $months." month".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($days=floor($totaldelay/86400))
{
$totaldelay = $totaldelay % 86400;
$plural = '';
if ($days > 1) $plural='s';
$interval = $days." day".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if ($marker) return $timesince;
if($hours=floor($totaldelay/3600))
{
$totaldelay = $totaldelay % 3600;
$plural = '';
if ($hours > 1) $plural='s';
$interval = $hours." hour".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$marker = 1;
$first = ", ";
}
if($minutes=floor($totaldelay/60))
{
$totaldelay = $totaldelay % 60;
$plural = '';
if ($minutes > 1) $plural='s';
$interval = $minutes." minute".$plural;
$timesince = $timesince.$first.$interval;
if ($marker) return $timesince;
$first = ", ";
}
if($seconds=floor($totaldelay/1))
{
$totaldelay = $totaldelay % 1;
$plural = '';
if ($seconds > 1) $plural='s';
$interval = $seconds." second".$plural;
$timesince = $timesince.$first.$interval;
}
return $timesince;
}
}
Используйте этот, и вы можете получить
$previousDate = '2013-7-26 17:01:10';
$startdate = new DateTime($previousDate);
$endDate = new DateTime('now');
$interval = $endDate->diff($startdate);
echo$interval->format('%y years, %m months, %d days');
См. Этот http://ca2.php.net/manual/en/dateinterval.format.php
Попробуйте один из этих репозиториев:
https://github.com/salavert/time-ago-in-words
https://github.com/jimmiw/php-time-ago
Я только начал использовать последний, делает свое дело, но нет точного отката в стиле stackru на точную дату, когда рассматриваемая дата слишком далека, и нет поддержки будущих дат - и API немного прикольный, но по крайней мере это работает на вид безупречно и поддерживается...
Преобразовать [сохраненную дату] в метку времени. Получить текущую метку времени.
текущая временная метка - [сохраненная_дата] временная метка.
Затем вы можете отформатировать его с датой ();
Обычно вы можете конвертировать большинство форматов даты в метки времени с помощью функции strtotime().
Пришлось сделать это недавно - надеюсь, это кому-нибудь поможет. Это не обслуживает каждую возможность, но удовлетворило мои потребности в проекте.
https://github.com/duncanheron/twitter_date_format
https://github.com/duncanheron/twitter_date_format/blob/master/twitter_date_format.php
Здесь я использую пользовательскую функцию для определения времени, прошедшего с даты.
echo Datetodays ('2013-7-26 17:01:10'); function Datetodays ($ d) {$ date_start = $ d; $ date_end = date ('Ymd H:i:s'); определить ('ВТОРОЙ', 1); определить ("МИНУТА", ВТОРОЙ * 60); определить ("ЧАС", МИНУТА * 60); определить ("ДЕНЬ", ЧАС * 24); определить ('НЕДЕЛЯ', ДЕНЬ * 7); $ t1 = strtotime ($ date_start); $ t2 = strtotime ($ date_end); if ($ t1> $ t2) {$ diffrence = $ t1 - $ t2; } else {$ diffrence = $ t2 - $ t1; } // echo "
"$ Date_end." "$ DATE_START." ". $ diffrence; $ results ['major'] = array (); // целое число, представляющее большее число в отношении даты и времени $ results1 = array (); $ string = ''; $ results ['major'][' недели '] = пол ($ diffrence / WEEK); $ results [' major '] [' days '] = floor ($ diffrence / DAY); $ results [' major '] [' hours '] = floor ($ diffrence / HOUR); $ results ['major']['minutes'] = этаж ($ diffrence / MINUTE); $ results ['major']['секунд'] = floor ($ diffrence / SECOND); // print_r($results); // Logic: // Шаг 1: взять основной результат и преобразовать его в необработанные секунды (это будет меньше количества секунд разницы) // ex: $result = ($results['major') ]['week']*WEEK) // Шаг 2: Вычесть меньшее число (результат) из разницы (общего времени) // ex: $minor_result = $ разность - $result // Шаг 3: Взять полученное время в секунд и преобразовать его в младший формат // ex: floor($minor_result/DAY) $results1['days'] = floor($diffrence / WEEK); $results1['days'] = floor((($diffrence - ($ Results ['Major']['Week'] * WEEK)) / ДЕНЬ)); $results1['hours'] = floor((($diffrence - ($results['major']['days'] * DAY)) / HOUR)); $results1['minutes'] = floor((($diffrence - ($results['major'][HOUR)) / MINUTE)); $results1['seconds'] = floor((($diffrence - ($results['major']['minutes'] * MINUTE)) / SECOND)); //print_r($results1); if ($results1['days']!= 0 && $results1['days'] == 0) { if ($results1['days'] == 1) { $string = $results1['days'] . ' неделю назад'; } else { if ($results1['days'] == 2) { $string = $results1['days']. "недели назад"; } else { $string = '2 недели назад'; } } } elseif ($results1['days']!= 0 && $results1['days']!= 0) { if ($results1['days'] == 1) { $string = $results1['days ']. ' неделю назад'; } else { if ($results1['days'] == 2) { $string = $results1['days']. "недели назад"; } else { $string = '2 недели назад'; } } } elseif ($results1['days'] == 0 && $results1['days']!= 0) { if ($results1['days'] == 1) { $string = $results1['days'] . "день назад"; } else { $string = $results1['days'] . ' дней назад'; } } elseif ($results1['days']!= 0 && $results1['hours']!= 0) { $string = $results1['days'] . "день и". $results1['часы']. ' несколько часов назад'; } elseif ($results1['days'] == 0 && $results1['hours']!= 0) { if ($results1['hours'] == 1) { $string = $results1['hours'], ' час назад'; } else { $string = $results1['hours'] . ' несколько часов назад'; } } elseif ($results1['hours']!= 0 && $results1['minutes']!= 0) { $string = $results1['hours'] . "час и". $results1['минут']. ' минут назад'; } elseif ($results1['hours'] == 0 && $results1['minutes']!= 0) { if ($results1['minutes'] == 1) { $string = $results1['minutes'], "минуту назад"; } else { $string = $results1['minutes'] . ' минут назад'; } } elseif ($results1['minutes']!= 0 && $results1['seconds']!= 0) { $string = $results1['minutes'] . "минута и". $results1['секунд']. "секунды назад"; } elseif ($results1['minutes'] == 0 && $results1['seconds']!= 0) { if ($results1['seconds'] == 1) { $string = $results1['секунд'], "второй назад"; } else {$ string = $ results1 ['секунд']. "секунды назад"; } } return $string; }?>
Импровизация на функцию "HumanTiming" от arnorhs. Он рассчитал бы "полностью растянутый" перевод строки времени в текстовую версию, удобную для чтения человеком. Например, чтобы сказать это как "1 неделя 2 дня 1 час 28 минут 14 секунд"
function humantime ($oldtime, $newtime = null, $returnarray = false) {
if(!$newtime) $newtime = time();
$time = $newtime - $oldtime; // to get the time since that moment
$tokens = array (
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
$htarray = array();
foreach ($tokens as $unit => $text) {
if ($time < $unit) continue;
$numberOfUnits = floor($time / $unit);
$htarray[$text] = $numberOfUnits.' '.$text.(($numberOfUnits>1)?'s':'');
$time = $time - ( $unit * $numberOfUnits );
}
if($returnarray) return $htarray;
return implode(' ', $htarray);
}
Вы можете получить функцию для этого непосредственно из файлов ядра WordPress.
http://core.trac.wordpress.org/browser/tags/3.6/wp-includes/formatting.php
function human_time_diff( $from, $to = '' ) {
if ( empty( $to ) )
$to = time();
$diff = (int) abs( $to - $from );
if ( $diff < HOUR_IN_SECONDS ) {
$mins = round( $diff / MINUTE_IN_SECONDS );
if ( $mins <= 1 )
$mins = 1;
/* translators: min=minute */
$since = sprintf( _n( '%s min', '%s mins', $mins ), $mins );
} elseif ( $diff < DAY_IN_SECONDS && $diff >= HOUR_IN_SECONDS ) {
$hours = round( $diff / HOUR_IN_SECONDS );
if ( $hours <= 1 )
$hours = 1;
$since = sprintf( _n( '%s hour', '%s hours', $hours ), $hours );
} elseif ( $diff < WEEK_IN_SECONDS && $diff >= DAY_IN_SECONDS ) {
$days = round( $diff / DAY_IN_SECONDS );
if ( $days <= 1 )
$days = 1;
$since = sprintf( _n( '%s day', '%s days', $days ), $days );
} elseif ( $diff < 30 * DAY_IN_SECONDS && $diff >= WEEK_IN_SECONDS ) {
$weeks = round( $diff / WEEK_IN_SECONDS );
if ( $weeks <= 1 )
$weeks = 1;
$since = sprintf( _n( '%s week', '%s weeks', $weeks ), $weeks );
} elseif ( $diff < YEAR_IN_SECONDS && $diff >= 30 * DAY_IN_SECONDS ) {
$months = round( $diff / ( 30 * DAY_IN_SECONDS ) );
if ( $months <= 1 )
$months = 1;
$since = sprintf( _n( '%s month', '%s months', $months ), $months );
} elseif ( $diff >= YEAR_IN_SECONDS ) {
$years = round( $diff / YEAR_IN_SECONDS );
if ( $years <= 1 )
$years = 1;
$since = sprintf( _n( '%s year', '%s years', $years ), $years );
}
return $since;
}
Чтобы узнать прошедшее время я обычно использую time()
вместо date()
и отформатированные метки времени. Затем получите разницу между последним значением и более ранним значением и отформатируйте соответственно. time()
это не замена для date()
но это полностью помогает при расчете прошедшего времени.
пример:
Значение time()
выглядит примерно так 1274467343
увеличивается каждую секунду. Так что вы могли бы иметь $erlierTime
со значением 1274467343
а также $latterTime
со значением 1274467500
тогда просто делай $latterTime - $erlierTime
чтобы получить время в секундах.
Написал свой
function getElapsedTime($eventTime)
{
$totaldelay = time() - strtotime($eventTime);
if($totaldelay <= 0)
{
return '';
}
else
{
if($days=floor($totaldelay/86400))
{
$totaldelay = $totaldelay % 86400;
return $days.' days ago.';
}
if($hours=floor($totaldelay/3600))
{
$totaldelay = $totaldelay % 3600;
return $hours.' hours ago.';
}
if($minutes=floor($totaldelay/60))
{
$totaldelay = $totaldelay % 60;
return $minutes.' minutes ago.';
}
if($seconds=floor($totaldelay/1))
{
$totaldelay = $totaldelay % 1;
return $seconds.' seconds ago.';
}
}
}