ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
ilCalendarRecurrenceCalculator Class Reference

Calculates an ilDateList for a given calendar entry and recurrence rule. More...

+ Collaboration diagram for ilCalendarRecurrenceCalculator:

Public Member Functions

 __construct (ilDatePeriod $entry, ilCalendarRecurrenceCalculation $rec)
 @access public More...
 
 calculateDateListByMonth ($a_month, $a_year)
 calculate day list by month(s) uses a cache of calculated recurring events @access public More...
 
 calculateDateList (ilDateTime $a_start, ilDateTime $a_end, $a_limit=-1)
 calculate date list More...
 

Protected Member Functions

 adjustTimeZones (ilDateTime $a_start, ilDateTime $a_end)
 Adjust timezone. More...
 
 optimizeStartingTime ()
 optimize starting time More...
 
 incrementByFrequency ($start)
 increment starting time by frequency More...
 
 applyBYMONTHRules (ilDateList $list)
 Apply BYMONTH rules. More...
 
 applyBYWEEKNORules (ilDateList $list)
 Apply BYWEEKNO rules (1 to 53 and -1 to -53). More...
 
 applyBYYEARDAYRules (ilDateList $list)
 Apply BYYEARDAY rules. More...
 
 applyBYMONTHDAYRules (ilDateList $list)
 Apply BYMONTHDAY rules. More...
 
 applyBYDAYRules (ilDateList $list)
 Apply BYDAY rules. More...
 
 getYearWeekDays (ilDateTime $seed)
 get a list of year week days according to the BYMONTH rule More...
 
 getMonthWeekDays ($year, $month)
 get a list of month days More...
 
 getWeekWeekDays ($seed_info)
 get weedays of week More...
 
 applyBYSETPOSRules (ilDateList $list)
 Apply BYSETPOST rules. More...
 
 applyLimits (ilDateList $list)
 Apply limits (count or until) More...
 
 applyExclusionDates ()
 
 initDateList ()
 init date list More...
 
 createDate ($a_date, $a_format_type=IL_CAL_UNIX)
 create date More...
 
 validateRecurrence ()
 validate recurrence More...
 

Protected Attributes

 $timezone = null
 
 $log = null
 
 $limit_reached = false
 
 $valid_dates = null
 
 $period_start = null
 
 $period_end = null
 
 $start = null
 
 $event = null
 
 $recurrence = null
 
 $frequence_context = 0
 

Detailed Description

Calculates an ilDateList for a given calendar entry and recurrence rule.

Author
Stefan Meyer meyer.nosp@m.@lei.nosp@m.fos.c.nosp@m.om
Version
$Id$

@ilCtrl_Calls

Definition at line 41 of file class.ilCalendarRecurrenceCalculator.php.

Constructor & Destructor Documentation

◆ __construct()

ilCalendarRecurrenceCalculator::__construct ( ilDatePeriod  $entry,
ilCalendarRecurrenceCalculation  $rec 
)

@access public

Parameters
ilDatePeriodinterface ilDatePeriod

Definition at line 64 of file class.ilCalendarRecurrenceCalculator.php.

65 {
66 global $ilLog;
67
68 $this->log = $ilLog;
69 $this->event = $entry;
70 $this->recurrence = $rec;
71 }

References $ilLog.

Member Function Documentation

◆ adjustTimeZones()

ilCalendarRecurrenceCalculator::adjustTimeZones ( ilDateTime  $a_start,
ilDateTime  $a_end 
)
protected

Adjust timezone.

@access protected

Definition at line 199 of file class.ilCalendarRecurrenceCalculator.php.

200 {
201 $this->timezone = $this->event->isFullday() ? ilTimeZone::UTC : $this->recurrence->getTimeZone();
202 ilTimeZone::_setDefaultTimeZone($this->timezone);
203
204 $this->period_start = clone $a_start;
205 $this->period_end = clone $a_end;
206 $this->start = clone $this->event->getStart();
207
208 try
209 {
210 if($this->event->isFullday())
211 {
212 $this->period_start->switchTimeZone(ilTimeZone::UTC);
213 $this->period_end->switchTimeZone(ilTimeZone::UTC);
214 $this->start->switchTimeZone(ilTimeZone::UTC);
215 }
216 else
217 {
218 $this->period_start->switchTimeZone($this->recurrence->getTimeZone());
219 $this->period_end->switchTimeZone($this->recurrence->getTimeZone());
220 $this->start->switchTimeZone($this->recurrence->getTimeZone());
221 }
222 return true;
223 }
224 catch(ilDateTimeException $e)
225 {
226 $this->log->write(__METHOD__.': '.$e->getMessage());
227 return false;
228 }
229 }
Class for DateTime exceptions.
switchTimeZone($a_timezone_identifier='')
Switch timezone.
static _setDefaultTimeZone($a_tz)
set default timezone

