社交應用中,絕對時間(如 2024-01-15 14:30)不如相對時間(3 分鐘前、2 天前)直觀。本類實現自動根據時間差切換單位,支持中英文複數形式。
<?php
class TimeAgo {
private static $timeagoObject;
private $value; // 計算出的數值
private $unit; // 1=分,2=時,3=天,4=超出範圍
private function __construct() {}
private function __clone() {}
public static function getObject(): self {
if (!(self::$timeagoObject instanceof self)) {
self::$timeagoObject = new self();
}
return self::$timeagoObject;
}
/** 核心計算:將 Unix 時間差轉換為數值+單位 */
private function calculate(int $unixTime): void {
if (!is_numeric($unixTime)) {
$this->unit = 0;
return;
}
$diff = time() - $unixTime; // 秒差
$minutes = (int)floor($diff / 60); // 分鐘差
if ($minutes < 60) { // 1小時內
$this->value = $minutes;
$this->unit = 1;
} elseif ($minutes < 720) { // 12小時內
$this->value = (int)floor($minutes / 60);
$this->unit = 2;
} elseif ($minutes < 7200) { // 10天內
$this->value = (int)floor($minutes / 720);
$this->unit = 3;
} else { // 超過10天
$this->value = $diff;
$this->unit = 4;
}
}
/** 生成英文提示字符串 */
public function toString(int $timestamp): string {
$this->calculate($timestamp);
$units = [
1 => 'minute',
2 => 'hour',
3 => 'day',
4 => ''
];
$unit = $units[$this->unit] ?? '';
if ($this->unit < 4) {
if ($this->value > 1) {
return "{$this->value} {$unit}s ago";
} elseif ($this->value === 1) {
return "{$this->value} {$unit} ago";
} else {
return 'Just now';
}
}
// 超過範圍:返回標準日期格式
return date('Y-m-d H:i', $timestamp);
}
}
$ago = TimeAgo::getObject();
// 假設當前時間 2024-01-15 15:00:00
echo $ago->toString(strtotime('-30 seconds')); // Just now
echo $ago->toString(strtotime('-5 minutes')); // 5 minutes ago
echo $ago->toString(strtotime('-1 minute')); // 1 minute ago
echo $ago->toString(strtotime('-2 hours')); // 2 hours ago
echo $ago->toString(strtotime('-3 days')); // 3 days ago
echo $ago->toString(strtotime('-15 days')); // 2024-01-01 15:00
public function toChineseString(int $timestamp): string {
$this->calculate($timestamp);
$units = [
1 => '分鐘',
2 => '小時',
3 => '天',
];
if ($this->unit < 4) {
if ($this->value > 0) {
return "{$this->value}{$units[$this->unit]}前";
}
return '剛剛';
}
return date('Y年m月d日 H:i', $timestamp);
}
| 時間差 | 顯示 | 邏輯分支 |
|---|---|---|
| < 1 分鐘 | Just now / 剛剛 | $value === 0 |
| 1 分鐘 ~ 59 分鐘 | X minute(s) ago | $unit=1 |
| 1 小時 ~ 11 小時 | X hour(s) ago | $unit=2 |
| 12 小時 ~ 9 天 23 小時 | X day(s) ago | $unit=3 |
| ≥ 10 天 | 完整日期時間 | $unit=4 |
MessageFormatter (intl 擴展) 支持多語言複數規則$timestamp > time(),建議增加「X 分鐘後」分支