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';
67 $this->log =
$GLOBALS[
'DIC']->logger()->cal();
68 $this->
event = $entry;
69 $this->recurrence = $rec;
109 # echo $this->event->getStart(); 110 # echo $this->event->getEnd(); 117 $this->valid_dates->add($this->event->getStart());
134 $this->valid_dates->add($this->event->getStart());
135 #$this->valid_dates->add($this->event->getStart()); 140 $time = microtime(
true);
145 #echo "ZEIT: ADJUST: ".(microtime(true) - $time).'<br>'; 153 $this->frequence_context = $this->recurrence->getFrequenceType();
160 #echo "BYMONTH: ".$freq_res; 163 #echo "BYWEEKNO: ".$freq_res; 166 #echo "BYYEARDAY: ".$freq_res; 170 #echo "BYMONTHDAY: ".$freq_res; 172 #$time = microtime(true); 174 #echo "ZEIT: ".(microtime(true) - $time); 175 #echo "BYDAY: ".$freq_res; 179 #echo "BYSETPOS: ".$freq_res; 195 $this->valid_dates->sort();
208 $list_copy = clone $list;
209 foreach ($list_copy as $start_date) {
210 $end_date = clone $start_date;
221 $this->log->debug(
'Removed invalid date ' . (
string) $start_date .
' <-> ' . (
string) $end_date);
222 $list->
remove($start_date);
234 $this->timezone = $this->
event->isFullday() ?
ilTimeZone::UTC : $this->recurrence->getTimeZone();
237 $this->period_start = clone $a_start;
238 $this->period_end = clone $a_end;
239 $this->start = clone $this->
event->getStart();
242 if ($this->event->isFullday()) {
247 $this->period_start->switchTimeZone($this->recurrence->getTimeZone());
248 $this->period_end->switchTimeZone($this->recurrence->getTimeZone());
249 $this->start->switchTimeZone($this->recurrence->getTimeZone());
253 $this->log->write(__METHOD__ .
': ' . $e->getMessage());
265 $time = microtime(
true);
269 if ($this->recurrence->getFrequenceUntilCount() > 0) {
275 $optimized = clone
$start;
301 $logger = $DIC->logger()->cal();
303 switch ($this->recurrence->getFrequenceType()) {
321 $logger->warning(
'No frequence defined.');
336 if (!$this->recurrence->getBYMONTHList()) {
340 foreach ($list->
get() as $date) {
341 #echo "SEED: ".$seed; 343 foreach ($this->recurrence->getBYMONTHList() as $month) {
344 #echo "RULW_MONTH:".$month; 352 #echo "BYMONTH: ".$month_date; 353 $month_list->add($month_date);
354 } elseif ($date->get(
IL_CAL_FKT_DATE,
'n', $this->timezone) == $month) {
355 $month_list->add($date);
378 if (!$this->recurrence->getBYWEEKNOList()) {
382 foreach ($list->
get() as $seed) {
383 $weeks_in_year = date(
'W', mktime(0, 0, 0, 12, 28, $seed->get(
IL_CAL_FKT_DATE,
'Y', $this->timezone)));
384 $this->log->write(__METHOD__ .
': Year ' . $seed->get(
IL_CAL_FKT_DATE,
'Y', $this->timezone) .
' has ' . $weeks_in_year .
' weeks');
385 foreach ($this->recurrence->getBYWEEKNOList() as $week_no) {
386 $week_no = $week_no < 0 ? ($weeks_in_year + $week_no + 1) : $week_no;
388 switch ($this->frequence_context) {
390 $this->log->write(__METHOD__ .
': Handling BYWEEKNO in MONTHLY context');
393 $weeks_list->add($seed);
398 $this->log->write(__METHOD__ .
': Handling BYWEEKNO in YEARLY context');
399 $week_diff = $week_no - $seed->get(
IL_CAL_FKT_DATE,
'W', $this->timezone);
404 $weeks_list->add($new_week);
422 if (!$this->recurrence->getBYYEARDAYList()) {
426 foreach ($list->
get() as $seed) {
427 $num_days = date(
'z', mktime(0, 0, 0, 12, 31, $seed->get(
IL_CAL_FKT_DATE,
'Y', $this->timezone)));
428 $this->log->write(__METHOD__ .
': Year ' . $seed->get(
IL_CAL_FKT_DATE,
'Y', $this->timezone) .
' has ' . $num_days .
' days.');
430 foreach ($this->recurrence->getBYYEARDAYList() as $day_no) {
431 $day_no = $day_no < 0 ? ($num_days + $day_no + 1) : $day_no;
433 $day_diff = $day_no - $seed->get(
IL_CAL_FKT_DATE,
'z', $this->timezone);
437 switch ($this->frequence_context) {
441 $days_list->add($new_day);
447 $days_list->add($new_day);
453 $days_list->add($new_day);
458 $days_list->add($new_day);
476 if (!$this->recurrence->getBYMONTHDAYList()) {
480 foreach ($list->
get() as $seed) {
490 #$this->log->write(__METHOD__.': Month '.$seed->get(IL_CAL_FKT_DATE,'M',$this->timezone).' has '.$num_days.' days.'); 492 foreach ($this->recurrence->getBYMONTHDAYList() as $bymonth_no) {
493 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
495 if ($day_no < 1 or $day_no > $num_days) {
496 $this->log->write(__METHOD__ .
': Ignoring BYMONTHDAY rule: ' . $day_no .
' for month ' .
501 $day_diff = $day_no - $seed->get(
IL_CAL_FKT_DATE,
'j', $this->timezone);
505 switch ($this->frequence_context) {
508 #var_dump("<pre>",$seed->get(IL_CAL_FKT_DATE,'z',$this->timezone),$day_no,"</pre>"); 510 $days_list->add($new_day);
517 $days_list->add($new_day);
523 $days_list->add($new_day);
527 $h = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
'H', $this->timezone);
528 $i = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
'i', $this->timezone);
529 $s = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE,
's', $this->timezone);
533 for ($month = 1;$month <= 12;$month++) {
534 #$num_days = cal_days_in_month(CAL_GREGORIAN, 541 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
542 if ($day_no < 1 or $day_no > $num_days) {
543 $this->log->write(__METHOD__ .
': Ignoring BYMONTHDAY rule: ' . $day_no .
' for month ' . $month);
547 $unix = mktime($h,
$i, $s, $month, $day_no, $y);
548 $tz_obj->restoreTZ();
550 $days_list->add($new_day);
572 if (!$this->recurrence->getBYDAYList()) {
580 foreach ($list->
get() as $seed) {
585 $date_info[
'mday'] = 1;
586 $date_info[
'mon'] = 1;
589 switch ($this->frequence_context) {
595 $day_sequence = $this->
getMonthWeekDays($seed_info[
'year'], $seed_info[
'mon']);
605 $day_sequence[strtoupper(substr($seed->get(
IL_CAL_FKT_DATE,
'D'), 0, 2))] = array($seed_info[
'yday']);
609 foreach ($this->recurrence->getBYDAYList() as $byday) {
611 $day = strtoupper(substr($byday, -2));
612 $num_by_day = (int) $byday;
615 if ($num_by_day > 0) {
616 if (isset($day_sequence[$day][$num_by_day - 1])) {
617 $year_day = array($day_sequence[$day][$num_by_day - 1]);
620 if (isset($day_sequence[$day][count($day_sequence[$day]) + $num_by_day])) {
621 $year_day = array($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]);
625 if (isset($day_sequence[$day])) {
626 $year_day = $day_sequence[$day];
629 foreach ($year_day as $day) {
630 switch ($this->frequence_context) {
637 $days_list->add($tmp_date);
655 $time = microtime(
true);
657 $year_days = array();
662 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
663 for (
$i = 0;
$i < $offset;
$i++) {
668 for (
$i = 0;
$i < $num_days;
$i++) {
669 if (($current_day = current($days)) ==
false) {
670 $current_day = reset($days);
672 $year_days[$current_day][] =
$i;
687 static $month_days = array();
689 if (isset($month_days[$year][$month])) {
690 return $month_days[$year][$month];
693 $month_str = $month < 10 ? (
'0' . $month) : $month;
697 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
698 for (
$i = 0;
$i < $begin_month_info[
'wday'];
$i++) {
702 if (($current_day = current($days)) ==
false) {
703 $current_day = reset($days);
705 $month_days[$year][$month][$current_day][] =
$i;
708 return $month_days[$year][$month];
720 $days = array(0 =>
'SU',1 =>
'MO',2 =>
'TU',3 =>
'WE',4 =>
'TH',5 =>
'FR',6 =>
'SA');
722 $start_day = $seed_info[
'yday'] - $seed_info[
'wday'];
723 foreach ($days as $num => $day) {
724 $week_days[$day][] = $start_day++;
740 if (!$this->recurrence->getBYSETPOSList()) {
745 $candidates = $list->
get();
746 $candidates_count = count($candidates);
747 foreach ($this->recurrence->getBYSETPOSList() as $position) {
748 if ($position > 0 and $date = $list->
getAtPosition($position)) {
749 $pos_list->add($date);
751 if ($position < 0 and $date = $list->getAtPosition($candidates_count + $position + 1)) {
752 $pos_list->add($date);
774 foreach ($list->
get() as $check_date) {
776 $this->log->debug(
'Removed invalid date: ' . (
string) $check_date .
' before starting date: ' . (
string) $this->event->getStart());
777 $list->
remove($check_date);
781 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate(); 784 if ($this->recurrence->getFrequenceUntilCount()) {
785 foreach ($list->
get() as
$res) {
787 if (count($this->valid_dates->get()) < $this->recurrence->getFrequenceUntilCount()) {
788 $this->valid_dates->add(
$res);
790 $this->limit_reached =
true;
795 } elseif ($this->recurrence->getFrequenceUntilDate()) {
796 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate(); 797 $date = $this->recurrence->getFrequenceUntilDate();
798 foreach ($list->
get() as
$res) {
799 #echo 'Check date '.$res; 801 #echo 'Limit reached'; 802 $this->limit_reached =
true;
805 $this->valid_dates->add(
$res);
810 $this->valid_dates->merge($list);
821 if (!$this->recurrence->getExclusionDates()) {
824 foreach ($this->recurrence->getExclusionDates() as $excl) {
825 $this->valid_dates->removeByDAY($excl->getDate());
846 if ($this->event->isFullday()) {
847 return new ilDate($a_date, $a_format_type);
850 return new ilDateTime($a_date, $a_format_type, $this->timezone);
862 return $this->recurrence->validate();
applyBYMONTHDAYRules(ilDateList $list)
Apply BYMONTHDAY rules.
remove(ilDateTime $remove)
remove from list
applyDurationPeriod(ilDateList $list, ilDateTime $start, ilDateTime $end)
Apply duration period.
applyBYDAYRules(ilDateList $list)
Apply BYDAY rules.
applyBYMONTHRules(ilDateList $list)
Apply BYMONTH rules.
static _after(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
static _isLeapYear($a_year)
check if a given year is a leap year
static _before(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
switchTimeZone($a_timezone_identifier='')
Switch timezone.
optimizeStartingTime()
optimize starting time
getWeekWeekDays($seed_info)
get weedays of week
Class for DateTime exceptions.
static _setDefaultTimeZone($a_tz)
set default timezone
applyBYYEARDAYRules(ilDateList $list)
Apply BYYEARDAY rules.
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
static _restoreDefaultTimeZone()
restore default timezone to server timezone
__construct(ilDatePeriod $entry, ilCalendarRecurrenceCalculation $rec)
public
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule
calculateDateList(ilDateTime $a_start, ilDateTime $a_end, $a_limit=-1)
calculate date list
calculateDateListByMonth($a_month, $a_year)
calculate day list by month(s) uses a cache of calculated recurring events public ...
static _equals(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check if two date are equal.
adjustTimeZones(ilDateTime $a_start, ilDateTime $a_end)
Adjust timezone.
foreach($_POST as $key=> $value) $res
Calculates an ilDateList for a given calendar entry and recurrence rule.
getStart()
Interface method get start.
incrementByFrequency($start)
increment starting time by frequency
getDuration()
Get duration of event.
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
get($a_format, $a_format_str='', $a_tz='')
get formatted date
getAtPosition($a_pos)
get item at specific position
getEnd()
Interface method get end.
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
static _getInstance($a_tz='')
get instance by timezone
initDateList()
init date list
applyLimits(ilDateList $list)
Apply limits (count or until)
getMonthWeekDays($year, $month)
get a list of month days
validateRecurrence()
validate recurrence
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).