References ilTimeZone\_setDefaultTimeZone(), ilDateTime\switchTimeZone(), and ilTimeZone\UTC.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYDAYRules()

ilCalendarRecurrenceCalculator::applyBYDAYRules ( ilDateList  $list)
protected

Apply BYDAY rules.

@access protected

Parameters
objectilDateList
Returns
object ilDateList

Definition at line 563 of file class.ilCalendarRecurrenceCalculator.php.

564 {
565 // return unmodified, if no byday rules are available
566 if(!$this->recurrence->getBYDAYList())
567 {
568 return $list;
569 }
570
571 $days_list = $this->initDateList();
572
573 // generate a list of e.g all Sundays for the given year
574 // or e.g a list of all week days in a give month (FREQ = MONTHLY,WEEKLY or DAILY)
575 foreach($list->get() as $seed)
576 {
577 $seed_info = $seed->get(IL_CAL_FKT_GETDATE);
578
579 // TODO: maybe not correct in dst cases
580 $date_info = $seed->get(IL_CAL_FKT_GETDATE);
581 $date_info['mday'] = 1;
582 $date_info['mon'] = 1;
583 $start = $this->createDate($date_info,IL_CAL_FKT_GETDATE);
584
585 switch($this->frequence_context)
586 {
588 $day_sequence = $this->getYearWeekDays($seed);
589 break;
590
592 $day_sequence = $this->getMonthWeekDays($seed_info['year'],$seed_info['mon']);
593 break;
594
596 // TODO or RFC bug: FREQ>WEEKLY;BYMONTH=1;BYDAY=FR returns FR 1.2.2008
597 // Ical says: apply BYMONTH rules and after that apply byday rules on that date list.
598 $day_sequence = $this->getWeekWeekDays($seed_info);
599 break;
600
602 $day_sequence[strtoupper(substr($seed->get(IL_CAL_FKT_DATE,'D'),0,2))] = array($seed_info['yday']);
603 break;
604
605 }
606 foreach($this->recurrence->getBYDAYList() as $byday)
607 {
608 $year_day = array();
609 $day = strtoupper(substr($byday,-2));
610 $num_by_day = (int) $byday;
611
612 if($num_by_day)
613 {
614 if($num_by_day > 0)
615 {
616 if(isset($day_sequence[$day][$num_by_day - 1]))
617 {
618 $year_day = array($day_sequence[$day][$num_by_day - 1]);
619 }
620 }
621 else
622 {
623 if(isset($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]))
624 {
625 $year_day = array($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]);
626 }
627 }
628 }
629 else
630 {
631 if(isset($day_sequence[$day]))
632 {
633 $year_day = $day_sequence[$day];
634 }
635 }
636 foreach($year_day as $day)
637 {
638 switch($this->frequence_context)
639 {
644 $tmp_date = clone $start;
645 $tmp_date->increment(IL_CAL_DAY,$day);
646 $days_list->add($tmp_date);
647 break;
648 }
649
650 }
651 }
652 }
653 #echo $days_list;
654
655 return $days_list;
656 }
const IL_CAL_FKT_GETDATE
const IL_CAL_FKT_DATE
const IL_CAL_DAY
getMonthWeekDays($year, $month)
get a list of month days
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule

References $start, createDate(), ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), getMonthWeekDays(), getWeekWeekDays(), getYearWeekDays(), IL_CAL_DAY, IL_CAL_FKT_DATE, IL_CAL_FKT_GETDATE, and initDateList().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYMONTHDAYRules()

ilCalendarRecurrenceCalculator::applyBYMONTHDAYRules ( ilDateList  $list)
protected

Apply BYMONTHDAY rules.

@access protected

Definition at line 457 of file class.ilCalendarRecurrenceCalculator.php.

