具有 DatePeriod 迭代的函数在第二次函数调用时缺少一天


Function with DatePeriod iteration is missing one day on second function call

我有一个带有以下函数的代码点火器函数:

/**
 * Returns Days within a period of time defined by two DateTime objects
 *
 *
 * @param $start DateTime
 * @param $end DateTime
 * @param $points
 *
 * $return['days'][x]
 */
public function getDaysInRange(DateTime $start,DateTime $end){
    $this->debug(memory_get_usage()/1024,"Memory Usage in KB");
    $this->debug(memory_get_peak_usage()/1024,"Peak Memory Usage in KB");
    $this->debug(memory_get_peak_usage(true)/1024,"Real Peak Memory Usage in KB");
    $interval = new DateInterval('P1D'); // 1Day Interval
    $startC= clone $start;
    $startC->setTime(0,0,0);
    $endC = clone $end;
    $endC->setTime(0,0,0);
    // Workaround because last day of period is not in Iterator
    $endC->add($interval);
    $this->debug($startC,"Get Days in Range Start");
    $this->debug($endC,"Get Days in Range End");
    $daterange = new DatePeriod($startC, $interval,$endC);
    $return = array('days' => array());
    foreach($daterange as $date){
        $this->debug($date->format("Y-m-d"),"Single Day in Daterange");
        $return['days'][] = $date->format("Y-m-d");
    }
    $this->debug($return,"Return of getDays in Range");
    return $return;
}

当我使用不同的 DateTime 对象调用此函数 2 次时。

             [start] => DateTime Object
                        (
                            [date] => 2014-03-01 00:00:00
                            [timezone_type] => 1
                            [timezone] => +00:00
                        )
                    [end] => DateTime Object
                        (
                            [date] => 2014-03-31 00:00:00
                            [timezone_type] => 1
                            [timezone] => +00:00
                        )
       [start] => DateTime Object
                        (
                            [date] => 2014-03-01 00:00:00
                            [timezone_type] => 1
                            [timezone] => +00:00
                        )
                    [end] => DateTime Object
                        (
                            [date] => 2014-03-31 00:00:00
                            [timezone_type] => 1
                            [timezone] => +00:00
                        )

从时间戳创建:

  $begin =   DateTime::createFromFormat('U',  $filter['start'], new DateTimeZone('UTC'));
  $end =   DateTime::createFromFormat('U',  $filter['end'], new DateTimeZone('UTC'));

第一个调用正确返回:

  (
    [days] => Array
(
    [0] => 2014-03-01
    [1] => 2014-03-02
    [2] => 2014-03-03
    [3] => 2014-03-04
    [4] => 2014-03-05
    [5] => 2014-03-06
    [6] => 2014-03-07
    [7] => 2014-03-08
    [8] => 2014-03-09
    [9] => 2014-03-10
    [10] => 2014-03-11
    [11] => 2014-03-12
    [12] => 2014-03-13
    [13] => 2014-03-14
    [14] => 2014-03-15
    [15] => 2014-03-16
    [16] => 2014-03-17
    [17] => 2014-03-18
    [18] => 2014-03-19
    [19] => 2014-03-20
    [20] => 2014-03-21
    [21] => 2014-03-22
    [22] => 2014-03-23
    [23] => 2014-03-24
    [24] => 2014-03-25
    [25] => 2014-03-26
    [26] => 2014-03-27
    [27] => 2014-03-28
    [28] => 2014-03-29
    [29] => 2014-03-30
    [30] => 2014-03-31
)
)

第二次调用重新运行以下内容,滞后于"2014-03-25"

(
    [days] => Array
        (
            [0] => 2014-03-01
            [1] => 2014-03-02
            [2] => 2014-03-03
            [3] => 2014-03-04
            [4] => 2014-03-05
            [5] => 2014-03-06
            [6] => 2014-03-07
            [7] => 2014-03-08
            [8] => 2014-03-09
            [9] => 2014-03-10
            [10] => 2014-03-11
            [11] => 2014-03-12
            [12] => 2014-03-13
            [13] => 2014-03-14
            [14] => 2014-03-15
            [15] => 2014-03-16
            [16] => 2014-03-17
            [17] => 2014-03-18
            [18] => 2014-03-19
            [19] => 2014-03-20
            [20] => 2014-03-21
            [21] => 2014-03-22
            [22] => 2014-03-23
            [23] => 2014-03-24
            [24] => 2014-03-26
            [25] => 2014-03-27
            [26] => 2014-03-28
            [27] => 2014-03-29
            [28] => 2014-03-30
            [29] => 2014-03-31
        )
)

我首先想到的是副作用。我错过了一个吗?

在php中,bugtracker对我的问题没有什么具体的,但是关于DatePeriod奇怪行为的其他一些报告。在服务器上运行一个相当旧的php 5.3.10。

在使用较新版本的 php 重现该错误之前,我尝试在 Codeigniter 之外重现它。在它外面,它正在各种星座中工作。请参阅:http://pastebin.com/FgPTSMEz

因此,我想到了代码点火器环境中可能占用大量内存,这可能会导致错误。但是代码点火器内部的内存使用量仅为4-5 MB。我在独立的测试文件中复制了它,并读取了 5 MB 的文本文件。

目前我不知道问题是什么。

找到其 PHP 错误 #62561 用 5.4 修复的原因

https://bugs.php.net/bug.php?id=62561

在详细的调试回显中,您将看到:

Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-01 00:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-02 01:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-03 02:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-04 03:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-05 04:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-06 05:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-07 06:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-08 07:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-09 08:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-10 09:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-11 10:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-12 11:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-13 12:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-14 13:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-15 14:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-16 15:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-17 16:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-18 17:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-19 18:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-20 19:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-21 20:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-22 21:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-23 22:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-24 23:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-26 00:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-27 01:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-28 02:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-29 03:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-30 04:00:00Access_Model.php>获取天数范围 (1067) - 日期范围内的单天2014-03-31 05:00:00

快速修复/解决方法:

由于该错误是通过从具有本地时区以外的其他时区的时间戳创建日期时间而派生的,因此我编写了以下快速修复

/**
 * Returns Days within a period of time defined by two DateTime objects
 *
 *
 * @param $start DateTime
 * @param $end DateTime
 * @param $points
 *
 * $return['days'][x]
 */
public function getDaysInRange(DateTime $start,DateTime $end){
    // Creation Workaround for Bug https://bugs.php.net/bug.php?id=62561
    $startC= new DateTime($start->format('Y-m-d'), new DateTimeZone('UTC')) ;
    $startC->setTime(0,0,0);
    $endC = new DateTime($end->format('Y-m-d'), new DateTimeZone('UTC')) ;
    $endC->setTime(0,0,0);

    $this->debug($startC,"Get Days in Range Start");
    $this->debug($endC,"Get Days in Range End");
    $return = array('days' => array());

    // Workaround because last day of period is not in Iterator
    $endC->modify('+1 day');
while($startC < $endC) {
            $this->debug($startC->format("Y-m-d H:i:s"),"Single Day in Daterange Modify");
    $return['days'][] = $startC->format('Y-m-d');
    $startC->modify('+1 day');
}
    $this->debug($return,"Return of getDays in Range");
    return $return;
}