【问题标题】:Add two hours to a date within given hours that rollover to the next timeframe将两个小时添加到给定小时内的日期,以滚动到下一个时间范围
【发布时间】:2013-11-26 21:48:53
【问题描述】:

我将如何构建条件以仅在早上 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 + 剩余的 0.5 小时 = 9:00)

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

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

但是我要添加什么来完成上述操作?

【问题讨论】:

  • 17:30 (of Tuesday ) + 2 = 09:30 ?????
  • @relentless(周三至次日)
  • if(date('is',$idate1)>830 && date('is',$idate1)<1830){...put here +120 minutes.....} 我想(可能是我错了)
  • 我已经提交了一份编辑,以使您的问题更清晰,一旦经过同行评审就应该显示出来 - 您的问题令人困惑,希望我已经把它说得更清楚了。

标签: php strtotime


【解决方案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()。

【讨论】:

  • 经过测试,效果很好,这正是我想要的,非常感谢您的帮助
  • 你的函数有问题,当我使用像(2013-11-26 12:30)这样的日期时,他给了我(2013-11-27 04:30:00)
  • 在这里你可以找到它的问题:stackoverflow.com/questions/20229093/…
  • 听起来是时候进行一些调试了。如果您取消注释 print 语句,也许将它们包装在 date() 函数中以便它们更具可读性,您能找到哪里出错了吗?
【解决方案2】:

日期函数适用于 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 时区才能正常工作。

【讨论】:

  • tnk 你的答案 (( 86400/12 )) 我可以知道这是什么意思吗?
  • 付出了很多努力,为了在现实生活中测试您的代码,它是否尊重上述时期?
  • 我在哪里可以看到我使用的是(UTC+0 时区)?
  • date_default_timezone_set()函数设置就行了
  • 这里有很多“幻数”,创建strtotime()函数是有原因的。所有的常量和数学都使它很难阅读,并引入了时区依赖性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多