如何在PHP中计算并显示超过24小时的时间间隔?
问题描述
在JS中计算得到的时间间隔字段存储为类似32:00:00的格式(超过24小时),但在PHP后端尝试减去例如04:00:00的时长时,结果被限制在23:59:59以内,这是因为常规时间处理会自动跨天转换,导致无法正确显示超过24小时的时间间隔。
现有代码
$readyDate = substr($pat['ready4disch_date'],0,10); $readyTime = ($pat['ready4disch_time'] != null) ? $pat['ready4disch_time'] : '00:00:00'; $disDate = substr($pat['date_unit_discharge'],0,10); $disTime = ($pat['time_unit_discharge'] != null) ? $pat['time_unit_discharge'] : '00:00:00'; $ready = new Carbon($readyDate.' '.$readyTime); $discharge = new Carbon($disDate.' '.$disTime); //Calculate difference between decision and admission $min = $ready->diff($discharge); $admSec = date_create('@0')->add($min)->getTimestamp(); //Convert Margin to usable time $marSec = strtotime($margin) - strtotime('TODAY'); // 3600 //Subtract margin from delay $result = $admSec - $marSec; $result = ($result > 0 ) ? $this->secondsToTime($result) : $this->secondsToTime(0);
解决方案
问题出在两个环节:一是通过DateInterval转换总秒数的方式存在隐藏风险,二是secondsToTime函数可能错误地将小时数限制在24以内。以下是修正方案:
1. 直接获取时间差总秒数
使用Carbon的diffInSeconds方法直接获取两个时间点的总秒数差,避免DateInterval转换带来的潜在问题:
// 替换原有的时间差计算代码 $admSec = $ready->diffInSeconds($discharge, false); // false保留正负值,此处因discharge晚于ready,结果为正
2. 安全转换margin为秒数
原方法依赖strtotime,若margin是超过24小时的时长(如25:00:00)会失效,改用拆分时分秒的方式计算:
// 新增辅助函数 private function timeToSeconds($timeStr) { list($hours, $minutes, $seconds) = explode(':', $timeStr); return (int)$hours * 3600 + (int)$minutes * 60 + (int)$seconds; } // 替换原有的marSec计算 $marSec = $this->timeToSeconds($margin);
3. 修正秒数转时长函数
确保转换后的小时数可以超过24,去掉对24的取模操作:
// 修正secondsToTime函数 private function secondsToTime($totalSeconds) { if ($totalSeconds < 0) { $totalSeconds = 0; } $hours = floor($totalSeconds / 3600); $remaining = $totalSeconds % 3600; $minutes = floor($remaining / 60); $seconds = $remaining % 60; // 格式化输出,小时数不强制补零(需补零可改用%02d) return sprintf('%d:%02d:%02d', $hours, $minutes, $seconds); }
4. 整合后的完整代码
$readyDate = substr($pat['ready4disch_date'],0,10); $readyTime = ($pat['ready4disch_time'] != null) ? $pat['ready4disch_time'] : '00:00:00'; $disDate = substr($pat['date_unit_discharge'],0,10); $disTime = ($pat['time_unit_discharge'] != null) ? $pat['time_unit_discharge'] : '00:00:00'; $ready = new Carbon($readyDate.' '.$readyTime); $discharge = new Carbon($disDate.' '.$disTime); // 获取时间差总秒数 $admSec = $ready->diffInSeconds($discharge, false); // 转换margin为秒数 $marSec = $this->timeToSeconds($margin); // 计算结果并转换为时长格式 $resultSec = max($admSec - $marSec, 0); $result = $this->secondsToTime($resultSec); // 辅助函数 private function timeToSeconds($timeStr) { list($hours, $minutes, $seconds) = explode(':', $timeStr); return (int)$hours * 3600 + (int)$minutes * 60 + (int)$seconds; } private function secondsToTime($totalSeconds) { $hours = floor($totalSeconds / 3600); $remaining = $totalSeconds % 3600; $minutes = floor($remaining / 60); $seconds = $remaining % 60; return sprintf('%d:%02d:%02d', $hours, $minutes, $seconds); }
处理后即可正确计算并显示类似32:00:00的超24小时时间间隔。
内容的提问来源于stack exchange,提问作者morne
相关产品推荐
相关产品推荐

