将两个小时添加到转换到下一个时间范围的给定小时内的日期

时间:2013-11-25 23:56:38

标签: php strtotime

我如何构建条件,仅在上午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;

但是我会为完成上述工作添加什么?

2 个答案:

答案 0 :(得分:1)

使用“魔术数字”并使用日期进行大量数学操作会降低您的代码的可读性,并且还会导致问题 - 它不能很好地处理成年,夏令时,时区或所有其他奇怪的问题附带日期和时间。

如果可能,你应该总是使用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()。

答案 1 :(得分:0)

日期函数与UNIX时间戳一起使用,因此我只添加86400(一天中的秒数),然后将其除以24并乘以2.这恰好是2小时。

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

如果您只想在一段时间内应用这些更改,可以使用(timestamp modulo 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时区才能实现此目的。