24 include_once
'./Services/Calendar/classes/class.ilCalendarRecurrence.php';
25 include_once(
'./Services/Calendar/classes/class.ilDateList.php');
26 include_once(
'./Services/Calendar/classes/class.ilTimeZone.php');
27 include_once(
'./Services/Calendar/classes/class.ilCalendarUtil.php');
28 include_once
'./Services/Calendar/interfaces/interface.ilCalendarRecurrenceCalculation.php';
69 $this->
event = $entry;
70 $this->recurrence = $rec;
100 # echo $this->event->getStart();
101 # echo $this->event->getEnd();
109 $this->valid_dates->add($this->event->getStart());
126 $this->valid_dates->add($this->event->getStart());
127 #$this->valid_dates->add($this->event->getStart());
132 $time = microtime(
true);
136 #echo "ZEIT: ADJUST: ".(microtime(true) - $time).'<br>';
145 $this->frequence_context = $this->recurrence->getFrequenceType();
152 #echo "BYMONTH: ".$freq_res;
155 #echo "BYWEEKNO: ".$freq_res;
158 #echo "BYYEARDAY: ".$freq_res;
162 #echo "BYMONTHDAY: ".$freq_res;
164 #$time = microtime(true);
166 #echo "ZEIT: ".(microtime(true) - $time);
167 #echo "BYDAY: ".$freq_res;
171 #echo "BYSETPOS: ".$freq_res;
187 $this->valid_dates->sort();
201 $this->timezone = $this->
event->isFullday() ?
ilTimeZone::UTC : $this->recurrence->getTimeZone();
204 $this->period_start = clone $a_start;
205 $this->period_end = clone $a_end;
206 $this->start = clone $this->
event->getStart();
210 if($this->event->isFullday())
218 $this->period_start->switchTimeZone($this->recurrence->getTimeZone());
219 $this->period_end->switchTimeZone($this->recurrence->getTimeZone());
220 $this->start->switchTimeZone($this->recurrence->getTimeZone());
226 $this->log->write(__METHOD__.
': '.$e->getMessage());
238 $time = microtime(
true);
242 if($this->recurrence->getFrequenceUntilCount() > 0)
250 $optimized = clone
$start;
266 switch($this->recurrence->getFrequenceType())
285 $ilLog->write(__METHOD__.
'No frequence defined.');
300 if(!$this->recurrence->getBYMONTHList())
305 foreach($list->
get() as $date)
307 #echo "SEED: ".$seed;
309 foreach($this->recurrence->getBYMONTHList() as $month)
311 #echo "RULW_MONTH:".$month;
320 #echo "BYMONTH: ".$month_date;
321 $month_list->add($month_date);
325 $month_list->add($date);
350 if(!$this->recurrence->getBYWEEKNOList())
355 foreach($list->
get() as $seed)
357 $weeks_in_year = date(
'W',mktime(0,0,0,12,28,$seed->get(
IL_CAL_FKT_DATE,
'Y',$this->timezone)));
358 $this->log->write(__METHOD__.
': Year '.$seed->get(
IL_CAL_FKT_DATE,
'Y',$this->timezone).
' has '.$weeks_in_year.
' weeks');
359 foreach($this->recurrence->getBYWEEKNOList() as $week_no)
361 $week_no = $week_no < 0 ? ($weeks_in_year + $week_no + 1) : $week_no;
363 switch($this->frequence_context)
366 $this->log->write(__METHOD__.
': Handling BYWEEKNO in MONTHLY context');
370 $weeks_list->add($seed);
375 $this->log->write(__METHOD__.
': Handling BYWEEKNO in YEARLY context');
376 $week_diff = $week_no - $seed->get(
IL_CAL_FKT_DATE,
'W',$this->timezone);
381 $weeks_list->add($new_week);
399 if(!$this->recurrence->getBYYEARDAYList())
404 foreach($list->
get() as $seed)
406 $num_days = date(
'z',mktime(0,0,0,12,31,$seed->get(
IL_CAL_FKT_DATE,
'Y',$this->timezone)));
407 $this->log->write(__METHOD__.
': Year '.$seed->get(
IL_CAL_FKT_DATE,
'Y',$this->timezone).
' has '.$num_days.
' days.');
409 foreach($this->recurrence->getBYYEARDAYList() as $day_no)
411 $day_no = $day_no < 0 ? ($num_days + $day_no + 1) : $day_no;
417 switch($this->frequence_context)
423 $days_list->add($new_day);
430 $days_list->add($new_day);
437 $days_list->add($new_day);
442 $day_list->add($new_day);
460 if(!$this->recurrence->getBYMONTHDAYList())
465 foreach($list->
get() as $seed)
475 #$this->log->write(__METHOD__.': Month '.$seed->get(IL_CAL_FKT_DATE,'M',$this->timezone).' has '.$num_days.' days.');
477 foreach($this->recurrence->getBYMONTHDAYList() as $bymonth_no)
479 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
482 if($day_no < 1 or $day_no > $num_days)
484 $this->log->write(__METHOD__.
': Ignoring BYMONTHDAY rule: '.$day_no.
' for month '.
493 switch($this->frequence_context)
497 #var_dump("<pre>",$seed->get(IL_CAL_FKT_DATE,'z',$this->timezone),$day_no,"</pre>");
500 $days_list->add($new_day);
508 $days_list->add($new_day);
514 $days_list->add($new_day);
518 $h = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
'H',$this->timezone);
519 $i = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
'i',$this->timezone);
520 $s = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
's',$this->timezone);
524 for($month = 1;$month <= 12;$month++)
526 #$num_days = cal_days_in_month(CAL_GREGORIAN,
532 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
533 if($day_no < 1 or $day_no > $num_days)
535 $this->log->write(__METHOD__.
': Ignoring BYMONTHDAY rule: '.$day_no.
' for month '.$month);
541 $unix = mktime($h,$i,$s,$month,$day_no,$y);
542 $tz_obj->restoreTZ();
544 $days_list->add($new_day);
566 if(!$this->recurrence->getBYDAYList())
575 foreach($list->
get() as $seed)
581 $date_info[
'mday'] = 1;
582 $date_info[
'mon'] = 1;
585 switch($this->frequence_context)
592 $day_sequence = $this->
getMonthWeekDays($seed_info[
'year'],$seed_info[
'mon']);
602 $day_sequence[strtoupper(substr($seed->get(
IL_CAL_FKT_DATE,
'D'),0,2))] = array($seed_info[
'yday']);
606 foreach($this->recurrence->getBYDAYList() as $byday)
609 $day = strtoupper(substr($byday,-2));
610 $num_by_day = (int) $byday;
616 if(isset($day_sequence[$day][$num_by_day - 1]))
618 $year_day = array($day_sequence[$day][$num_by_day - 1]);
623 if(isset($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]))
625 $year_day = array($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]);
631 if(isset($day_sequence[$day]))
633 $year_day = $day_sequence[$day];
636 foreach($year_day as $day)
638 switch($this->frequence_context)
646 $days_list->add($tmp_date);
665 $time = microtime(
true);
667 $year_days = array();
672 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
673 for($i = 0;$i < $offset;$i++)
679 for($i = 0;$i < $num_days;$i++)
681 if(($current_day = current($days)) ==
false)
683 $current_day = reset($days);
685 $year_days[$current_day][] = $i;
700 static $month_days = array();
702 if(isset($month_days[$year][$month]))
704 return $month_days[$year][$month];
707 $month_str = $month < 10 ? (
'0'.$month) : $month;
711 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
712 for($i = 0;$i < $begin_month_info[
'wday'];$i++)
718 if(($current_day = current($days)) ==
false)
720 $current_day = reset($days);
722 $month_days[$year][$month][$current_day][] = $i;
725 return $month_days[$year][$month];
737 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
739 $start_day = $seed_info[
'yday'] - $seed_info[
'wday'];
740 foreach($days as $num => $day)
742 $week_days[$day][] = $start_day++;
758 if(!$this->recurrence->getBYSETPOSList())
764 $candidates = $list->
get();
765 $candidates_count = count($candidates);
766 foreach($this->recurrence->getBYSETPOSList() as $position)
768 if($position > 0 and $date = $list->
getAtPosition($position))
770 $pos_list->add($date);
772 if($position < 0 and $date = $list->getAtPosition($candidates_count + $position + 1))
774 $pos_list->add($date);
796 foreach($list->
get() as $check_date)
800 #echo 'Removed: '.$check_date.'<br/>';
801 $list->
remove($check_date);
805 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate();
808 if($this->recurrence->getFrequenceUntilCount())
813 if(count($this->valid_dates->get()) < $this->recurrence->getFrequenceUntilCount())
815 $this->valid_dates->add(
$res);
819 $this->limit_reached =
true;
825 elseif($this->recurrence->getFrequenceUntilDate())
827 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate();
828 $date = $this->recurrence->getFrequenceUntilDate();
831 #echo 'Check date '.$res;
834 #echo 'Limit reached';
835 $this->limit_reached =
true;
838 $this->valid_dates->add(
$res);
843 $this->valid_dates->merge($list);
854 if(!$this->recurrence->getExclusionDates())
858 foreach($this->recurrence->getExclusionDates() as $excl)
860 $this->valid_dates->removeByDAY($excl->getDate());
881 if($this->event->isFullday())
883 return new ilDate($a_date,$a_format_type);
888 return new ilDateTime($a_date,$a_format_type,$this->timezone);
900 return $this->recurrence->validate();