在PHP开发中,经常需要将两个时间点的差值转换为易读的格式,比如显示“3分钟前”“2小时前”“5天前”这类内容,这种需求在社交类、内容类项目中非常常见。实现这个功能的核心是先计算出两个时间的差值,再根据差值的大小转换为对应的时间单位进行展示。

基础实现:使用时间戳计算时间差
最基础的方式是通过strtotime函数将时间字符串转为时间戳,计算差值后再按单位转换。时间戳的单位是秒,我们可以先算出总秒数,再依次判断对应的时间单位。
<?php
/**
* 基础版时间差格式化函数
* @param string $targetTime 目标时间字符串
* @param string $nowTime 当前时间字符串,默认取当前时间
* @return string 格式化后的时间差
*/
function formatTimeDiffBasic($targetTime, $nowTime = '') {
// 处理当前时间,默认取当前时间戳
$now = $nowTime ? strtotime($nowTime) : time();
$target = strtotime($targetTime);
// 计算时间差(秒)
$diff = $now - $target;
// 如果时间差为负,说明目标时间在未来,直接返回目标时间
if ($diff <= 0) {
return date('Y-m-d H:i:s', $target);
}
// 定义时间单位对应的秒数
$units = [
'年' => 31536000,
'个月' => 2592000,
'周' => 604800,
'天' => 86400,
'小时' => 3600,
'分钟' => 60,
'秒' => 1
];
foreach ($units as $unit => $seconds) {
if ($diff >= $seconds) {
$num = floor($diff / $seconds);
return $num . $unit . '前';
}
}
return '刚刚';
}
// 测试示例
echo formatTimeDiffBasic('2024-05-20 10:30:00');
?>进阶实现:使用DateTime类处理时间差
PHP内置的DateTime类和DateInterval类可以更规范地处理时间计算,避免时间戳计算可能出现的时区问题,也更符合面向对象的编程习惯。
<?php
/**
* 使用DateTime类实现时间差格式化
* @param string $targetTime 目标时间字符串
* @param string $timezone 时区,默认Asia/Shanghai
* @return string 格式化后的时间差
*/
function formatTimeDiffWithDateTime($targetTime, $timezone = 'Asia/Shanghai') {
try {
// 设置时区
$timezoneObj = new DateTimeZone($timezone);
$now = new DateTime('now', $timezoneObj);
$target = new DateTime($targetTime, $timezoneObj);
// 计算时间差
$diff = $now->diff($target);
// 如果目标时间在未来,返回格式化后的目标时间
if ($diff->invert == 0) {
return $target->format('Y-m-d H:i:s');
}
// 按从大到小的单位判断
if ($diff->y > 0) {
return $diff->y . '年前';
}
if ($diff->m > 0) {
return $diff->m . '个月前';
}
if ($diff->d >= 7) {
$weeks = floor($diff->d / 7);
return $weeks . '周前';
}
if ($diff->d > 0) {
return $diff->d . '天前';
}
if ($diff->h > 0) {
return $diff->h . '小时前';
}
if ($diff->i > 0) {
return $diff->i . '分钟前';
}
return '刚刚';
} catch (Exception $e) {
// 时间格式错误时返回原时间
return $targetTime;
}
}
// 测试示例
echo formatTimeDiffWithDateTime('2024-05-25 14:20:00');
?>两种实现方式的对比
可以通过以下表格对比两种实现方式的特点,开发者可以根据项目需求选择:
| 实现方式 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 时间戳计算 | 逻辑简单,性能略高,兼容性好 | 容易出现时区问题,处理复杂时间规则较麻烦 | 简单项目,对时区要求不高的场景 |
| DateTime类 | 内置时区处理,支持复杂时间计算,面向对象更规范 | 代码量稍多,性能略低于时间戳方式 | 中大型项目,需要严格时区控制的场景 |
注意事项
- 使用
strtotime函数时,要确保传入的时间字符串格式符合PHP的解析规则,否则会返回false导致计算错误。 - 如果项目涉及多时区用户,建议统一使用DateTime类并指定对应时区,避免时间展示错误。
- 可以根据业务需求调整时间单位的判断顺序,比如不需要显示“周”单位,可以删除对应的判断逻辑。
- 如果时间差超过一年,也可以根据需求调整为返回具体的日期格式,而不是“X年前”。
以上就是PHP格式化时间差显示的完整实现方法,两种方式都提供了可直接复用的函数,开发者可以根据实际情况选择使用,也可以基于这些逻辑扩展出更符合自己业务需求的格式化规则。