使用“幻数”并对日期进行大量数学运算会降低代码的可读性,并且还会导致问题 - 它不能很好地处理闰年、夏令时、时区或所有其他奇怪的问题带有日期和时间。
如果可能,您应该始终使用诸如 strtotime() 之类的辅助函数来处理日期并避免直接进行数学运算。
这是我做你想做的事的镜头,它并不完美(你不能添加一个大于两个时间段之间的间隔的时间段 - 即从 18:30 到 8:30 的 14 小时 - 它仍然使用一些原始的数学,但这是一个改进:
<?php
function addRollover($givenDate, $addtime) {
$starttime = 8.5*60; //Start time in minutes (decimal hours * 60)
$endtime = 18.5*60; //End time in minutes (decimal hours * 60)
$givenDate = strtotime($givenDate);
//Get just the day portion of the given time
$givenDay = strtotime('today', $givenDate);
//Calculate what the end of today's period is
$maxToday = strtotime("+$endtime minutes", $givenDay);
//Calculate the start of the next period
$nextPeriod = strtotime("tomorrow", $givenDay); //Set it to the next day
$nextPeriod = strtotime("+$starttime minutes", $nextPeriod); //And add the starting time
//If it's the weekend, bump it to Monday
if(date("D", $nextPeriod) == "Sat") {
$nextPeriod = strtotime("+2 days", $nextPeriod);
}
//Add the time period to the new day
$newDate = strtotime("+$addtime", $givenDate);
//print "$givenDate -> $newDate\n";
//print "$maxToday\n";
//Get the new hour as a decimal (adding minutes/60)
$hourfrac = date('H',$newDate) + date('i',$newDate)/60;
//print "$hourfrac\n";
//Check if we're outside the range needed
if($hourfrac < $starttime || $hourfrac > $endtime) {
//We're outside the range, find the remainder and add it on
$remainder = $newDate - $maxToday;
//print "$remainder\n";
$newDate = $nextPeriod + $remainder;
}
return $newDate;
}
?>
我已经注释掉了我用于调试的打印语句,如果你想看看它是如何工作的,你可以取消注释它们(我推荐!)
你这样使用它:
<?php
print date('Y-m-d H:i:s',addRollover('2013-01-01 17:30','2 hours')) . "\n";
print date('Y-m-d H:i:s',addRollover('2013-01-01 18:00','3 hours')) . "\n";
print date('Y-m-d H:i:s',addRollover('2013-01-04 17:00','150 minutes')) . "\n";
?>
结果:
2013-01-02 09:30:00
2013-01-02 11:00:00
2013-01-07 09:30:00
这段代码应该可以很好地处理大多数奇怪的日期,例如时区、夏令时等。使用 PHP 的 DateTime class 会更好地实现它,但这是相当新的,我对它不太熟悉,所以我坚持使用 strtotime()。