/**
  * set calendar component property rdate
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.21.11 - 2015-03-10
  * @param array   $rdates
  * @param array   $params
  * @param integer $index
  * @uses calendarComponent::getConfig()
  * @uses iCalUtilityFunctions::_setMval()
  * @uses calendarComponent::$rdate
  * @uses iCalUtilityFunctions::_setParams()
  * @uses calendarComponent::$objName
  * @uses iCalUtilityFunctions::_isArrayDate()
  * @uses iCalUtilityFunctions::_chkdatecfg()
  * @uses iCalUtilityFunctions::_existRem()
  * @uses iCalUtilityFunctions::_strDate2arr()
  * @uses iCalUtilityFunctions::_isArrayTimestampDate()
  * @uses iCalUtilityFunctions::_isOffset()
  * @uses iCalUtilityFunctions::_timestamp2date()
  * @uses iCalUtilityFunctions::_chkDateArr()
  * @uses iCalUtilityFunctions::$fmt
  * @uses iCalUtilityFunctions::_strdate2date()
  * @uses iCalUtilityFunctions::_duration2arr()
  * @uses iCalUtilityFunctions::_durationStr2arr()
  * @return bool
  */
 function setRdate($rdates, $params = FALSE, $index = FALSE)
 {
     if (empty($rdates)) {
         if ($this->getConfig('allowEmpty')) {
             iCalUtilityFunctions::_setMval($this->rdate, '', $params, FALSE, $index);
             return TRUE;
         } else {
             return FALSE;
         }
     }
     $input = array('params' => iCalUtilityFunctions::_setParams($params, array('VALUE' => 'DATE-TIME')));
     if (in_array($this->objName, array('vtimezone', 'standard', 'daylight'))) {
         unset($input['params']['TZID']);
         $input['params']['VALUE'] = 'DATE-TIME';
     }
     $zArr = array('GMT', 'UTC', 'Z');
     $toZ = isset($params['TZID']) && in_array(strtoupper($params['TZID']), $zArr) ? TRUE : FALSE;
     /*  check if PERIOD, if not set */
     if ((!isset($input['params']['VALUE']) || !in_array($input['params']['VALUE'], array('DATE', 'PERIOD'))) && isset($rdates[0]) && is_array($rdates[0]) && 2 == count($rdates[0]) && isset($rdates[0][0]) && isset($rdates[0][1]) && !isset($rdates[0]['timestamp']) && (is_array($rdates[0][0]) && (isset($rdates[0][0]['timestamp']) || iCalUtilityFunctions::_isArrayDate($rdates[0][0])) || is_string($rdates[0][0]) && 8 <= strlen(trim($rdates[0][0]))) && (is_array($rdates[0][1]) || is_string($rdates[0][1]) && 3 <= strlen(trim($rdates[0][1])))) {
         $input['params']['VALUE'] = 'PERIOD';
     }
     /* check 1:st date, upd. $parno (opt) and save ev. timezone **/
     $date = reset($rdates);
     if (isset($input['params']['VALUE']) && 'PERIOD' == $input['params']['VALUE']) {
         // PERIOD
         $date = reset($date);
     }
     iCalUtilityFunctions::_chkdatecfg($date, $parno, $input['params']);
     iCalUtilityFunctions::_existRem($input['params'], 'VALUE', 'DATE-TIME');
     // remove default
     foreach ($rdates as $rpix => $theRdate) {
         $inputa = null;
         iCalUtilityFunctions::_strDate2arr($theRdate);
         if (is_array($theRdate)) {
             if (isset($input['params']['VALUE']) && 'PERIOD' == $input['params']['VALUE']) {
                 // PERIOD
                 foreach ($theRdate as $rix => $rPeriod) {
                     iCalUtilityFunctions::_strDate2arr($theRdate);
                     if (is_array($rPeriod)) {
                         if (iCalUtilityFunctions::_isArrayTimestampDate($rPeriod)) {
                             // timestamp
                             if (isset($rPeriod['tz']) && !iCalUtilityFunctions::_isOffset($rPeriod['tz'])) {
                                 if (isset($input['params']['TZID'])) {
                                     $rPeriod['tz'] = $input['params']['TZID'];
                                 } else {
                                     $input['params']['TZID'] = $rPeriod['tz'];
                                 }
                             }
                             $inputab = iCalUtilityFunctions::_timestamp2date($rPeriod, $parno);
                         } elseif (iCalUtilityFunctions::_isArrayDate($rPeriod)) {
                             $d = 3 < count($rPeriod) ? iCalUtilityFunctions::_chkDateArr($rPeriod, $parno) : iCalUtilityFunctions::_chkDateArr($rPeriod, 6);
                             if (isset($d['tz']) && 'Z' != $d['tz'] && iCalUtilityFunctions::_isOffset($d['tz'])) {
                                 $strdate = sprintf(iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz']);
                                 $inputab = iCalUtilityFunctions::_strdate2date($strdate, 7);
                                 unset($inputab['unparsedtext']);
                             } else {
                                 $inputab = $d;
                             }
                         } elseif (1 == count($rPeriod) && 8 <= strlen(reset($rPeriod))) {
                             // text-date
                             $inputab = iCalUtilityFunctions::_strdate2date(reset($rPeriod), $parno);
                             unset($inputab['unparsedtext']);
                         } else {
                             // array format duration
                             $inputab = iCalUtilityFunctions::_duration2arr($rPeriod);
                         }
                     } elseif (3 <= strlen(trim($rPeriod)) && in_array($rPeriod[0], array('P', '+', '-'))) {
                         if ('P' != $rPeriod[0]) {
                             $rPeriod = substr($rPeriod, 1);
                         }
                         $inputab = iCalUtilityFunctions::_durationStr2arr($rPeriod);
                     } elseif (8 <= strlen(trim($rPeriod))) {
                         // text date ex. 2006-08-03 10:12:18
                         $inputab = iCalUtilityFunctions::_strdate2date($rPeriod, $parno);
                         unset($inputab['unparsedtext']);
                     }
                     if (0 == $rpix && 0 == $rix) {
                         if (isset($inputab['tz']) && in_array(strtoupper($inputab['tz']), $zArr)) {
                             $inputab['tz'] = 'Z';
                             $toZ = TRUE;
                         }
                     } else {
                         if (isset($inputa[0]['tz']) && 'Z' == $inputa[0]['tz'] && isset($inputab['year'])) {
                             $inputab['tz'] = 'Z';
                         } else {
                             unset($inputab['tz']);
                         }
                     }
                     if ($toZ && isset($inputab['year'])) {
                         $inputab['tz'] = 'Z';
                     }
                     $inputa[] = $inputab;
                 }
             } elseif (iCalUtilityFunctions::_isArrayTimestampDate($theRdate)) {
                 // timestamp
                 if (isset($theRdate['tz']) && !iCalUtilityFunctions::_isOffset($theRdate['tz'])) {
                     if (isset($input['params']['TZID'])) {
                         $theRdate['tz'] = $input['params']['TZID'];
                     } else {
                         $input['params']['TZID'] = $theRdate['tz'];
                     }
                 }
                 $inputa = iCalUtilityFunctions::_timestamp2date($theRdate, $parno);
             } else {
                 // date[-time]
                 $inputa = iCalUtilityFunctions::_chkDateArr($theRdate, $parno);
                 if (isset($inputa['tz']) && 'Z' != $inputa['tz'] && iCalUtilityFunctions::_isOffset($inputa['tz'])) {
                     $strdate = sprintf(iCalUtilityFunctions::$fmt['YmdHise'], (int) $inputa['year'], (int) $inputa['month'], (int) $inputa['day'], (int) $inputa['hour'], (int) $inputa['min'], (int) $inputa['sec'], $inputa['tz']);
                     $inputa = iCalUtilityFunctions::_strdate2date($strdate, 7);
                     unset($inputa['unparsedtext']);
                 }
             }
         } elseif (8 <= strlen(trim($theRdate))) {
             // text date ex. 2006-08-03 10:12:18
             $inputa = iCalUtilityFunctions::_strdate2date($theRdate, $parno);
             unset($inputa['unparsedtext']);
             if ($toZ) {
                 $inputa['tz'] = 'Z';
             }
         }
         if (!isset($input['params']['VALUE']) || 'PERIOD' != $input['params']['VALUE']) {
             // no PERIOD
             if (0 == $rpix && !$toZ) {
                 $toZ = isset($inputa['tz']) && in_array(strtoupper($inputa['tz']), $zArr) ? TRUE : FALSE;
             }
             if ($toZ) {
                 $inputa['tz'] = 'Z';
             }
             if (3 == $parno) {
                 unset($inputa['hour'], $inputa['min'], $inputa['sec'], $inputa['tz']);
             } elseif (isset($inputa['tz'])) {
                 $inputa['tz'] = (string) $inputa['tz'];
             }
             if (isset($input['params']['TZID']) || isset($input['value'][0]) && !isset($input['value'][0]['tz'])) {
                 if (!$toZ) {
                     unset($inputa['tz']);
                 }
             }
         }
         $input['value'][] = $inputa;
     }
     if (3 == $parno) {
         $input['params']['VALUE'] = 'DATE';
         unset($input['params']['TZID']);
     }
     if ($toZ) {
         unset($input['params']['TZID']);
     }
     iCalUtilityFunctions::_setMval($this->rdate, $input['value'], $input['params'], FALSE, $index);
     return TRUE;
 }
Пример #2
0
 public static function _strdate2date($datetime, $parno = FALSE, $wtz = null)
 {
     // save original input string to return it later
     $unparseddatetime = $datetime;
     $datetime = (string) trim($datetime);
     $tz = null;
     $offset = 0;
     $tzSts = FALSE;
     $len = strlen($datetime);
     if ('Z' == substr($datetime, -1)) {
         $tz = 'Z';
         $datetime = trim(substr($datetime, 0, $len - 1));
         $tzSts = TRUE;
         $len = 88;
     }
     if (iCalUtilityFunctions::_isOffset(substr($datetime, -5, 5))) {
         // [+/-]NNNN offset
         $tz = substr($datetime, -5, 5);
         $datetime = trim(substr($datetime, 0, $len - 5));
         $len = strlen($datetime);
     } elseif (iCalUtilityFunctions::_isOffset(substr($datetime, -7, 7))) {
         // [+/-]NNNNNN offset
         $tz = substr($datetime, -7, 7);
         $datetime = trim(substr($datetime, 0, $len - 7));
         $len = strlen($datetime);
     } elseif (empty($wtz) && ctype_digit(substr($datetime, 0, 4)) && ctype_digit(substr($datetime, -2, 2)) && iCalUtilityFunctions::_strDate2arr($datetime)) {
         $output = $datetime;
         if (!empty($tz)) {
             $output['tz'] = 'Z';
         }
         $output['unparsedtext'] = $unparseddatetime;
         return $output;
     } else {
         $cx = $tx = 0;
         //  find any trailing timezone or offset
         for ($cx = -1; $cx > 9 - $len; $cx--) {
             $char = substr($datetime, $cx, 1);
             if (' ' == $char || ctype_digit($char)) {
                 break;
             } else {
                 $tx--;
             }
             // tz length counter
         }
         if (0 > $tx) {
             // if any
             $tz = substr($datetime, $tx);
             $datetime = trim(substr($datetime, 0, $len + $tx));
             $len = strlen($datetime);
         }
         if (17 <= $len || ctype_digit(substr($datetime, 0, 8)) && 'T' == substr($datetime, 8, 1) && ctype_digit(substr($datetime, -6, 6)) || ctype_digit(substr($datetime, 0, 14))) {
             $len = 88;
             $tzSts = TRUE;
         } else {
             $tz = null;
         }
         // no tz for Y-m-d dates
     }
     if (empty($tz) && !empty($wtz)) {
         $tz = $wtz;
     }
     if (17 >= $len) {
         // any Y-m-d textual date
         $tz = null;
     }
     if (!empty($tz) && 17 < $len) {
         // tz set AND long textual datetime
         if ('Z' != $tz && iCalUtilityFunctions::_isOffset($tz)) {
             $offset = (string) iCalUtilityFunctions::_tz2offset($tz) * -1;
             $tz = 'UTC';
             $tzSts = TRUE;
         } elseif (!empty($wtz)) {
             $tzSts = TRUE;
         }
         $tz = trim($tz);
         if ('Z' == $tz || 'GMT' == strtoupper($tz)) {
             $tz = 'UTC';
         }
         if (0 < substr_count($datetime, '-')) {
             $datetime = str_replace('-', '/', $datetime);
         }
         try {
             $d = new DateTime($datetime, new DateTimeZone($tz));
             if (0 != $offset) {
                 // adjust for offset
                 $d->modify($offset . ' seconds');
             }
             $datestring = $d->format('Y-m-d-H-i-s');
             unset($d);
         } catch (Exception $e) {
             $datestring = date('Y-m-d-H-i-s', strtotime($datetime));
         }
     } else {
         $datestring = date('Y-m-d-H-i-s', strtotime($datetime));
     }
     // echo "<tr><td>&nbsp;<td colspan='3'>_strdate2date input=$datetime, tz=$tz, offset=$offset, wtz=$wtz, len=$len, prepDate=$datestring\n";
     if ('UTC' == $tz) {
         $tz = 'Z';
     }
     $d = explode('-', $datestring);
     $output = array('year' => $d[0], 'month' => $d[1], 'day' => $d[2]);
     if (FALSE !== $parno && 3 != $parno || FALSE === $parno && 'Z' == $tz || FALSE === $parno && 'Z' != $tz && 0 != $d[3] + $d[4] + $d[5] && 17 < $len) {
         // !parno and !UTC and 0 != hour+min+sec and long input text
         $output['hour'] = $d[3];
         $output['min'] = $d[4];
         $output['sec'] = $d[5];
         if (($tzSts || 7 == $parno) && !empty($tz)) {
             $output['tz'] = $tz;
         }
     }
     // return original string in the array in case strtotime failed to make sense of it
     $output['unparsedtext'] = $unparseddatetime;
     return $output;
 }
 /**
  * ensures internal date-time/date format for input date-time/date in string fromat
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.21.11 - 2015-03-15
  * Modified to also return original string value by Yitzchok Lavi <*****@*****.**>
  * @param array $datetime
  * @param int   $parno optional, default FALSE
  * @param moxed $wtz optional, default null
  * @uses iCalUtilityFunctions::_isOffset()
  * @uses iCalUtilityFunctions::_strDate2arr()
  * @uses iCalUtilityFunctions::_isOffset()
  * @uses iCalUtilityFunctions::_tz2offset()
  * @uses iCalUtilityFunctions::$fmt
  * @return array
  */
 public static function _strdate2date($datetime, $parno = FALSE, $wtz = null)
 {
     $unparseddatetime = $datetime;
     $datetime = (string) trim($datetime);
     $tz = null;
     $offset = 0;
     $tzSts = FALSE;
     $len = strlen($datetime);
     if ('Z' == substr($datetime, -1)) {
         $tz = 'Z';
         $datetime = trim(substr($datetime, 0, $len - 1));
         $tzSts = TRUE;
     }
     if (iCalUtilityFunctions::_isOffset(substr($datetime, -5, 5))) {
         // [+/-]NNNN offset
         $tz = substr($datetime, -5, 5);
         $datetime = trim(substr($datetime, 0, $len - 5));
     } elseif (iCalUtilityFunctions::_isOffset(substr($datetime, -7, 7))) {
         // [+/-]NNNNNN offset
         $tz = substr($datetime, -7, 7);
         $datetime = trim(substr($datetime, 0, $len - 7));
     } elseif (empty($wtz) && ctype_digit(substr($datetime, 0, 4)) && ctype_digit(substr($datetime, -2, 2)) && iCalUtilityFunctions::_strDate2arr($datetime)) {
         $output = $datetime;
         if (!empty($tz)) {
             $output['tz'] = 'Z';
         }
         $output['unparsedtext'] = $unparseddatetime;
         return $output;
     } else {
         $cx = $tx = 0;
         //  find any trailing timezone or offset
         $len = strlen($datetime);
         for ($cx = -1; $cx > 9 - $len; $cx--) {
             $char = substr($datetime, $cx, 1);
             if (' ' == $char || ctype_digit($char)) {
                 break;
             } else {
                 $tx--;
             }
             // tz length counter
         }
         if (0 > $tx) {
             // if any
             $tz = substr($datetime, $tx);
             $datetime = trim(substr($datetime, 0, $len + $tx));
         }
         if (ctype_digit(substr($datetime, 0, 8)) && 'T' == substr($datetime, 8, 1) && ctype_digit(substr($datetime, -6, 6)) || ctype_digit(substr($datetime, 0, 14))) {
             $tzSts = TRUE;
         }
     }
     if (empty($tz) && !empty($wtz)) {
         $tz = $wtz;
     }
     if (3 == $parno) {
         $tz = null;
     }
     if (!empty($tz)) {
         // tz set
         if ('Z' != $tz && iCalUtilityFunctions::_isOffset($tz)) {
             $offset = (string) iCalUtilityFunctions::_tz2offset($tz) * -1;
             $tz = 'UTC';
             $tzSts = TRUE;
         } elseif (!empty($wtz)) {
             $tzSts = TRUE;
         }
         $tz = trim($tz);
         if ('Z' == $tz || 'GMT' == strtoupper($tz)) {
             $tz = 'UTC';
         }
         if (0 < substr_count($datetime, '-')) {
             $datetime = str_replace('-', '/', $datetime);
         }
         try {
             $d = new DateTime($datetime, new DateTimeZone($tz));
             if (0 != $offset) {
                 // adjust for offset
                 $d->modify($offset . ' seconds');
             }
             $datestring = $d->format(iCalUtilityFunctions::$fmt['YmdHis3']);
             unset($d);
         } catch (Exception $e) {
             $datestring = date(iCalUtilityFunctions::$fmt['YmdHis3'], strtotime($datetime));
         }
     } else {
         $datestring = date(iCalUtilityFunctions::$fmt['YmdHis3'], strtotime($datetime));
     }
     if ('UTC' == $tz) {
         $tz = 'Z';
     }
     $d = explode('-', $datestring);
     $output = array('year' => $d[0], 'month' => $d[1], 'day' => $d[2]);
     if (!$parno || 3 != $parno) {
         // parno is set to 6 or 7
         $output['hour'] = $d[3];
         $output['min'] = $d[4];
         $output['sec'] = $d[5];
         if (($tzSts || 7 == $parno) && !empty($tz)) {
             $output['tz'] = $tz;
         }
     }
     // return original string in the array in case strtotime failed to make sense of it
     $output['unparsedtext'] = $unparseddatetime;
     return $output;
 }
 /**
  * convert format for input date (UTC) to internal date with parameters
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.11.8 - 2012-01-19
  * @param mixed $year
  * @param mixed $month optional
  * @param int $day optional
  * @param int $hour optional
  * @param int $min optional
  * @param int $sec optional
  * @param array $params optional
  * @return array
  */
 public static function _setDate2($year, $month = FALSE, $day = FALSE, $hour = FALSE, $min = FALSE, $sec = FALSE, $params = FALSE)
 {
     $input = null;
     iCalUtilityFunctions::_strDate2arr($year);
     if (iCalUtilityFunctions::_isArrayDate($year)) {
         $input['value'] = iCalUtilityFunctions::_date_time_array($year, 7);
         $input['params'] = iCalUtilityFunctions::_setParams($month, array('VALUE' => 'DATE-TIME'));
     } elseif (iCalUtilityFunctions::_isArrayTimestampDate($year)) {
         $input['value'] = iCalUtilityFunctions::_timestamp2date($year, 7);
         $input['params'] = iCalUtilityFunctions::_setParams($month, array('VALUE' => 'DATE-TIME'));
     } elseif (8 <= strlen(trim($year))) {
         // ex. 2006-08-03 10:12:18
         $input['value'] = iCalUtilityFunctions::_date_time_string($year, 7);
         unset($input['value']['unparsedtext']);
         $input['params'] = iCalUtilityFunctions::_setParams($month, array('VALUE' => 'DATE-TIME'));
     } else {
         $input['value'] = array('year' => $year, 'month' => $month, 'day' => $day, 'hour' => $hour, 'min' => $min, 'sec' => $sec);
         $input['params'] = iCalUtilityFunctions::_setParams($params, array('VALUE' => 'DATE-TIME'));
     }
     $parno = iCalUtilityFunctions::_existRem($input['params'], 'VALUE', 'DATE-TIME', 7);
     // remove default
     if (!isset($input['value']['hour'])) {
         $input['value']['hour'] = 0;
     }
     if (!isset($input['value']['min'])) {
         $input['value']['min'] = 0;
     }
     if (!isset($input['value']['sec'])) {
         $input['value']['sec'] = 0;
     }
     if (isset($input['params']['TZID']) && !empty($input['params']['TZID'])) {
         if ('Z' != $input['params']['TZID'] && iCalUtilityFunctions::_isOffset($input['params']['TZID'])) {
             // utc offset in TZID to tz
             $input['value']['tz'] = $input['params']['TZID'];
             unset($input['params']['TZID']);
         } elseif (in_array(strtoupper($input['params']['TZID']), array('GMT', 'UTC', 'Z'))) {
             // time zone Z
             $input['value']['tz'] = 'Z';
             unset($input['params']['TZID']);
         }
     }
     if (!isset($input['value']['tz']) || !iCalUtilityFunctions::_isOffset($input['value']['tz'])) {
         $input['value']['tz'] = 'Z';
     }
     return $input;
 }
 /**
  * select components from calendar on date or selectOption basis
  *
  * Ensure DTSTART is set for every component.
  * No date controls occurs.
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.21.11 - 2015-03-31
  * @param mixed $startY optional,      (int) start Year,  default current Year
  *                                ALT. (obj) start date (datetime)
  *                                ALT. array selecOptions ( *[ <propName> => <uniqueValue> ] )
  * @param mixed $startM optional,      (int) start Month, default current Month
  *                                ALT. (obj) end date (datetime)
  * @param int   $startD optional, start Day,   default current Day
  * @param int   $endY   optional, end   Year,  default $startY
  * @param int   $endM   optional, end   Month, default $startM
  * @param int   $endD   optional, end   Day,   default $startD
  * @param mixed $cType  optional, calendar component type(-s), default FALSE=all else string/array type(-s)
  * @param bool  $flat   optional, FALSE (default) => output : array[Year][Month][Day][]
  *                                TRUE            => output : array[] (ignores split)
  * @param bool  $any    optional, TRUE (default) - select component(-s) that occurs within period
  *                                FALSE          - only component(-s) that starts within period
  * @param bool  $split  optional, TRUE (default) - one component copy every DAY it occurs during the
  *                                                 period (implies flat=FALSE)
  *                                FALSE          - one occurance of component only in output array
  * @uses vcalendar::$components
  * @uses vcalendar::selectComponents2()
  * @uses iCalUtilityFunctions::$vComps
  * @uses calendarComponent::$objName
  * @uses calendarComponent::getProperty()
  * @uses iCaldateTime::factory()
  * @uses iCaldateTime::getTimezoneName()
  * @uses iCaldateTime::getTime()
  * @uses iCalUtilityFunctions::$fmt
  * @uses iCaldateTime::$SCbools
  * @uses iCaldateTime::format()
  * @uses iCalUtilityFunctions::_strDate2arr()
  * @uses iCalUtilityFunctions::_recur2date()
  * @uses iCalUtilityFunctions::_inScope()
  * @uses calendarComponent::copy()
  * @uses calendarComponent::setProperty()
  * @uses iCalUtilityFunctions::$fmt
  * @uses calendarComponent::deleteProperty()
  * @uses iCalUtilityFunctions::_setSortArgs()
  * @uses iCalUtilityFunctions::_cmpfcn()
  * @return array or FALSE
  */
 function selectComponents($startY = FALSE, $startM = FALSE, $startD = FALSE, $endY = FALSE, $endM = FALSE, $endD = FALSE, $cType = FALSE, $flat = FALSE, $any = TRUE, $split = TRUE)
 {
     /* check  if empty calendar */
     if (0 >= count($this->components)) {
         return FALSE;
     }
     if (is_array($startY)) {
         return $this->selectComponents2($startY);
     }
     /* check default dates */
     if (is_a($startY, 'DateTime') && is_a($startM, 'DateTime')) {
         $endY = $startM->format('Y');
         $endM = $startM->format('m');
         $endD = $startM->format('d');
         $startD = $startY->format('d');
         $startM = $startY->format('m');
         $startY = $startY->format('Y');
     } else {
         if (!$startY) {
             $startY = date('Y');
         }
         if (!$startM) {
             $startM = date('m');
         }
         if (!$startD) {
             $startD = date('d');
         }
         if (!$endY) {
             $endY = $startY;
         }
         if (!$endM) {
             $endM = $startM;
         }
         if (!$endD) {
             $endD = $startD;
         }
     }
     // echo "selectComp args={$startY}-{$startM}-{$startD} - {$endY}-{$endM}-{$endD}<br>\n"; $tcnt = 0;// test ###
     /* check component types */
     if (empty($cType)) {
         $cType = iCalUtilityFunctions::$vComps;
     } else {
         if (!is_array($cType)) {
             $cType = array($cType);
         }
         $cType = array_map('strtolower', $cType);
         foreach ($cType as $cix => $theType) {
             if (!in_array($theType, iCalUtilityFunctions::$vComps)) {
                 $cType[$cix] = 'vevent';
             }
         }
         $cType = array_unique($cType);
     }
     if (FALSE === $flat && FALSE === $any) {
         // invalid combination
         $split = FALSE;
     }
     if (TRUE === $flat && TRUE === $split) {
         // invalid combination
         $split = FALSE;
     }
     /* iterate components */
     $result = array();
     $this->sort('UID');
     $compUIDcmp = null;
     $exdatelist = $recurridList = array();
     $intervalP1D = new DateInterval('P1D');
     foreach ($this->components as $cix => $component) {
         if (empty($component)) {
             continue;
         }
         /* deselect unvalid type components */
         if (!in_array($component->objName, $cType)) {
             continue;
         }
         unset($compStart, $compEnd);
         /* select start from dtstart or due if dtstart is missing */
         $prop = $component->getProperty('dtstart', FALSE, TRUE);
         if (empty($prop) && $component->objName == 'vtodo' && FALSE === ($prop = $component->getProperty('due', FALSE, TRUE))) {
             continue;
         }
         if (empty($prop)) {
             continue;
         }
         /* get UID */
         $compUID = $component->getProperty('UID');
         if ($compUIDcmp != $compUID) {
             $compUIDcmp = $compUID;
             $exdatelist = $recurridList = array();
         }
         $recurrid = FALSE;
         // file_put_contents( '/opt/work/iCal/iCalcreator/iCalcreator-2.20.x/log/log.txt', "#$cix".PHP_EOL.var_export( $component, TRUE ).PHP_EOL.PHP_EOL, FILE_APPEND ); // test ###
         $compStart = iCaldateTime::factory($prop['value'], $prop['params'], $prop['value']);
         $dtstartTz = $compStart->getTimezoneName();
         if (isset($prop['params']['VALUE']) && 'DATE' == $prop['params']['VALUE']) {
             $compStartHis = '';
         } else {
             $his = $compStart->getTime();
             $compStartHis = sprintf(iCalUtilityFunctions::$fmt['His'], (int) $his[0], (int) $his[1], (int) $his[2]);
         }
         /* get end date from dtend/due/duration properties */
         if (FALSE !== ($prop = $component->getProperty('dtend', FALSE, TRUE))) {
             $compEnd = iCaldateTime::factory($prop['value'], $prop['params'], $prop['value'], $dtstartTz);
             $compEnd->SCbools['dtendExist'] = TRUE;
         }
         if (empty($prop) && $component->objName == 'vtodo' && FALSE !== ($prop = $component->getProperty('due', FALSE, TRUE))) {
             $compEnd = iCaldateTime::factory($prop['value'], $prop['params'], $prop['value'], $dtstartTz);
             $compEnd->SCbools['dueExist'] = TRUE;
         }
         if (empty($prop) && FALSE !== ($prop = $component->getProperty('duration', FALSE, TRUE, TRUE))) {
             // in dtend (array) format
             $compEnd = iCaldateTime::factory($prop['value'], $prop['params'], $prop['value'], $dtstartTz);
             $compEnd->SCbools['durationExist'] = TRUE;
         }
         if (!empty($prop) && !isset($prop['value']['hour'])) {
             /* a DTEND without time part denotes an end of an event that actually ends the day before,
                for an all-day event DTSTART=20071201 DTEND=20071202, taking place 20071201!!! */
             $compEnd->SCbools['endAllDayEvent'] = TRUE;
             $compEnd->modify('-1 day');
             $compEnd->setTime(23, 59, 59);
         }
         unset($prop);
         if (empty($compEnd)) {
             $compDuration = FALSE;
             $compEnd = clone $compStart;
             $compEnd->setTime(23, 59, 59);
             //  23:59:59 the same day as start
         } else {
             if ($compEnd->format('Ymd') < $compStart->format('Ymd')) {
                 // MUST be after start date!!
                 $compEnd = clone $compStart;
                 $compEnd->setTime(23, 59, 59);
                 //  23:59:59 the same day as start or ???
             }
             $compDuration = $compStart->diff($compEnd);
             // DateInterval
         }
         /* check recurrence-id (note, a missing sequence is the same as sequence=0 so don't test for sequence), to alter when hit dtstart/recurlist */
         if (FALSE !== ($prop = $component->getProperty('recurrence-id', FALSE, TRUE))) {
             $recurrid = iCaldateTime::factory($prop['value'], $prop['params'], $prop['value'], $dtstartTz);
             $rangeSet = isset($prop['params']['RANGE']) && 'THISANDFUTURE' == $prop['params']['RANGE'] ? TRUE : FALSE;
             $recurridList[$recurrid->key] = array(clone $compStart, clone $compEnd, $compDuration, $rangeSet);
             // change recur this day to new YmdHis/duration/range
             // echo "adding comp no:$cix with date=".$compStart->format(iCalUtilityFunctions::$fmt['YmdHis2e'])." to recurridList id={$recurrid->key}, newDate={$compStart->key}<br>\n"; // test ###
             unset($prop);
             continue;
             // ignore any other props in the component
         }
         // end recurrence-id/sequence test
         // else echo "comp no:$cix with date=".$compStart->format().", NO recurrence-id<br>\n"; // test ###
         ksort($recurridList, SORT_STRING);
         // echo 'recurridList='.implode(', ', array_keys( $recurridList ))."<br>\n"; // test ###
         $fcnStart = clone $compStart;
         $fcnStart->setDate((int) $startY, (int) $startM, (int) $startD);
         $fcnStart->setTime(0, 0, 0);
         $fcnEnd = clone $compEnd;
         $fcnEnd->setDate((int) $endY, (int) $endM, (int) $endD);
         $fcnEnd->setTime(23, 59, 59);
         // echo 'compStart='.$compStart->format().', compEnd'.$compEnd->format(); if($compDuration)echo ', interval='.$compDuration->format( iCalUtilityFunctions::$fmt['durDHis'] ); echo "<br>\n"; $tcnt = 0;// test ###
         /* *************************************************************
            make a list of optional exclude dates for component occurence from exrule and exdate
            *********************************************************** */
         $workStart = clone $compStart;
         $workStart->sub($compDuration ? $compDuration : $intervalP1D);
         $workEnd = clone $fcnEnd;
         $workEnd->add($compDuration ? $compDuration : $intervalP1D);
         while (FALSE !== ($prop = $component->getProperty('EXRULE'))) {
             $exdatelist2 = array();
             if (isset($prop['UNTIL']['hour'])) {
                 // convert until date to dtstart timezone
                 $until = iCaldateTime::factory($prop['UNTIL'], array('TZID' => 'UTC'), null, $dtstartTz);
                 $until = $until->format();
                 iCalUtilityFunctions::_strDate2arr($until);
                 $prop['UNTIL'] = $until;
             }
             iCalUtilityFunctions::_recur2date($exdatelist2, $prop, $compStart, $workStart, $workEnd);
             foreach ($exdatelist2 as $k => $v) {
                 $exdatelist[$k . $compStartHis] = $v;
             }
             // point out exact every excluded ocurrence (incl. opt. His)
             unset($until, $exdatelist2);
         }
         while (FALSE !== ($prop = $component->getProperty('EXDATE', FALSE, TRUE))) {
             // - start check exdate
             foreach ($prop['value'] as $exdate) {
                 $exdate = iCaldateTime::factory($exdate, $prop['params'], $exdate, $dtstartTz);
                 $exdatelist[$exdate->key] = TRUE;
             }
             // end - foreach( $exdate as $exdate )
         }
         // end - check exdate
         unset($prop, $exdate);
         // echo 'exdatelist='  .implode(', ', array_keys( $exdatelist ))  ."<br>\n"; // test ###
         /* *************************************************************
            select only components within.. .
            *********************************************************** */
         $xRecurrence = 1;
         if (!$any && iCalUtilityFunctions::_inScope($compStart, $fcnStart, $compStart, $fcnEnd, $compStart->dateFormat) || $any && iCalUtilityFunctions::_inScope($fcnEnd, $compStart, $fcnStart, $compEnd, $compStart->dateFormat)) {
             /* add the selected component (WITHIN valid dates) to output array */
             if ($flat) {
                 // any=true/false, ignores split
                 if (!$recurrid) {
                     $result[$compUID] = $component->copy();
                 }
                 // copy original to output (but not anyone with recurrence-id)
             } elseif ($split) {
                 // split the original component
                 // echo 'split org.:'.$compStart->format().' < '.$fcnStart->format( 'Ymd His e' )."<br>\n"; // test ###
                 if ($compStart->format(iCalUtilityFunctions::$fmt['YmdHis2']) < $fcnStart->format(iCalUtilityFunctions::$fmt['YmdHis2'])) {
                     $rstart = clone $fcnStart;
                 } else {
                     $rstart = clone $compStart;
                 }
                 if ($compEnd->format(iCalUtilityFunctions::$fmt['YmdHis2']) > $fcnEnd->format(iCalUtilityFunctions::$fmt['YmdHis2'])) {
                     $rend = clone $fcnEnd;
                 } else {
                     $rend = clone $compEnd;
                 }
                 // echo "going to test comp no:$cix, rstart=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )." (key={$rstart->key}), end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###
                 if (!isset($exdatelist[$rstart->key])) {
                     // not excluded in exrule/exdate
                     if (isset($recurridList[$rstart->key])) {
                         // change start day to new YmdHis/duration
                         $k = $rstart->key;
                         // echo "recurridList HIT, key={$k}, recur Date=".$recurridList[$k][0]->key."<br>\n"; // test ###
                         $rstart = clone $recurridList[$k][0];
                         $startHis = $rstart->getTime();
                         $rend = clone $rstart;
                         if (FALSE !== $recurridList[$k][2]) {
                             $rend->add($recurridList[$k][2]);
                         } elseif (FALSE !== $compDuration) {
                             $rend->add($compDuration);
                         }
                         $endHis = $rend->getTime();
                         unset($recurridList[$k]);
                     } else {
                         $startHis = $compStart->getTime();
                         $endHis = $compEnd->getTime();
                     }
                     // echo "_____testing comp no:$cix, rstart=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )." (key={$rstart->key}), end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###
                     $cnt = 0;
                     // exclude any recurrence START date, found in exdatelist or recurridList but accept the reccurence-id comp itself
                     $occurenceDays = 1 + (int) $rstart->diff($rend)->format('%a');
                     // count the days (incl start day)
                     while ($rstart->format(iCalUtilityFunctions::$fmt['Ymd2']) <= $rend->format(iCalUtilityFunctions::$fmt['Ymd2'])) {
                         $cnt += 1;
                         if (1 < $occurenceDays) {
                             $component->setProperty('X-OCCURENCE', sprintf(iCalUtilityFunctions::$fmt['dayOfDays'], $cnt, $occurenceDays));
                         }
                         if (1 < $cnt) {
                             $rstart->setTime(0, 0, 0);
                         } else {
                             $rstart->setTime($startHis[0], $startHis[1], $startHis[2]);
                             $exdatelist[$rstart->key] = $compDuration;
                             // make sure to exclude start day from the recurrence pattern
                         }
                         $component->setProperty('X-CURRENT-DTSTART', $rstart->format($compStart->dateFormat));
                         if (FALSE !== $compDuration) {
                             $propName = isset($compEnd->SCbools['dueExist']) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
                             if ($cnt < $occurenceDays) {
                                 $rstart->setTime(23, 59, 59);
                             } else {
                                 $rstart->setTime($endHis[0], $endHis[1], $endHis[2]);
                             }
                             $component->setProperty($propName, $rstart->format($compEnd->dateFormat));
                         }
                         $result[(int) $rstart->format('Y')][(int) $rstart->format('m')][(int) $rstart->format('d')][$compUID] = $component->copy();
                         // copy to output
                         $rstart->add($intervalP1D);
                     }
                     // end while(( $rstart->format( 'Ymd' ) < $rend->format( 'Ymd' ))
                     unset($cnt, $occurenceDays);
                 }
                 // end if( ! isset( $exdatelist[$rstart->key] ))
                 // else echo "skip no:$cix with date=".$compStart->format()."<br>\n"; // test ###
                 unset($rstart, $rend);
             } else {
                 // !$flat && !$split, i.e. no flat array and DTSTART within period
                 $tstart = isset($recurridList[$compStart->key]) ? clone $recurridList[$k][0] : clone $compStart;
                 // echo "going to test comp no:$cix with checkDate={$compStart->key} with recurridList=".implode(',',array_keys($recurridList)); // test ###
                 if (!$any || !isset($exdatelist[$tstart->key])) {
                     // exclude any recurrence date, found in exdatelist
                     // echo " and copied to output<br>\n"; // test ###
                     $result[(int) $tstart->format('Y')][(int) $tstart->format('m')][(int) $tstart->format('d')][$compUID] = $component->copy();
                     // copy to output
                 }
                 unset($tstart);
             }
         }
         // end (dt)start within the period OR occurs within the period
         /* *************************************************************
            if 'any' components, check components with reccurrence rules, removing all excluding dates
            *********************************************************** */
         if (TRUE === $any) {
             $recurlist = array();
             /* make a list of optional repeating dates for component occurence, rrule, rdate */
             while (FALSE !== ($prop = $component->getProperty('RRULE'))) {
                 // get all rrule dates (multiple values allowed)
                 $recurlist2 = array();
                 if (isset($prop['UNTIL']['hour'])) {
                     // convert $rrule['UNTIL'] to the same timezone as DTSTART !!
                     $until = iCaldateTime::factory($prop['UNTIL'], array('TZID' => 'UTC'), null, $dtstartTz);
                     $until = $until->format();
                     iCalUtilityFunctions::_strDate2arr($until);
                     $prop['UNTIL'] = $until;
                 }
                 iCalUtilityFunctions::_recur2date($recurlist2, $prop, $compStart, $workStart, $workEnd);
                 foreach ($recurlist2 as $recurkey => $recurvalue) {
                     // recurkey=Ymd
                     $recurkey .= $compStartHis;
                     // add opt His
                     if (!isset($exdatelist[$recurkey])) {
                         $recurlist[$recurkey] = $compDuration;
                     }
                     // DateInterval or FALSE
                 }
                 unset($prop, $until, $recurlist2);
             }
             $workStart = clone $fcnStart;
             $workStart->sub($compDuration ? $compDuration : $intervalP1D);
             $format = $compStart->dateFormat;
             while (FALSE !== ($prop = $component->getProperty('RDATE', FALSE, TRUE))) {
                 $rdateFmt = isset($prop['params']['VALUE']) ? $prop['params']['VALUE'] : 'DATETIME';
                 $params = $prop['params'];
                 $prop = $prop['value'];
                 foreach ($prop as $theRdate) {
                     if ('PERIOD' == $rdateFmt) {
                         // all days within PERIOD
                         $rdate = iCaldateTime::factory($theRdate[0], $params, $theRdate[0], $dtstartTz);
                         if (!iCalUtilityFunctions::_inScope($rdate, $workStart, $rdate, $fcnEnd, $format) || isset($exdatelist[$rdate->key])) {
                             continue;
                         }
                         if (isset($theRdate[1]['year'])) {
                             // date-date period end
                             $recurlist[$rdate->key] = $rdate->diff(iCaldateTime::factory($theRdate[1], $params, $theRdate[1], $dtstartTz));
                         } else {
                             // period duration
                             $recurlist[$rdate->key] = new DateInterval(iCalUtilityFunctions::_duration2str($theRdate[1]));
                         }
                     } elseif ('DATE' == $rdateFmt) {
                         // single recurrence, date
                         $rdate = iCaldateTime::factory($theRdate, array_merge($params, array('TZID' => $dtstartTz)), null, $dtstartTz);
                         if (iCalUtilityFunctions::_inScope($rdate, $workStart, $rdate, $fcnEnd, $format) && !isset($exdatelist[$rdate->key])) {
                             $recurlist[$rdate->key . $compStartHis] = $compDuration;
                         }
                         // set start date for recurrence + DateInterval/FALSE (+opt His)
                     } else {
                         // start DATETIME
                         $rdate = iCaldateTime::factory($theRdate, $params, $theRdate, $dtstartTz);
                         if (iCalUtilityFunctions::_inScope($rdate, $workStart, $rdate, $fcnEnd, $format) && !isset($exdatelist[$rdate->key])) {
                             $recurlist[$rdate->key] = $compDuration;
                         }
                         // set start datetime for recurrence DateInterval/FALSE
                     }
                     // end DATETIME
                 }
                 // end foreach( $prop as $theRdate )
             }
             // end while( FALSE !== ( $prop = $component->getProperty( 'rdate', FALSE, TRUE )))
             unset($prop, $workStart, $format, $theRdate, $rdate, $rend);
             foreach ($recurridList as $rKey => $rVal) {
                 // check for recurrence-id, i.e. alter recur Ymd[His] and duration
                 if (isset($recurlist[$rKey])) {
                     unset($recurlist[$rKey]);
                     $recurlist[$rVal[0]->key] = FALSE !== $rVal[2] ? $rVal[2] : $compDuration;
                     // echo "alter recurfrom {$rKey} to {$rVal[0]->key} ";if(FALSE!==$dur)echo " ({$dur->format( '%a days, %h-%i-%s' )})";echo "<br>\n"; // test ###
                 }
             }
             ksort($recurlist, SORT_STRING);
             // echo 'recurlist='   .implode(', ', array_keys( $recurlist ))   ."<br>\n"; // test ###
             // echo 'recurridList='   .implode(', ', array_keys( $recurridList ))   ."<br>\n"; // test ###
             /* *************************************************************
                output all remaining components in recurlist
                *********************************************************** */
             if (0 < count($recurlist)) {
                 $component2 = $component->copy();
                 $compUID = $component2->getProperty('UID');
                 $workStart = clone $fcnStart;
                 $workStart->sub($compDuration ? $compDuration : $intervalP1D);
                 $YmdOld = null;
                 foreach ($recurlist as $recurkey => $durvalue) {
                     if ($YmdOld == substr($recurkey, 0, 8)) {
                         // skip overlapping recur the same day, i.e. RDATE before RRULE
                         continue;
                     }
                     $YmdOld = substr($recurkey, 0, 8);
                     $rstart = clone $compStart;
                     $rstart->setDate((int) substr($recurkey, 0, 4), (int) substr($recurkey, 4, 2), (int) substr($recurkey, 6, 2));
                     $rstart->setTime((int) substr($recurkey, 8, 2), (int) substr($recurkey, 10, 2), (int) substr($recurkey, 12, 2));
                     // echo "recur start=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###;
                     /* add recurring components within valid dates to output array, only start date set */
                     if ($flat) {
                         if (!isset($result[$compUID])) {
                             // only one comp
                             $result[$compUID] = $component2->copy();
                         }
                         // copy to output
                     } elseif ($split) {
                         $rend = clone $rstart;
                         if (FALSE !== $durvalue) {
                             $rend->add($durvalue);
                         }
                         if ($rend->format(iCalUtilityFunctions::$fmt['Ymd2']) > $fcnEnd->format(iCalUtilityFunctions::$fmt['Ymd2'])) {
                             $rend = clone $fcnEnd;
                         }
                         // echo "recur 1={$recurkey}, start=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] ).", end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] );if($durvalue) echo ", duration=".$durvalue->format( iCalUtilityFunctions::$fmt['durDHis'] );echo "<br>\n"; // test ###
                         $xRecurrence += 1;
                         $cnt = 0;
                         $occurenceDays = 1 + (int) $rstart->diff($rend)->format('%a');
                         // count the days (incl start day)
                         while ($rstart->format(iCalUtilityFunctions::$fmt['Ymd2']) <= $rend->format(iCalUtilityFunctions::$fmt['Ymd2'])) {
                             // iterate.. .
                             $cnt += 1;
                             if ($rstart->format(iCalUtilityFunctions::$fmt['Ymd2']) < $fcnStart->format(iCalUtilityFunctions::$fmt['Ymd2'])) {
                                 // date before dtstart
                                 // echo "recur 3, start=".$rstart->format( 'Y-m-d H:i:s' )." &gt;= fcnStart=".$fcnStart->format( 'Y-m-d H:i:s' )."<br>\n"; // test ###
                                 $rstart->add($intervalP1D);
                                 $rstart->setTime(0, 0, 0);
                                 continue;
                             } elseif (2 == $cnt) {
                                 $rstart->setTime(0, 0, 0);
                             }
                             $component2->setProperty('X-RECURRENCE', $xRecurrence);
                             if (1 < $occurenceDays) {
                                 $component2->setProperty('X-OCCURENCE', sprintf(iCalUtilityFunctions::$fmt['dayOfDays'], $cnt, $occurenceDays));
                             } else {
                                 $component2->deleteProperty('X-OCCURENCE');
                             }
                             $component2->setProperty('X-CURRENT-DTSTART', $rstart->format($compStart->dateFormat));
                             $propName = isset($compEnd->SCbools['dueExist']) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
                             if (FALSE !== $durvalue) {
                                 if ($cnt < $occurenceDays) {
                                     $rstart->setTime(23, 59, 59);
                                 } else {
                                     $His = $rend->getTime();
                                     // set end time
                                     $rstart->setTime($His[0], $His[1], $His[2]);
                                 }
                                 $component2->setProperty($propName, $rstart->format($compEnd->dateFormat));
                                 // echo "checking date, (day {$cnt} of {$occurenceDays}), _end_=".$rstart->format( 'Y-m-d H:i:s e' )."<br>"; // test ###;
                             } else {
                                 $component2->deleteProperty($propName);
                             }
                             $result[(int) $rstart->format('Y')][(int) $rstart->format('m')][(int) $rstart->format('d')][$compUID] = $component2->copy();
                             // copy to output
                             $rstart->add($intervalP1D);
                         }
                         // end while( $rstart->format( 'Ymd' ) <= $rend->format( 'Ymd' ))
                         unset($rstart, $rend);
                     } elseif ($rstart->format(iCalUtilityFunctions::$fmt['Ymd2']) >= $fcnStart->format(iCalUtilityFunctions::$fmt['Ymd2'])) {
                         $xRecurrence += 1;
                         // date within period  //* flat=FALSE && split=FALSE => one comp every recur startdate *//
                         $component2->setProperty('X-RECURRENCE', $xRecurrence);
                         $component2->setProperty('X-CURRENT-DTSTART', $rstart->format($compStart->dateFormat));
                         $propName = isset($compEnd->SCbools['dueExist']) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
                         if (FALSE !== $durvalue) {
                             $rstart->add($durvalue);
                             $component2->setProperty($propName, $rstart->format($compEnd->dateFormat));
                         } else {
                             $component2->deleteProperty($propName);
                         }
                         $result[(int) $rstart->format('Y')][(int) $rstart->format('m')][(int) $rstart->format('d')][$compUID] = $component2->copy();
                         // copy to output
                     }
                     // end elseif( $rstart >= $fcnStart )
                     unset($rstart);
                 }
                 // end foreach( $recurlist as $recurkey => $durvalue )
                 unset($component2, $xRecurrence, $compUID, $workStart, $rstart);
             }
             // end if( 0 < count( $recurlist ))
         }
         // end if( TRUE === $any )
         unset($component);
     }
     // end foreach ( $this->components as $cix => $component )
     unset($recurrid, $recurridList, $fcnStart, $fcnEnd, $compStart, $compEnd, $exdatelist, $recurlist);
     // clean up
     if (0 >= count($result)) {
         return FALSE;
     } elseif (!$flat) {
         foreach ($result as $y => $yeararr) {
             foreach ($yeararr as $m => $montharr) {
                 foreach ($montharr as $d => $dayarr) {
                     if (empty($result[$y][$m][$d])) {
                         unset($result[$y][$m][$d]);
                     } else {
                         $result[$y][$m][$d] = array_values($dayarr);
                         // skip tricky UID-index
                         if (1 < count($result[$y][$m][$d])) {
                             foreach ($result[$y][$m][$d] as &$c) {
                                 // sort
                                 iCalUtilityFunctions::_setSortArgs($c);
                             }
                             usort($result[$y][$m][$d], array('iCalUtilityFunctions', '_cmpfcn'));
                         }
                     }
                 }
                 // end foreach( $montharr as $d => $dayarr )
                 if (empty($result[$y][$m])) {
                     unset($result[$y][$m]);
                 } else {
                     ksort($result[$y][$m]);
                 }
             }
             // end foreach( $yeararr as $m => $montharr )
             if (empty($result[$y])) {
                 unset($result[$y]);
             } else {
                 ksort($result[$y]);
             }
         }
         // end foreach( $result as $y => $yeararr )
         if (empty($result)) {
             unset($result);
         } else {
             ksort($result);
         }
     }
     // end elseif( !$flat )
     if (0 >= count($result)) {
         return FALSE;
     }
     return $result;
 }