458 {
459 // return unmodified, if no byweekno rules are available
460 if(!$this->recurrence->getBYMONTHDAYList())
461 {
462 return $list;
463 }
464 $days_list = $this->initDateList();
465 foreach($list->get() as $seed)
466 {
468 $seed->get(IL_CAL_FKT_DATE,'Y',$this->timezone),
469 $seed->get(IL_CAL_FKT_DATE,'n',$this->timezone));
470 /*
471 $num_days = cal_days_in_month(CAL_GREGORIAN,
472 $seed->get(IL_CAL_FKT_DATE,'n',$this->timezone),
473 $seed->get(IL_CAL_FKT_DATE,'Y',$this->timezone));
474 */
475 #$this->log->write(__METHOD__.': Month '.$seed->get(IL_CAL_FKT_DATE,'M',$this->timezone).' has '.$num_days.' days.');
476
477 foreach($this->recurrence->getBYMONTHDAYList() as $bymonth_no)
478 {
479 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
480 if($this->frequence_context != ilCalendarRecurrence::FREQ_YEARLY)
481 {
482 if($day_no < 1 or $day_no > $num_days)
483 {
484 $this->log->write(__METHOD__.': Ignoring BYMONTHDAY rule: '.$day_no.' for month '.
485 $seed->get(IL_CAL_FKT_DATE,'M',$this->timezone));
486 continue;
487 }
488 }
489 $day_diff = $day_no - $seed->get(IL_CAL_FKT_DATE,'j',$this->timezone);
490 $new_day = $this->createDate($seed->get(IL_CAL_UNIX,'',$this->timezone));
491 $new_day->increment(ilDateTime::DAY,$day_diff);
492
493 switch($this->frequence_context)
494 {
496 // Check if day matches
497 #var_dump("<pre>",$seed->get(IL_CAL_FKT_DATE,'z',$this->timezone),$day_no,"</pre>");
498 if($seed->get(IL_CAL_FKT_DATE,'j',$this->timezone) == $day_no)
499 {
500 $days_list->add($new_day);
501 }
502 break;
503
505 // Check if week matches
506 if($seed->get(IL_CAL_FKT_DATE,'W',$this->timezone) == $new_day->get(IL_CAL_FKT_DATE,'W',$this->timezone))
507 {
508 $days_list->add($new_day);
509 }
510 break;
511
513 // seed and new day are in the same month.
514 $days_list->add($new_day);
515 break;
516
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);
521 $y = $seed->get(IL_CAL_FKT_DATE,'Y',$this->timezone);
522
523 // TODO: the chosen monthday has to added to all months
524 for($month = 1;$month <= 12;$month++)
525 {
526 #$num_days = cal_days_in_month(CAL_GREGORIAN,
527 # $month,
528 # $y);
530 $y,
531 $month);
532 $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
533 if($day_no < 1 or $day_no > $num_days)
534 {
535 $this->log->write(__METHOD__.': Ignoring BYMONTHDAY rule: '.$day_no.' for month '.$month);
536 }
537 else
538 {
539 $tz_obj = ilTimeZone::_getInstance($this->timezone);
540 $tz_obj->switchTZ();
541 $unix = mktime($h,$i,$s,$month,$day_no,$y);
542 $tz_obj->restoreTZ();
543 $new_day = $this->createDate($unix);
544 $days_list->add($new_day);
545 }
546 }
547 break;
548 }
549 }
550 }
551 $this->frequence_context = ilCalendarRecurrence::FREQ_DAILY;
552 return $days_list;
553 }
const IL_CAL_UNIX
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
static _getInstance($a_tz='')
get instance by timezone
$y
Definition: example_007.php:83
$h

References $h, $y, ilTimeZone\_getInstance(), ilCalendarUtil\_getMaxDayOfMonth(), createDate(), ilDateTime\DAY, ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, and initDateList().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYMONTHRules()

ilCalendarRecurrenceCalculator::applyBYMONTHRules ( ilDateList  $list)
protected

Apply BYMONTH rules.

@access protected

Returns
object ilDateList

Definition at line 297 of file class.ilCalendarRecurrenceCalculator.php.

298 {
299 // return unmodified, if no bymonth rules are available
300 if(!$this->recurrence->getBYMONTHList())
301 {
302 return $list;
303 }
304 $month_list = $this->initDateList();
305 foreach($list->get() as $date)
306 {
307 #echo "SEED: ".$seed;
308
309 foreach($this->recurrence->getBYMONTHList() as $month)
310 {
311 #echo "RULW_MONTH:".$month;
312
313 // YEARLY rules extend the seed to every month given in the BYMONTH rule
314 // Rules < YEARLY must match the month of the seed
315 if($this->recurrence->getFrequenceType() == ilCalendarRecurrence::FREQ_YEARLY)
316 {
317 $month_date = $this->createDate($date->get(IL_CAL_UNIX,'',$this->timezone));
318 $month_date->increment(ilDateTime::MONTH,-($date->get(IL_CAL_FKT_DATE,'n',$this->timezone) - $month));
319
320 #echo "BYMONTH: ".$month_date;
321 $month_list->add($month_date);
322 }
323 elseif($date->get(IL_CAL_FKT_DATE,'n',$this->timezone) == $month)
324 {
325 $month_list->add($date);
326 }
327 }
328 }
329 // decrease the frequence_context for YEARLY rules
330 if($this->recurrence->getFrequenceType() == ilCalendarRecurrence::FREQ_YEARLY)
331 {
332 $this->frequence_context = ilCalendarRecurrence::FREQ_MONTHLY;
333 }
334 return $month_list;
335 }

