You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:20:30