社群、即時通訊、動態牆都需要「相對時間」而非冷冰冰的 2024-03-15 14:30。本文提供一個完整、可直接複製部署的 formatFriendlyTime($timestamp) 函式,涵蓋跨年、跨日、秒/分/時級切換邏輯。
<?php
function formatFriendlyTime(int $ts, string $lang = 'zh-TW'): string {
$now = time();
$diff = $now - $ts;
// 未來時間防呆
if ($diff < 0) return date('Y-m-d H:i', $ts);
// 同一年且天數差 < 365 才用相對時間,否則直接顯示完整日期
$isSameYear = date('Y', $ts) === date('Y', $now);
$dayDiff = (int)floor($diff / 86400);
if (!$isSameYear || $dayDiff >= 3) {
// 跨年或超過 3 天:顯示月日(同年)或完整年月日
return $isSameYear ? date('m月d日 H:i', $ts) : date('Y-m-d H:i', $ts);
}
// 今天
if ($dayDiff === 0) {
if ($diff < 60) return $diff . '秒前';
if ($diff < 3600) return floor($diff / 60) . '分鐘前';
return floor($diff / 3600) . '小時前';
}
// 昨天 / 前天:顯示「昨天 HH:MM」「前天 HH:MM」
$hm = date('H:i', $ts);
if ($dayDiff === 1) return '昨天 ' . $hm;
if ($dayDiff === 2) return '前天 ' . $hm;
// 兜底(理論上不會到這)
return date('m月d日 H:i', $ts);
}
echo formatFriendlyTime(strtotime('-30 seconds')); // 30秒前
echo formatFriendlyTime(strtotime('-5 minutes')); // 5分鐘前
echo formatFriendlyTime(strtotime('-2 hours')); // 2小時前
echo formatFriendlyTime(strtotime('yesterday 10:15')); // 昨天 10:15
echo formatFriendlyTime(strtotime('-3 days')); // 03月12日 14:30 (同年)
echo formatFriendlyTime(strtotime('-400 days')); // 2023-02-10 14:30 (跨年)
gettext,傳入 $lang 切換。$diff < 5 時回傳「剛剛」。<time datetime="2024-03-15T14:30:00+08:00">),由 JS(如 dayjs().fromNow())即時更新,減輕伺服器負擔並解決快取問題。date_default_timezone_set 與資料庫、使用者時區一致。純 PHP 運算極快(單次 < 0.01ms),但若在大清單(>1000 筆)中逐筆呼叫,建議改用 SQL 端 TIMESTAMPDIFF 或前端 JS 處理,避免重複 date() 格式化開銷。