References createDate(), ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), and ilDateTime\MONTH.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYSETPOSRules()

ilCalendarRecurrenceCalculator::applyBYSETPOSRules ( ilDateList  $list)
protected

Apply BYSETPOST rules.

@access protected

Parameters
objectilDateList
Returns
object ilDateList

Definition at line 755 of file class.ilCalendarRecurrenceCalculator.php.

756 {
757 // return unmodified, if no bysetpos rules are available
758 if(!$this->recurrence->getBYSETPOSList())
759 {
760 return $list;
761 }
762 $pos_list = $this->initDateList();
763 $list->sort();
764 $candidates = $list->get();
765 $candidates_count = count($candidates);
766 foreach($this->recurrence->getBYSETPOSList() as $position)
767 {
768 if($position > 0 and $date = $list->getAtPosition($position))
769 {
770 $pos_list->add($date);
771 }
772 if($position < 0 and $date = $list->getAtPosition($candidates_count + $position + 1))
773 {
774 $pos_list->add($date);
775 }
776 }
777 return $pos_list;
778 }
getAtPosition($a_pos)
get item at specific position
sort()
Sort list.

References ilDateList\get(), ilDateList\getAtPosition(), initDateList(), and ilDateList\sort().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYWEEKNORules()

ilCalendarRecurrenceCalculator::applyBYWEEKNORules ( ilDateList  $list)
protected

Apply BYWEEKNO rules (1 to 53 and -1 to -53).

This rule can only be applied to YEARLY rules (RFC 2445 4.3.10)

@access protected

Definition at line 343 of file class.ilCalendarRecurrenceCalculator.php.

344 {
345 if($this->recurrence->getFrequenceType() != ilCalendarRecurrence::FREQ_YEARLY)
346 {
347 return $list;
348 }
349 // return unmodified, if no byweekno rules are available
350 if(!$this->recurrence->getBYWEEKNOList())
351 {
352 return $list;
353 }
354 $weeks_list = $this->initDateList();
355 foreach($list->get() as $seed)
356 {
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)
360 {
361 $week_no = $week_no < 0 ? ($weeks_in_year + $week_no + 1) : $week_no;
362
363 switch($this->frequence_context)
364 {
366 $this->log->write(__METHOD__.': Handling BYWEEKNO in MONTHLY context');
367 // Check if week matches
368 if($seed->get(IL_CAL_FKT_DATE,'W',$this->timezone) == $week_no)
369 {
370 $weeks_list->add($seed);
371 }
372 break;
373
375 $this->log->write(__METHOD__.': Handling BYWEEKNO in YEARLY context');
376 $week_diff = $week_no - $seed->get(IL_CAL_FKT_DATE,'W',$this->timezone);
377
378 // TODO: think about tz here
379 $new_week = $this->createDate($seed->get(IL_CAL_UNIX,'',$this->timezone));
380 $new_week->increment(ilDateTime::WEEK,$week_diff);
381 $weeks_list->add($new_week);
382 break;
383 }
384 }
385 }
386 $this->frequence_context = ilCalendarRecurrence::FREQ_WEEKLY;
387
388 return $weeks_list;
389 }

References createDate(), ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, initDateList(), and ilDateTime\WEEK.

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyBYYEARDAYRules()

ilCalendarRecurrenceCalculator::applyBYYEARDAYRules ( ilDateList  $list)
protected

Apply BYYEARDAY rules.

@access protected

Definition at line 396 of file class.ilCalendarRecurrenceCalculator.php.

397 {
398 // return unmodified, if no byweekno rules are available
399 if(!$this->recurrence->getBYYEARDAYList())
400 {
401 return $list;
402 }
403 $days_list = $this->initDateList();
404 foreach($list->get() as $seed)
405 {
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.');
408
409 foreach($this->recurrence->getBYYEARDAYList() as $day_no)
410 {
411 $day_no = $day_no < 0 ? ($num_days + $day_no + 1) : $day_no;
412
413 $day_diff = $day_no - $seed->get(IL_CAL_FKT_DATE,'z',$this->timezone);
414 $new_day = $this->createDate($seed->get(IL_CAL_UNIX,'',$this->timezone));
415 $new_day->increment(ilDateTime::DAY,$day_diff);
416
417 switch($this->frequence_context)
418 {
420 // Check if day matches
421 if($seed->get(IL_CAL_FKT_DATE,'z',$this->timezone) == $day_no)
422 {
423 $days_list->add($new_day);
424 }
425 break;
427 // Check if week matches
428 if($seed->get(IL_CAL_FKT_DATE,'W',$this->timezone) == $new_day->get(IL_CAL_FKT_DATE,'W',$this->timezone))
429 {
430 $days_list->add($new_day);
431 }
432 break;
434 // Check if month matches
435 if($seed->get(IL_CAL_FKT_DATE,'n',$this->timezone) == $new_day->get(IL_CAL_FKT_DATE,'n',$this->timezone))
436 {
437 $days_list->add($new_day);
438 }
439 break;
441 // Simply add
442 $day_list->add($new_day);
443 break;
444 }
445 }
446 }
447
448 $this->frequence_context = ilCalendarRecurrence::FREQ_DAILY;
449 return $days_list;
450 }

