简体   繁体   中英

Php DateTime::setDate() not working on first DatePeriod iteration

In some reporting I'm looping through the next 6 months and figuring out a start/end ranges to do calculations with. For each month this loops through, setDate() works correctly EXCEPT for the first month.

# Loop over the next 6 months (from start of this month)
$now = new DateTime("first day of this month", new DateTimeZone("Pacific/Auckland"));

$end = clone $now;
$end->modify("+6 month");

$int = new DateInterval("P1M");
$period = new DatePeriod($now, $int, $end);

# For each month, work out the start/end dates and times for the reports
foreach ($period as $month) {
    $start = clone $month;
    $start->setDate($start->format("Y"), $start->format("m"), 1);
    $start->setTime(0, 0, 0);

    $end = clone $month;
    $end->setDate($end->format("Y"), $end->format("m"), $end->format("t"));
    $end->setTime(23, 23, 59);

    # Dumping out data here shows weirdness below
}

No matter what, the first month end comes out as the 1st. Even if I manually set it to any other valid day integer. I've stripped this to the bare example and it's still doing it.

string(19) "2016-05-01 00:00:00"
string(19) "2016-05-01 23:23:59" <- Huh? This should be 31
===========
string(19) "2016-06-01 00:00:00"
string(19) "2016-06-30 23:23:59"
===========
string(19) "2016-07-01 00:00:00"
string(19) "2016-07-31 23:23:59"
...etc...

I'm on php 5.5.26

Bug in PHP when creating a DateTime object using certain relative formats .

PHP Bug #63863 DateTime:setDate() date not used after modify("last day of...")

This seems to happen only when using certain relative formats to create the DateTime object, such as 'last day of next month' or 'first day of this month' , however 'last sat of July 2008' does not cause the error.

Thanks to Mike in the comments.

Simple workaround, use a different approach to creating the intial $now DateTime object.

https://eval.in/577984

# Loop over the next 6 months (from start of this month)
$now = new DateTime("now", new DateTimeZone("Pacific/Auckland"));
$now->setDate($now->format("Y"), $now->format("m"), 1);

$end = clone $now;
$end->modify("+6 month");

$int = new DateInterval("P1M");
$period = new DatePeriod($now, $int, $end);

# For each month, work out the start/end dates and times for the reports
foreach ($period as $month) {
    $start = clone $month;
    $start->setDate($start->format("Y"), $start->format("m"), 1);
    $start->setTime(0, 0, 0);

    $end = clone $month;
    $end->setDate($end->format("Y"), $end->format("m"), $end->format("t"));
    $end->setTime(23, 23, 59);

    echo $start->format('Y-m-d H:i:s') . "\n";
    echo $end->format('Y-m-d H:i:s') . "\n";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM