【问题标题】:PHP create range of datesPHP 创建日期范围
【发布时间】:2011-08-31 23:11:07
【问题描述】:

从以下格式的日期开始:2011-05-01 09:00:00,如何创建一个包含一年中所有工作日的所有办公时间(09:00 到 17:00)的数组(因此不包括所有周六和周日) .我想要到达的是这样的:

2011-05-01 09:00:00
2011-05-01 10:00:00
2011-05-01 11:00:00
2011-05-01 12:00:00
2011-05-01 13:00:00
2011-05-01 14:00:00
2011-05-01 15:00:00
2011-05-01 16:00:00
2011-05-01 17:00:00
//next day, starting at 09:00 and ending at 17:00
2011-05-02 09:00:00
...
2011-05-02 17:00:00
//until the last day of the year from 09:00 to 17:00
2011-12-31 09:00:00
...
2011-12-31 17:00:00

开始日期将是当月的第一天,时间为 09:00,最后一个日期(数组的最后一个元素)将始终是一年中最后一天的 17:00。

同样,应排除周末。

伪代码思路: 我想到了strtotime($start, "+1 one hour") 之类的东西,并检查了"if smaller than 17:00",但似乎没那么简单。

【问题讨论】:

  • 如果您不关心周六/周日,只需将 86400 秒(1 天)添加到任何开始时间即可进行迭代。从一整天开始,然后迭代直到达到时间范围。然后跳过它,直到它再次正常。

标签: php datetime date-arithmetic


【解决方案1】:

这是一个应该相当快的解决方案,因为它不使用字符串比较并且在循环内只有两个函数调用:

function hours()
{
    $start = mktime(0, 0, 0, date('n'), 1, date('Y'));
    $end = mktime(0, 0, 0, 1, 1, date('Y') + 1);
    $wday = date('w', $start);
    $result = array();
    for ($t = $start; $t < $end; $t += 3600 * 24) {
        if (($wday > 0) && ($wday < 6)) {
            for ($hour = 9; $hour <= 17; $hour++) {
                $result[] = date('Y-m-d', $t) . sprintf(' %02d:00:00', $hour);
            }
        }
        $wday = ($wday + 1) % 7;
    }
    return $result;
}

【讨论】:

    【解决方案2】:
    $datetime = new DateTime(); // Set your start date here
    do { // Iterate over .. dont know, a long time?
      do { // Iterate over the week ...
        $datetime->setTime(9,0,0);
        do { // Iterate over the hours ...
          echo $datetime->format('c') . PHP_EOL; // Do something with $datetime here
          $datetime->add(new DateInterval('PT1H'));
        } while ($datetime->format('G') < 18); // .. till < 18
        $datetime->add(new DateInterval('P1D')); // next day
      } while (!in_array($datetime->format('w'), array('0','6'))); // until we hit sunday or saturday
      $datetime->add(new DateInterval('P2D')); // next monday
    } while (true); // replace with your "end" expression
    

    目前未经测试。

    您也可以使用常见的区间字符串(如1 hour 等)http://php.net/dateinterval.createfromdatestring

    【讨论】:

    • 哇,没想到会这么简单;)
    【解决方案3】:

    我鼓励您使用精彩的DateTime 类及其相关类。在这里,你可以好好利用DatePeriod

    <?php
    
    $now = new DateTime('today'); // starting time 0.00 this morning
    $endOfYear = new DateTime('31 December this year 23:00'); // end time
    $interval = new DateInterval('PT1H'); // frequency -- every hour
    
    $times = array();
    
    foreach (new DatePeriod($now, $interval, $endOfYear ) as $datetime) {
    // $datetime is a DateTime object for the hour and time in question
        $dow = $datetime->format('w'); // 0 is Sunday
        if (($dow == '0') || ($dow == '6')) {
            continue; // miss Saturday and Sunday out
        }
    
        $time = $datetime->format('G'); // hour without leading 0
        if (($time < '9') || ($time > '17')) {
            continue;
        }
    
        $times[] = $datetime->format('r'); // output format
    }
    
    var_dump($times);
    

    显然,您可以配置这方面的各个方面,尤其是输出格式。根据您的目的,您可能更愿意将 DateTime 对象本身放入数组中。

    【讨论】:

      【解决方案4】:

      这个怎么样:

      $start = strtotime('2011-05-01');
      $end = strtotime('2011-12-31');
      
      $times = array();
      
      for ($i = $start; $i <= $end; $i += 24 * 3600)
      {
          if (date("D", $i) == "Sun" || date("D", $i) == "Sat")
          {
              continue;
          }
      
          for ($j = 9; $j <= 17; $j++)
          {
              $times []= date("Y-m-d $j:00:00", $i);
          }
      }
      

      外部循环遍历给定时间段内的所有日期。在外循环中,我们检查这一天是周六还是周日(周末),如果是,我们跳过那一天。如果不是周末,我们会遍历所有有效时间,同时将完整的日期和时间添加到数组中。

      【讨论】:

      • 几乎,如果 $start 是 strtotime(2011-05-01 09:00:00),它从 2011-05-02 9:00:00 开始;还应包括 2011-05-01 的时间。谢谢!!
      • 我不明白,所以周末除外,除了边界?
      • 我的错!没想到 5 月 1 日是周末。
      • 哈哈没问题,我只是对我错过了什么感到困惑。
      【解决方案5】:

      我将遍历所有日期,按小时递增,从 now 到年底,如下(显然是伪代码):

      for n = now until end of year
          if (date(n) is between 9:00 and 17:00) AND (if date(n) is not sat or sun)
              add to array
          end if
          increment n by 1 hour
      end
      

      【讨论】:

        【解决方案6】:

        一些提示:

        1. date("G", $some_timestamp) 以 24 小时格式为您提供一天中的小时
        2. date("N", $some_timestamp) 为您提供星期几,从 1(周一)到 7(周日)

        看看php manual for date

        编辑:您可以选择任何开始时间戳并添加 3600 以增加一小时,如果您的小时大于 17,您可以添加更大的步骤以直接到第二天早上,对于一个周末,然后做一个while ($timestamp &lt; $end_timestamp) {}

        【讨论】:

        • 是的,我很了解日期功能,只是不确定如何在上午 9 点和下午 5 点之间“增加一小时”。
        • @stef Ummmmmm,时间戳加3600?
        • Jeroen 的解决方案让我更接近了!
        • @Gordon 如果您设置时区,php 不会自动处理吗?
        • @jeroen php 会知​​道您的时区是否有 DST,但是如果您在 tz 中使用 DST 并将 3600 添加到时间戳并通过日期运行,则在 DST 发生时您将不会获得连续的小时数,这这就是为什么你不使用算术但strtotime('+1 hour')
        【解决方案7】:

        您可以使用两个嵌套循环计算日期并使用 date() 生成字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-03-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-02
          相关资源
          最近更新 更多