References createDate(), ilDateTime\DAY, ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateList\get(), IL_CAL_FKT_DATE, IL_CAL_UNIX, and initDateList().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ applyExclusionDates()

ilCalendarRecurrenceCalculator::applyExclusionDates ( )
protected
Parameters
ilDateList$list
Returns

Definition at line 852 of file class.ilCalendarRecurrenceCalculator.php.

853 {
854 if(!$this->recurrence->getExclusionDates())
855 {
856 return true;
857 }
858 foreach($this->recurrence->getExclusionDates() as $excl)
859 {
860 $this->valid_dates->removeByDAY($excl->getDate());
861 }
862 }

Referenced by calculateDateList().

+ Here is the caller graph for this function:

◆ applyLimits()

ilCalendarRecurrenceCalculator::applyLimits ( ilDateList  $list)
protected

Apply limits (count or until)

@access protected

Parameters
objectilDateList

Definition at line 787 of file class.ilCalendarRecurrenceCalculator.php.

788 {
789 $list->sort();
790
791 #echo "list: ";
792 #echo $list;
793 #echo '<br />';
794
795 // Check valid dates before starting time
796 foreach($list->get() as $check_date)
797 {
798 if(ilDateTime::_before($check_date,$this->event->getStart(),IL_CAL_DAY))
799 {
800 #echo 'Removed: '.$check_date.'<br/>';
801 $list->remove($check_date);
802 }
803 }
804
805 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate();
806
807 // Check count if given
808 if($this->recurrence->getFrequenceUntilCount())
809 {
810 foreach($list->get() as $res)
811 {
812 // check smaller than since the start time counts as one
813 if(count($this->valid_dates->get()) < $this->recurrence->getFrequenceUntilCount())
814 {
815 $this->valid_dates->add($res);
816 }
817 else
818 {
819 $this->limit_reached = true;
820 return false;
821 }
822 }
823 return true;
824 }
825 elseif($this->recurrence->getFrequenceUntilDate())
826 {
827 #echo 'Until date '.$this->recurrence->getFrequenceUntilDate();
828 $date = $this->recurrence->getFrequenceUntilDate();
829 foreach($list->get() as $res)
830 {
831 #echo 'Check date '.$res;
833 {
834 #echo 'Limit reached';
835 $this->limit_reached = true;
836 return false;
837 }
838 $this->valid_dates->add($res);
839 }
840 return true;
841 }
842
843 $this->valid_dates->merge($list);
844 return true;
845 }
remove(ilDateTime $remove)
remove from list
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 _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.

References $res, ilDateTime\_after(), ilDateTime\_before(), ilDateList\get(), IL_CAL_DAY, ilDateList\remove(), and ilDateList\sort().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calculateDateList()

ilCalendarRecurrenceCalculator::calculateDateList ( ilDateTime  $a_start,
ilDateTime  $a_end,
  $a_limit = -1 
)

calculate date list

@access public

Parameters
objectilDateTime start of period
objectilDateTime end of period
intlimit number of returned dates
Returns
ilDateList ilDateList

Definition at line 96 of file class.ilCalendarRecurrenceCalculator.php.

