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

PHP DateTime->diff方法计算时间差间歇性显示错误问题求助

问题排查:间歇性错误显示“1 day ago”的根源

嘿,这个间歇性bug的原因其实很明确——你在创建DateTime对象时误用了12小时制的小时格式符h,而不是24小时制的H!这就是导致错误的元凶。

为什么会出现这个问题?

当$RawDate对应的是UTC时间的下午时段(12:00-23:59),date("Y-m-d h:i:s", $RawDate)会把小时部分转成1-12的12小时制格式(比如14:26会变成02:26),但这个格式化后的字符串没有AM/PM标识。DateTime类在解析这种不带AM/PM的12小时制时间时,默认会把它当成上午的时间,这就导致你创建的$DateObject比实际事件时间早了整整12小时。

举个具体的例子:

  • 实际事件时间:2021-06-18 14:26:31 UTC(对应某个时间戳)
  • 用h格式化后得到字符串:2021-06-18 02:26:31
  • DateTime解析后得到的对象:2021-06-18 02:26:31 UTC(比实际时间早12小时)

如果当前时间是2021-06-19 11:00:00 UTC:

  • 实际时间差是20小时33分(还没到24小时,应该显示20 hours ago)
  • 但错误的DateObject和当前时间的差是32小时33分(超过24小时),这时候diff返回的d属性会变成1,导致错误输出1 day ago

当当前时间继续推进到实际事件时间的24小时后,错误的显示和正确结果巧合一致,你就会误以为“恢复正常”了——但这只是偶然,问题根源并没有解决。

修复方案

只需要把创建DateTime对象那一行里的h改成H(24小时制格式符),这样格式化后的时间字符串是正确的24小时制,DateTime就能准确解析出事件的真实时间:

// 关键修复:将h替换为H,使用24小时制格式化时间戳
$DateObject = new DateTime(date("Y-m-d H:i:s", $RawDate));

额外优化建议

其实你完全不需要先用date()格式化时间戳,DateTime类可以直接接受带@前缀的时间戳作为构造参数,这样更高效还能彻底避免格式符用错的问题:

// 直接用时间戳创建UTC时区的DateTime对象,更简洁准确
$DateObject = new DateTime("@$RawDate");
$DateObject->setTimezone(new DateTimeZone('UTC'));

修复后的完整代码:

<?php
function TimeAgo($RawDate) {
    global $G_CurrentTime;
    $TimeAgoString = '';
    // 优化后的写法:直接用时间戳创建UTC时区的DateTime对象
    $DateObject = new DateTime("@$RawDate");
    $DateObject->setTimezone(new DateTimeZone('UTC'));
    
    $DateDiff = $G_CurrentTime->diff($DateObject);
    $TimeAgoArray = (array)$DateDiff;
    print_r($G_CurrentTime);
    print_r($DateObject);
    print_r($TimeAgoArray);
    
    // years
    if ($TimeAgoArray['y'] > 0) {
        $YearString = 'year';
        $TimeAgoString = $TimeAgoArray['y'] . ' ' . ($TimeAgoArray['y'] > 1 ? $YearString . 's' : $YearString) . ' ago';
    }
    // months
    else if ($TimeAgoArray['m'] > 0) {
        $MonthString = 'month';
        $TimeAgoString = $TimeAgoArray['m'] . ' ' . ($TimeAgoArray['m'] > 1 ? $MonthString . 's' : $MonthString) . ' ago';
    }
    // days
    else if ($TimeAgoArray['d'] > 0) {
        $DayString = 'day';
        $TimeAgoString = $TimeAgoArray['d'] . ' ' . ($TimeAgoArray['d'] > 1 ? $DayString . 's' : $DayString) . ' ago';
    }
    // hours
    else if ($TimeAgoArray['h'] > 0) {
        $HourString = 'hour';
        $TimeAgoString = $TimeAgoArray['h'] . ' ' . ($TimeAgoArray['h'] > 1 ? $HourString . 's' : $HourString) . ' ago';
    }
    // minutes
    else if ($TimeAgoArray['i'] > 0) {
        $MinuteString = 'minute';
        $TimeAgoString = $TimeAgoArray['i'] . ' ' . ($TimeAgoArray['i'] > 1 ? $MinuteString . 's' : $MinuteString) . ' ago';
    }
    // seconds
    else if ($TimeAgoArray['s'] > 0) {
        $SecondString = 'second';
        $TimeAgoString = $TimeAgoArray['s'] . ' ' . ($TimeAgoArray['s'] > 1 ? $SecondString . 's' : $SecondString) . ' ago';
    }
    // just now
    else {
        $TimeAgoString = 'just now';
    }
    return $TimeAgoString;
}
?>

内容的提问来源于stack exchange,提问作者PHPisMyFavLol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 19:33:09