function testParseICalendarDate()
 {
     $dateTime = Sabre_VObject_DateTimeParser::parseDate('20100316');
     $expected = new DateTime('2010-03-16 00:00:00', new DateTimeZone('UTC'));
     $this->assertEquals($expected, $dateTime);
     $dateTime = Sabre_VObject_DateTimeParser::parse('20100316');
     $this->assertEquals($expected, $dateTime);
 }
/**
 * Parses some information from calendar objects, used for optimized
 * calendar-queries.
 *
 * Blantently copied from Sabre_CalDAV_Backend_PDO
 *
 * Returns an array with the following keys:
 *   * etag
 *   * size
 *   * componentType
 *   * firstOccurence
 *   * lastOccurence
 *
 * @param string $calendarData
 * @return array
 */
function getDenormalizedData($calendarData)
{
    $vObject = Sabre_VObject_Reader::read($calendarData);
    $componentType = null;
    $component = null;
    $firstOccurence = null;
    $lastOccurence = null;
    foreach ($vObject->getComponents() as $component) {
        if ($component->name !== 'VTIMEZONE') {
            $componentType = $component->name;
            break;
        }
    }
    if (!$componentType) {
        throw new Sabre_DAV_Exception_BadRequest('Calendar objects must have a VJOURNAL, VEVENT or VTODO component');
    }
    if ($componentType === 'VEVENT') {
        $firstOccurence = $component->DTSTART->getDateTime()->getTimeStamp();
        // Finding the last occurence is a bit harder
        if (!isset($component->RRULE)) {
            if (isset($component->DTEND)) {
                $lastOccurence = $component->DTEND->getDateTime()->getTimeStamp();
            } elseif (isset($component->DURATION)) {
                $endDate = clone $component->DTSTART->getDateTime();
                $endDate->add(Sabre_VObject_DateTimeParser::parse($component->DURATION->value));
                $lastOccurence = $endDate->getTimeStamp();
            } elseif ($component->DTSTART->getDateType() === Sabre_VObject_Property_DateTime::DATE) {
                $endDate = clone $component->DTSTART->getDateTime();
                $endDate->modify('+1 day');
                $lastOccurence = $endDate->getTimeStamp();
            } else {
                $lastOccurence = $firstOccurence;
            }
        } else {
            $it = new Sabre_VObject_RecurrenceIterator($vObject, (string) $component->UID);
            $maxDate = new DateTime(self::MAX_DATE);
            if ($it->isInfinite()) {
                $lastOccurence = $maxDate->getTimeStamp();
            } else {
                $end = $it->getDtEnd();
                while ($it->valid() && $end < $maxDate) {
                    $end = $it->getDtEnd();
                    $it->next();
                }
                $lastOccurence = $end->getTimeStamp();
            }
        }
    }
    return array('etag' => md5($calendarData), 'size' => strlen($calendarData), 'componentType' => $componentType, 'firstOccurence' => $firstOccurence, 'lastOccurence' => $lastOccurence);
}
 /**
  * Creates the iterator
  *
  * You should pass a VCALENDAR component, as well as the UID of the event
  * we're going to traverse.
  *
  * @param Sabre_VObject_Component $comp
  */
 public function __construct(Sabre_VObject_Component $vcal, $uid = null)
 {
     if (is_null($uid)) {
         if ($vcal->name === 'VCALENDAR') {
             throw new InvalidArgumentException('If you pass a VCALENDAR object, you must pass a uid argument as well');
         }
         $components = array($vcal);
         $uid = (string) $vcal->uid;
     } else {
         $components = $vcal->select('VEVENT');
     }
     foreach ($components as $component) {
         if ((string) $component->uid == $uid) {
             if (isset($component->{'RECURRENCE-ID'})) {
                 $this->overriddenEvents[$component->DTSTART->getDateTime()->getTimeStamp()] = $component;
                 $this->overriddenDates[] = $component->{'RECURRENCE-ID'}->getDateTime();
             } else {
                 $this->baseEvent = $component;
             }
         }
     }
     if (!$this->baseEvent) {
         throw new InvalidArgumentException('Could not find a base event with uid: ' . $uid);
     }
     $this->startDate = clone $this->baseEvent->DTSTART->getDateTime();
     $this->endDate = null;
     if (isset($this->baseEvent->DTEND)) {
         $this->endDate = clone $this->baseEvent->DTEND->getDateTime();
     } else {
         $this->endDate = clone $this->startDate;
         if (isset($this->baseEvent->DURATION)) {
             $this->endDate->add(Sabre_VObject_DateTimeParser::parse($this->baseEvent->DURATION->value));
         }
     }
     $this->currentDate = clone $this->startDate;
     $rrule = (string) $this->baseEvent->RRULE;
     $parts = explode(';', $rrule);
     foreach ($parts as $part) {
         list($key, $value) = explode('=', $part, 2);
         switch (strtoupper($key)) {
             case 'FREQ':
                 if (!in_array(strtolower($value), array('secondly', 'minutely', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'))) {
                     throw new InvalidArgumentException('Unknown value for FREQ=' . strtoupper($value));
                 }
                 $this->frequency = strtolower($value);
                 break;
             case 'UNTIL':
                 $this->until = Sabre_VObject_DateTimeParser::parse($value);
                 break;
             case 'COUNT':
                 $this->count = (int) $value;
                 break;
             case 'INTERVAL':
                 $this->interval = (int) $value;
                 break;
             case 'BYSECOND':
                 $this->bySecond = explode(',', $value);
                 break;
             case 'BYMINUTE':
                 $this->byMinute = explode(',', $value);
                 break;
             case 'BYHOUR':
                 $this->byHour = explode(',', $value);
                 break;
             case 'BYDAY':
                 $this->byDay = explode(',', strtoupper($value));
                 break;
             case 'BYMONTHDAY':
                 $this->byMonthDay = explode(',', $value);
                 break;
             case 'BYYEARDAY':
                 $this->byYearDay = explode(',', $value);
                 break;
             case 'BYWEEKNO':
                 $this->byWeekNo = explode(',', $value);
                 break;
             case 'BYMONTH':
                 $this->byMonth = explode(',', $value);
                 break;
             case 'BYSETPOS':
                 $this->bySetPos = explode(',', $value);
                 break;
             case 'WKST':
                 $this->weekStart = strtoupper($value);
                 break;
         }
     }
     // Parsing exception dates
     if (isset($this->baseEvent->EXDATE)) {
         foreach ($this->baseEvent->EXDATE as $exDate) {
             foreach (explode(',', (string) $exDate) as $exceptionDate) {
                 $this->exceptionDates[] = Sabre_VObject_DateTimeParser::parse($exceptionDate, $this->startDate->getTimeZone());
             }
         }
     }
 }