97 {
98# echo $a_start;
99# echo $a_end;
100# echo $this->event->getStart();
101# echo $this->event->getEnd();
102
103
104 $this->valid_dates = $this->initDateList();
105
106 // Check invalid settings: e.g no frequence given, invalid start/end dates ...
107 if(!$this->validateRecurrence())
108 {
109 $this->valid_dates->add($this->event->getStart());
110 return $this->valid_dates;
111 }
112
113 // Performance fix: Switching the timezone for many dates seems to be
114 // quite time consuming.
115 // Therfore we adjust the timezone of all input dates (start,end, event start)
116 // to the same tz (UTC for fullday events, Recurrence tz for all others).
117 $this->adjustTimeZones($a_start,$a_end);
118
119
120 // Add start of event if it is in the period
121 if((ilDateTime::_after($this->event->getStart(),$this->period_start,IL_CAL_DAY) and
122 ilDateTime::_before($this->event->getStart(),$this->period_end,IL_CAL_DAY)) or
123 ilDateTime::_equals($this->event->getStart(),$this->period_start,IL_CAL_DAY))
124 {
125 // begin-patch aptar
126 $this->valid_dates->add($this->event->getStart());
127 #$this->valid_dates->add($this->event->getStart());
128 // end patch aptar
129 }
130
131 // Calculate recurrences based on frequency (e.g. MONTHLY)
132 $time = microtime(true);
133
134 $start = $this->optimizeStartingTime();
135
136 #echo "ZEIT: ADJUST: ".(microtime(true) - $time).'<br>';
137 $counter = 0;
138 do
139 {
140 ++$counter;
141 // initialize context for applied rules
142 // E.g
143 // RRULE:FREQ=YEARLY;BYMONTH=1;BYWEEKNO=1,50 => context for BYWERKNO is monthly because it filters to the weeks in JAN
144 // RRULE:FREQ=YEARLY;BYWEEKNO=1,50 => context for BYWERKNO is yearly because it adds all weeks.
145 $this->frequence_context = $this->recurrence->getFrequenceType();
146
147 $freq_res = $this->initDateList();
148 $freq_res->add($start);
149
150 // Fixed sequence of applying rules (RFC 2445 4.3.10)
151 $freq_res = $this->applyBYMONTHRules($freq_res);
152 #echo "BYMONTH: ".$freq_res;
153
154 $freq_res = $this->applyBYWEEKNORules($freq_res);
155 #echo "BYWEEKNO: ".$freq_res;
156
157 $freq_res = $this->applyBYYEARDAYRules($freq_res);
158 #echo "BYYEARDAY: ".$freq_res;
159
160
161 $freq_res = $this->applyBYMONTHDAYRules($freq_res);
162 #echo "BYMONTHDAY: ".$freq_res;
163
164 #$time = microtime(true);
165 $freq_res = $this->applyBYDAYRules($freq_res);
166 #echo "ZEIT: ".(microtime(true) - $time);
167 #echo "BYDAY: ".$freq_res;
168
169
170 $freq_res = $this->applyBYSETPOSRules($freq_res);
171 #echo "BYSETPOS: ".$freq_res;
172
173 $freq_res = $this->applyLimits($freq_res);
174 #echo $freq_res;
175
177
178 if(ilDateTime::_after($start,$this->period_end) or $this->limit_reached)
179 {
180 break;
181 }
182 }
183 while(true);
184
185 $this->applyExclusionDates();
186
187 $this->valid_dates->sort();
188
189 // Restore default timezone
191 return $this->valid_dates;
192 }
applyBYMONTHDAYRules(ilDateList $list)
Apply BYMONTHDAY rules.
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
applyBYMONTHRules(ilDateList $list)
Apply BYMONTH rules.
applyBYYEARDAYRules(ilDateList $list)
Apply BYYEARDAY rules.
incrementByFrequency($start)
increment starting time by frequency
applyLimits(ilDateList $list)
Apply limits (count or until)
adjustTimeZones(ilDateTime $a_start, ilDateTime $a_end)
Adjust timezone.
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).
applyBYDAYRules(ilDateList $list)
Apply BYDAY rules.
static _equals(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check if two date are equal.
static _restoreDefaultTimeZone()
restore default timezone to server timezone

References $start, $valid_dates, ilDateTime\_after(), ilDateTime\_before(), ilDateTime\_equals(), ilTimeZone\_restoreDefaultTimeZone(), adjustTimeZones(), applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYSETPOSRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), applyExclusionDates(), applyLimits(), IL_CAL_DAY, incrementByFrequency(), initDateList(), optimizeStartingTime(), and validateRecurrence().

+ Here is the call graph for this function:

◆ calculateDateListByMonth()

ilCalendarRecurrenceCalculator::calculateDateListByMonth (   $a_month,
  $a_year 
)

calculate day list by month(s) uses a cache of calculated recurring events @access public

Parameters
intmonth
intyear
Returns
object ilDateList

Definition at line 81 of file class.ilCalendarRecurrenceCalculator.php.

82 {
83
84 }

◆ createDate()

ilCalendarRecurrenceCalculator::createDate (   $a_date,
  $a_format_type = IL_CAL_UNIX 
)
protected

create date

@access protected

Definition at line 879 of file class.ilCalendarRecurrenceCalculator.php.

