在 PHP 中,将时间戳(或秒数)转换为时长(如“X天X小时X分X秒”),本质上是一个纯数学量纲转换问题,而不是绝对时间点的格式化。
核心思路是:获取总秒数后,通过逐级整除取余(floor division & modulus)的方式,依次计算出天、小时、分钟和秒。
以下为您提供一个生产就绪、高内聚的 PHP 函数实现:
核心实现代码
/*** 将秒数转换为可读的时长格式** @param int $totalSeconds 总秒数* @param bool $includeZeroUnits 是否包含值为0的时间单位(默认false,省略0值)* @return string 格式化后的时长字符串*/function formatSecondsToDuration(int $totalSeconds, bool $includeZeroUnits = false): string{// 处理负数情况,保证语义一致性$isNegative = $totalSeconds < 0;$seconds = abs($totalSeconds);// 1天 = 86400秒$days = floor($seconds / 86400);$seconds %= 86400;// 1小时 = 3600秒$hours = floor($seconds / 3600);$seconds %= 3600;// 1分钟 = 60秒$minutes = floor($seconds / 60);$secs = $seconds % 60;// 组装结果$parts = [];if ($includeZeroUnits || $days > 0) $parts[] = "{$days}天";if ($includeZeroUnits || $hours > 0) $parts[] = "{$hours}小时";if ($includeZeroUnits || $minutes > 0) $parts[] = "{$minutes}分";if ($includeZeroUnits || $secs > 0 || empty($parts)) $parts[] = "{$secs}秒"; // 如果全为0,至少显示0秒$result = implode('', $parts);return $isNegative ? "-{$result}" : $result;}
使用示例
// 示例 1:常规转换echo formatSecondsToDuration(90061);// 输出: 1天1小时1分1秒// 示例 2:省略为0的单位echo formatSecondsToDuration(3661);// 输出: 1小时1分1秒// 示例 3:包含为0的单位echo formatSecondsToDuration(3661, true);// 输出: 0天1小时1分1秒// 示例 4:处理负数(如已超时的倒计时)echo formatSecondsToDuration(-125);// 输出: -2分5秒
⚠️ 开发避坑指南
- 不要使用
date()函数:date('H:i:s', $seconds)是将秒数当作自 1970 年以来的绝对时间点来解析的。如果传入3661,它会解析为1970-01-01 01:01:01,这完全偏离了“相对时长”的语义。 - 必须使用
floor()向下取整:在处理负数秒数时(例如-125秒),floor(-125 / 60)会得到-3,配合取余可以正确表达-2分5秒的语义。如果使用(int)强转或round(),会导致截断错误。 - 时区无关性:时长的计算(如 1天=86400秒)是纯数学逻辑,与时区无关。但如果您是通过两个时间戳相减(如
$end - $start)来获取总秒数,请务必确保两个时间戳处于统一的时区标准下(推荐 UTC)。 - 毫秒级时间戳处理:如果您的时间戳是毫秒级(13位),请先除以
1000转为秒级再进行计算。
