When\When::getOccurrencesBetween PHP Method

getOccurrencesBetween() public method

Get occurrences between two DateTimes, exclusive. Does not modify $this.
public getOccurrencesBetween ( $startDate, $endDate, $limit = NULL )
    public function getOccurrencesBetween($startDate, $endDate, $limit = NULL)
    {
        $thisClone = clone $this;
        // Enforce consistent time zones. Date comparisons don't require them, but +P1D loop does.
        if ($tz = $thisClone->getTimeZone()) {
            $startDate->setTimeZone($tz);
            $endDate->setTimeZone($tz);
        }
        $occurrences = array();
        if ($endDate <= $startDate) {
            return $occurrences;
        }
        // if existing UNTIL < startDate - we have nothing
        if (isset($thisClone->until) && $thisClone->until < $startDate) {
            return $occurrences;
        } elseif (!isset($thisClone->until)) {
            $thisClone->until = $endDate;
        }
        $thisClone->generateOccurrences();
        $all_occurrences = $thisClone->occurrences;
        // nothing found in $thisClone->generateOccurrences();
        if (empty($all_occurrences)) {
            return $occurrences;
        }
        $last_occurrence = end($all_occurrences);
        // if we've hit the rangeLimit, restart looking but start at this last_occurrence
        if ($thisClone->rangeLimit == count($all_occurrences) && $thisClone->startDate != $last_occurrence) {
            $thisClone->startDate = clone $last_occurrence;
            if (isset($thisClone->limit)) {
                $thisClone->limit = $thisClone->limit - 200;
            }
            // clear all occurrences before our start date
            foreach ($thisClone->occurrences as $key => $occurrence) {
                if ($occurrence < $startDate) {
                    unset($thisClone->occurrences[$key]);
                }
            }
            return $thisClone->getOccurrencesBetween($startDate, $endDate, $limit);
        }
        // if our last occurrence is is before our startDate, we have nothing
        if ($last_occurrence < $startDate) {
            return $occurrences;
        }
        // we have something to report, so reset our array pointer
        reset($all_occurrences);
        $count = 0;
        foreach ($all_occurrences as $occurrence) {
            // fastforward our pointer to where it's >= startDate
            if ($occurrence < $startDate) {
                continue;
            }
            // if current occurence is past our endDate - we're done
            if ($occurrence > $endDate) {
                break;
            }
            // if we reach getOccurrencesBetween()'s limit - we're done
            if (NULL != $limit && ++$count > $limit) {
                break;
            }
            $occurrences[] = $occurrence;
        }
        return $occurrences;
    }

Usage Example

 /**
  * Check that we don't alter results
  * DTSTART;TZID=America/New_York:19970902T090000
  * RRULE:FREQ=WEEKLY;
  *
  * '2001-07-03 09:00:00' = #201
  * '2001-07-31 09:00:00' = #205
  */
 function testCurruptingThis()
 {
     $results[] = new DateTime('2001-07-03 09:00:00');
     $results[] = new DateTime('2001-07-10 09:00:00');
     $results[] = new DateTime('2001-07-17 09:00:00');
     $results[] = new DateTime('2001-07-24 09:00:00');
     $results[] = new DateTime('2001-07-31 09:00:00');
     $r = new When();
     $r->startDate(new DateTime("19970902T090000"))->rrule("FREQ=WEEKLY;");
     $occurrences = $r->getOccurrencesBetween(new DateTime("20010521T090000"), new DateTime("20010612T090000"));
     $occurrences2 = $r->getOccurrencesBetween(new DateTime("20010702T090000"), new DateTime("20010801T090000"));
     foreach ($results as $key => $result) {
         $this->assertEquals($result, $occurrences2[$key]);
     }
 }