880 {
881 if($this->event->isFullday())
882 {
883 return new ilDate($a_date,$a_format_type);
884 }
885 else
886 {
887 // TODO: the timezone for this recurrence must be stored in the db
888 return new ilDateTime($a_date,$a_format_type,$this->timezone);
889 }
890 }
@classDescription Date and time handling
Class for single dates.

Referenced by applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), and optimizeStartingTime().

+ Here is the caller graph for this function:

◆ getMonthWeekDays()

ilCalendarRecurrenceCalculator::getMonthWeekDays (   $year,
  $month 
)
protected

get a list of month days

@access protected

Parameters

return

Definition at line 698 of file class.ilCalendarRecurrenceCalculator.php.

699 {
700 static $month_days = array();
701
702 if(isset($month_days[$year][$month]))
703 {
704 return $month_days[$year][$month];
705 }
706
707 $month_str = $month < 10 ? ('0'.$month) : $month;
708 $begin_month = new ilDate($year.'-'.$month_str.'-01',IL_CAL_DATE);
709 $begin_month_info = $begin_month->get(IL_CAL_FKT_GETDATE);
710
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++)
713 {
714 next($days);
715 }
716 for($i = $begin_month_info['yday']; $i < $begin_month_info['yday'] + ilCalendarUtil::_getMaxDayOfMonth($year,$month) ; $i++)
717 {
718 if(($current_day = current($days)) == false)
719 {
720 $current_day = reset($days);
721 }
722 $month_days[$year][$month][$current_day][] = $i;
723 next($days);
724 }
725 return $month_days[$year][$month];
726 }
const IL_CAL_DATE

References ilCalendarUtil\_getMaxDayOfMonth(), IL_CAL_DATE, and IL_CAL_FKT_GETDATE.

Referenced by applyBYDAYRules().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getWeekWeekDays()

ilCalendarRecurrenceCalculator::getWeekWeekDays (   $seed_info)
protected

get weedays of week

@access protected

Parameters

return

Definition at line 735 of file class.ilCalendarRecurrenceCalculator.php.

736 {
737 $days = array(0 => 'SU',1 => 'MO',2 => 'TU',3 => 'WE',4 => 'TH',5 => 'FR',6 => 'SA');
738
739 $start_day = $seed_info['yday'] - $seed_info['wday'];
740 foreach($days as $num => $day)
741 {
742 $week_days[$day][] = $start_day++;
743 }
744 return $week_days;
745 }

Referenced by applyBYDAYRules().

+ Here is the caller graph for this function:

◆ getYearWeekDays()

ilCalendarRecurrenceCalculator::getYearWeekDays ( ilDateTime  $seed)
protected

get a list of year week days according to the BYMONTH rule

@access protected

Definition at line 663 of file class.ilCalendarRecurrenceCalculator.php.

664 {
665 $time = microtime(true);
666
667 $year_days = array();
668
669 $current_year = $seed->get(IL_CAL_FKT_DATE,'Y');
670 $start = new ilDate($current_year.'-01-01',IL_CAL_DATE);
671 $offset = $start->get(IL_CAL_FKT_DATE,'w');
672 $days = array(0 => 'SU',1 => 'MO',2 => 'TU',3 => 'WE',4 => 'TH',5 => 'FR',6 => 'SA');
673 for($i = 0;$i < $offset;$i++)
674 {
675 next($days);
676 }
677
678 $num_days = ilCalendarUtil::_isLeapYear($current_year) ? 366 : 365;
679 for($i = 0;$i < $num_days;$i++)
680 {
681 if(($current_day = current($days)) == false)
682 {
683 $current_day = reset($days);
684 }
685 $year_days[$current_day][] = $i;
686 next($days);
687 }
688 return $year_days;
689 }
static _isLeapYear($a_year)
check if a given year is a leap year
get($a_format, $a_format_str='', $a_tz='')
get formatted date

References $start, ilCalendarUtil\_isLeapYear(), ilDateTime\get(), IL_CAL_DATE, and IL_CAL_FKT_DATE.

Referenced by applyBYDAYRules().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ incrementByFrequency()

ilCalendarRecurrenceCalculator::incrementByFrequency (   $start)
protected

increment starting time by frequency

@access protected

Definition at line 262 of file class.ilCalendarRecurrenceCalculator.php.

263 {
264 global $ilLog;
265
266 switch($this->recurrence->getFrequenceType())
267 {
269 $start->increment(ilDateTime::YEAR,$this->recurrence->getInterval());
270 break;
271
273 $start->increment(ilDateTime::MONTH,$this->recurrence->getInterval());
274 break;
275
277 $start->increment(ilDateTime::WEEK,$this->recurrence->getInterval());
278 break;
279
281 $start->increment(ilDateTime::DAY,$this->recurrence->getInterval());
282 break;
283
284 default:
285 $ilLog->write(__METHOD__.'No frequence defined.');
286 break;
287 }
288 return $start;
289 }

