自时间戳以来的天、小时、分钟


Days, hours, minutes since timestamp

所以我有这个函数,它显示自时间戳以来的时间。

现在,如果是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上检查结果。

PHP 5.2.0引入了DateTime对象,这将为该问题提供更好的解决方案。

我将用我对另一个问题的回答来展示它有多容易,不过会稍微编辑一下代码:

$create_time = "2016-08-02 12:35:04";
$current_time="2016-08-02 16:16:02";
$dtCurrent = DateTime::createFromFormat('Y-m-d H:i:s', $current_time);
// to use current timestamp, use the following:
//$dtCurrent = new DateTime();
$dtCreate = DateTime::createFromFormat('Y-m-d 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

您可以使用渐进式计算方法,例如:

$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;
    }
}

然后,您应该在tokenValues中只有2个项目,根据需要进行调整!

您可以使用diff查找事件发生时间和当前时间差。例如,请参阅以下代码

$time1 = new DateTime('2013-11-21 12:59:00'); // Event occurred time
$time2 = new DateTime(date('Y-m-d 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"