在PHP中间隔的舍入时间

时间:2013-10-29 08:49:12

标签: php time

我想将时间转换为四舍五入的时间 因此,想要在几秒钟内使用间隔。 它适用于四分之一小时和整个小时。但不是几天。然后它搞砸了。但我无法理解为什么

这是我的功能:

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。我的错是什么?

2 个答案:

答案 0 :(得分:1)

您有时区问题,因为strtotime功能不支持时区,而date是。{1}}。您可以在本地设置它,而不是使用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);

<强> Run code


更新

DateTime classes的帮助下,您可以使功能更加通用和可读,而不是修改每个时间间隔的功能,例如:

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');

Run code

答案 1 :(得分:0)

  

我的错误是什么?

整个方法都有缺陷。

如果您检查$iRemainder,则会看到它包含Thu, 01 Jan 1970 23:01:48 +0100之类的日期值 - 并从原始值中减去该值并再次添加“几天的秒数”当然会变得混乱由DST引起的不同时间。

使用unix时间戳时,假设一天总是由一定数量的秒组成,这是完全错误的 - 因为之类的东西,如DST。

顺便说一句,根据你的例子,你实际上并没有“四舍五入” - 对于前两个,你将向上四舍五入到下一个15分钟或整整一个小时,但对于第三个你想把 down 围绕到那一天 - 那背后的逻辑是什么?

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