References $ilLog, $start, ilDateTime\DAY, ilCalendarRecurrence\FREQ_DAILY, ilCalendarRecurrence\FREQ_MONTHLY, ilCalendarRecurrence\FREQ_WEEKLY, ilCalendarRecurrence\FREQ_YEARLY, ilDateTime\MONTH, ilDateTime\WEEK, and ilDateTime\YEAR.

Referenced by calculateDateList(), and optimizeStartingTime().

+ Here is the caller graph for this function:

◆ initDateList()

ilCalendarRecurrenceCalculator::initDateList ( )
protected

init date list

@access protected

Definition at line 869 of file class.ilCalendarRecurrenceCalculator.php.

870 {
871 return new ilDateList($this->event->isFullday() ? ilDateList::TYPE_DATE : ilDateList::TYPE_DATETIME);
872 }
List of dates.

References ilDateList\TYPE_DATE, and ilDateList\TYPE_DATETIME.

Referenced by applyBYDAYRules(), applyBYMONTHDAYRules(), applyBYMONTHRules(), applyBYSETPOSRules(), applyBYWEEKNORules(), applyBYYEARDAYRules(), and calculateDateList().

+ Here is the caller graph for this function:

◆ optimizeStartingTime()

ilCalendarRecurrenceCalculator::optimizeStartingTime ( )
protected

optimize starting time

@access protected

Definition at line 236 of file class.ilCalendarRecurrenceCalculator.php.

237 {
238 $time = microtime(true);
239
240 // starting time cannot be optimzed if RRULE UNTIL is given.
241 // In that case we have to calculate all dates until "UNTIL" is reached.
242 if($this->recurrence->getFrequenceUntilCount() > 0)
243 {
244 // Switch the date to the original defined timzone for this recurrence
245 return $this->createDate($this->start->get(IL_CAL_UNIX,$this->timezone));
246 }
247 $optimized = $start = $this->createDate($this->start->get(IL_CAL_UNIX,$this->timezone));
248 while(ilDateTime::_before($start,$this->period_start))
249 {
250 $optimized = clone $start;
251 $start = $this->incrementByFrequency($start);
252 }
253
254 return $optimized;
255 }

References $start, ilDateTime\_before(), createDate(), IL_CAL_UNIX, and incrementByFrequency().

Referenced by calculateDateList().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateRecurrence()

ilCalendarRecurrenceCalculator::validateRecurrence ( )
protected

validate recurrence

@access protected

Returns
bool

Definition at line 898 of file class.ilCalendarRecurrenceCalculator.php.

899 {
900 return $this->recurrence->validate();
901 }

Referenced by calculateDateList().

+ Here is the caller graph for this function:

Field Documentation

◆ $event

ilCalendarRecurrenceCalculator::$event = null
protected

Definition at line 52 of file class.ilCalendarRecurrenceCalculator.php.

◆ $frequence_context

ilCalendarRecurrenceCalculator::$frequence_context = 0
protected

Definition at line 55 of file class.ilCalendarRecurrenceCalculator.php.

◆ $limit_reached

ilCalendarRecurrenceCalculator::$limit_reached = false
protected

Definition at line 46 of file class.ilCalendarRecurrenceCalculator.php.

◆ $log

ilCalendarRecurrenceCalculator::$log = null
protected

Definition at line 44 of file class.ilCalendarRecurrenceCalculator.php.

◆ $period_end

ilCalendarRecurrenceCalculator::$period_end = null
protected

Definition at line 49 of file class.ilCalendarRecurrenceCalculator.php.

◆ $period_start

ilCalendarRecurrenceCalculator::$period_start = null
protected

Definition at line 48 of file class.ilCalendarRecurrenceCalculator.php.

◆ $recurrence

ilCalendarRecurrenceCalculator::$recurrence = null
protected

Definition at line 53 of file class.ilCalendarRecurrenceCalculator.php.

◆ $start

ilCalendarRecurrenceCalculator::$start = null
protected

◆ $timezone

ilCalendarRecurrenceCalculator::$timezone = null
protected

Definition at line 43 of file class.ilCalendarRecurrenceCalculator.php.

◆ $valid_dates

ilCalendarRecurrenceCalculator::$valid_dates = null
protected

Definition at line 47 of file class.ilCalendarRecurrenceCalculator.php.

Referenced by calculateDateList().


The documentation for this class was generated from the following file: