在滚动到下一个时间段的给定小时内,为日期添加两个小时


Add two hours to a date within given hours that rollover to the next timeframe

我如何构建条件,只在早上08:30到晚上18:30之间的日期上添加两个小时,不包括周六和周日?

如果给定了边界附近的时间(例如,周二17:30),则剩余时间应添加到下一个"有效"时间段的开始。

例如:如果给定的日期是星期二的17:30,那么两个小时的添加将导致星期三的9:30(17:30+1小时=18:30,8:30+剩余的1小时=9:30)。或者,如果给定的日期是周五17:00,结果将是周一9:00(周五17:00+1.5小时=18:30,周一8:30+剩余时间。5小时=9:00)

我知道如何简单地添加两个小时,如下所示:

$idate1 = strtotime($_POST['date']);
$time1 = date('Y-m-d G:i', strtotime('+120 minutes', $idate1));
$_POST['due_date']  = $time1;

但是,为了实现上述目标,我需要补充什么呢?

使用"幻数"并对日期进行大量计算会降低代码的可读性,也可能会导致问题——它无法很好地处理leapyears、夏令时、时区或日期和时间带来的所有其他奇怪之处。

如果可能,您应该始终使用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类会更好地实现它,但这是一个相当新的类,我对它不太熟悉,所以我坚持使用strtotime()。

date函数使用UNIX时间戳,因此我只需将86400(一天中的秒数)相加,然后除以24,再乘以2。整整多了2个小时。

$time1 = date('Y-m-d G:i', strtotime($idate1)+86400/12);

如果您只想在特定的时间段内应用这些更改,您可以使用(时间戳模86400)公式来获得小时和分钟。

if(($idate%86400)>=(86400/24*8.5)&&($idate%86400)<=(86400/24*18.5)) 
$time1 = date('Y-m-d G:i', strtotime($idate1)+86400/12);

对于过滤周末,date()将帮助您:

if(date("D",$idate)=="Sun" || date("D",$idate)=="Sat)

现在合并条件,我们得到第一部分的解决方案:

if(date("D",$idate)!="Sun" && date("D",$idate)!="Sat" && ($idate%86400)>=(86400/24*8.5)&&($idate%86400)<=(86400/24*18.5)) 
$time1 = date('Y-m-d G:i', strtotime($idate1)+86400/12);

注意:必须在脚本中使用UTC+0时区才能正常工作