以 php 为单位的间隔舍入时间


Rounding time with intervals in php

我想将时间转换为舍入时间。
因此,我只想使用以秒为单位的间隔。它适用于四分之一小时和整小时。但不是几天。然后就搞砸了。但我不明白为什么

这是我的函数:

function formatToMySQLTime($sTime,$iInterval){
    switch ($iInterval){
        case 1: // 15 minutes;
            $iDivider = 15 * 60;
            break;
        case 2: // 1 hour
            $iDivider = 60 * 60;
            break;
        case 3: // 1 day
            $iDivider = 60 * 60 * 24;
            break;
    }    
    $iRemainder = strtotime($sTime) % $iDivider;
    $iRoundTime = strtotime($sTime) - $iRemainder;    
    $sTime = date('Y-m-d H:i:s', $iRoundTime);
    return $sTime;
}

这是输出:

echo formatToMySQLTime('2013-10-21 03:23:00',1);
2013-10-21 03:15:00
echo formatToMySQLTime('2013-10-21 03:23:00',2);
2013-10-21 03:00:00
echo formatToMySQLTime('2013-10-21 03:23:00',3);
2013-10-21 02:00:00

第三个输出是错误的,应该是2013-10-21 00:00:00.我的错误是什么?

您有时区问题,因为strtotime函数无法识别时区,而date是。您可以通过将 UTC字符串附加到$sTime变量来在本地设置全局时区,而不是使用date()使用gmdate()

// it doesn't matter in which timezone your are, function works with UTC
date_default_timezone_set('Europe/Berlin');
function formatToMySQLTime($sTime, $iInterval) {
    switch ($iInterval){
        case 1: // 15 minutes;
            $iDivider = 15 * 60;
            break;
        case 2: // 1 hour
            $iDivider = 60 * 60;
            break;
        case 3: // 1 day
            $iDivider = 60 * 60 * 24;
            break;
    }
    $U = strtotime($sTime . ' UTC');
    $iRoundTime = $U - $U % $iDivider;    
    return gmdate('Y-m-d H:i:s', $iRoundTime);
}
    
echo formatToMySQLTime('2013-10-21 03:23:00',1);
echo formatToMySQLTime('2013-10-21 03:23:00',2);
echo formatToMySQLTime('2013-10-21 03:23:00',3);

运行代码。

<小时 />

更新:

在 DateTime 类的帮助下,您可以使函数更加通用和可读,而不是为每个间隔修改函数,例如:

function formatToMySQLTime($sTime, $iInterval) {
    $dt = new DateTime($sTime, new DateTimezone('UTC'));
    $U = $dt->getTimestamp();
    $dt2 = clone $dt;
    $interval = DateInterval::createFromDateString($iInterval);
    $iDivider = $dt2->add($interval)->getTimestamp() - $U;
    
    $dt->setTimestamp($U - $U % $iDivider);
    return $dt->format('Y-m-d H:i:s');
}
echo formatToMySQLTime('2013-10-21 03:23:00', '15 minute');
echo formatToMySQLTime('2013-10-21 03:23:00', '1 hour');
echo formatToMySQLTime('2013-10-21 03:23:00', '1 day');

运行代码

我的错误是什么?

整个方法都是有缺陷的。

如果您检查$iRemainder,您会看到它包含一个日期值,例如 Thu, 01 Jan 1970 23:01:48 +0100 - 并且从原始值中减去它并再次添加"一天的秒数"当然会因 DST 引起的不同时间而变得混乱。

在使用 unix 时间戳时,假设一天总是包含一定数量的秒是完全错误的——因为 DST 之类的东西。

顺便说一句,根据你的例子,你实际上并没有"四舍五入"——对于前两个,你四舍五入到

接下来的 15 分钟或整小时,但对于第三个你想舍五入到一天——这背后的逻辑是什么?

我建议您单独查看日期的必要部分,然后返回格式化日期,其余部分仅手动设置为匹配值。