Search code examples
phpphp-7dateinterval

Decreasing DateInterval not producing result


Trying to get the last four Sundays, decrementing in a loop starting with the most recent Sunday first.

// most recent sunday
$mostRecentSunday = new DateTime('last sunday');

// four Sundays ago
$maxDateAttempt = clone $mostRecentSunday;
$maxDateAttempt->modify('-4 weeks');

// interval of one week (same as 7 days or "P7D")
$dateInterval = new DateInterval('P1W');

// isn't this supposedly supposed to switch the increasing interval to decreasing?
$dateInterval->invert = 1;

$dateRange = new DatePeriod($mostRecentSunday, $dateInterval, $maxDateAttempt);

foreach ($dateRange as $day) {
    echo $day->format('F j, Y');
}

Taking @hijarian's answer in this similar question, I thought setting the invert property would solve this, but I cannot get it to work. Then this comment in the PHP docs claims the DatePeriod class isn't even compatible with negative intervals. Anyone have some clarity in the issue? Maybe the PHP docs could use some improvement here.


Solution

  • That comment in the PHP docs is only partially correct. Everything I've read and experimented with so far seems to indicate that DatePeriod doesn't work with negative DateIntervals when using an end date. Maybe there's some initial check that the minimum is less than the maximum before it does anything, but I'm really not sure why it doesn't work.

    However, it does work if you use the recurrences constructor rather than setting an end date.

    $dateRange = new DatePeriod($mostRecentSunday, $dateInterval, 3);
    // using 3 rather than 4 because the initial value is one occurrence
    

    But you have to create your DateInterval like this instead:

    $dateInterval = DateInterval::createFromDateString('-1 week');
    

    Interestingly enough, that does not create a 7 day interval with invert=1. If you var_dump($dateInterval), you'll see public 'd' => int -7 and public 'invert' => int 0.


    But technically you don't need DateInterval or DatePeriod to accomplish this.

    for ($i=0, $date = new DateTime; $i < 4; $i++) {
        echo $date->modify('last sunday')->format('F j, Y');
    }