社群網站、討論區、動態牆常需顯示「幾分鐘前」、「3 小時前」等相對時間。本文提供一個功能完整、可客製化的相對時間函數。
<?php
/**
* 格式化相對時間
*
* @param string|int|false $time 時間戳記或日期字串,預設為當前時間
* @param int $limit 超過此秒數改用絕對格式,預設 86400(24小時)
* @param string $format 絕對時間格式,預設 'g:i A M jS'
* @return string
*/
function relativeTime($time = false, $limit = 86400, $format = 'g:i A M jS') {
// 參數正規化
if (empty($time) || (!is_string($time) && !is_numeric($time))) {
$time = time();
} elseif (is_string($time)) {
$time = strtotime($time);
}
$now = time();
// 未來時間
if ($time > $now) {
return 'in the future';
}
// 當下
if ($time === $now) {
return 'just now';
}
$diff = $now - $time;
// 超過限制:顯示絕對時間
if ($diff >= $limit) {
return date($format, $time);
}
// 1 分鐘內
if ($diff < 60) {
return 'less than a minute ago';
}
// 分鐘級(1-59 分鐘)
$minutes = ceil($diff / 60);
if ($minutes < 60) {
return $minutes . ' minute' . ($minutes === 1 ? '' : 's') . ' ago';
}
// 小時級(1-23 小時)
$hours = ceil($diff / 3600);
return 'about ' . $hours . ' hour' . ($hours === 1 ? '' : 's') . ' ago';
}
?>
<?php
function relativeTimeZh($time = false, $limit = 86400, $format = 'Y-m-d H:i') {
if (empty($time) || (!is_string($time) && !is_numeric($time))) {
$time = time();
} elseif (is_string($time)) {
$time = strtotime($time);
}
$now = time();
$diff = $now - $time;
if ($diff < 0) return '未來時間';
if ($diff === 0) return '剛剛';
if ($diff >= $limit) return date($format, $time);
if ($diff < 60) return $diff . ' 秒前';
if ($diff < 3600) return floor($diff / 60) . ' 分鐘前';
if ($diff < 86400) return floor($diff / 3600) . ' 小時前';
return date($format, $time);
}
?>
<?php
function humanTimeDiff($from, $to = null) {
$to = $to ?: time();
$diff = abs($to - $from);
$units = array(
31536000 => 'year',
2592000 => 'month',
604800 => 'week',
86400 => 'day',
3600 => 'hour',
60 => 'minute',
1 => 'second'
);
foreach ($units as $seconds => $unit) {
if ($diff >= $seconds) {
$value = floor($diff / $seconds);
$suffix = ($from > $to) ? ' from now' : ' ago';
return $value . ' ' . $unit . ($value > 1 ? 's' : '') . $suffix;
}
}
return 'just now';
}
?>
<?php
echo relativeTimeZh(strtotime('-30 seconds')); // 30 秒前
echo relativeTimeZh(strtotime('-5 minutes')); // 5 分鐘前
echo relativeTimeZh(strtotime('-2 hours')); // 2 小時前
echo relativeTimeZh(strtotime('-3 days')); // 2024-01-15 14:30 (超過 24h)
echo relativeTimeZh(strtotime('+1 hour')); // 未來時間
?>
<?php
// SQL 直接計算(MySQL)
$sql = "SELECT id, title, created_at,
TIMESTAMPDIFF(SECOND, created_at, NOW()) AS diff_seconds
FROM articles ORDER BY created_at DESC";
// PHP 處理
while ($row = mysql_fetch_assoc($result)) {
echo "<span class='time'>" . relativeTimeZh($row['created_at']) . "</span>";
}
?>
結合 JavaScript 定時器,無需重新整理頁面即可更新相對時間:
<script>
// 資料屬性儲存 Unix 時間戳
// <time datetime="2024-01-15T14:30:00" data-timestamp="1705312200">2 小時前</time>
function updateRelativeTimes() {
document.querySelectorAll('[data-timestamp]').forEach(function(el) {
var diff = Math.floor(Date.now()/1000 - parseInt(el.dataset.timestamp));
var text = '';
if (diff < 60) text = diff + ' 秒前';
else if (diff < 3600) text = Math.floor(diff/60) + ' 分鐘前';
else if (diff < 86400) text = Math.floor(diff/3600) + ' 小時前';
else text = new Date(parseInt(el.dataset.timestamp)*1000).toLocaleDateString();
el.textContent = text;
});
}
setInterval(updateRelativeTimes, 30000); // 每 30 秒更新
</script>
相對時間函數能大幅提升使用者體驗,配合前端即時更新,讓動態內容保持新鮮感。根據專案需求選擇適合的實作版本即可。