ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
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)
 public More...
 
 calculateDateListByMonth ($a_month, $a_year)
 calculate day list by month(s) uses a cache of calculated recurring events 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$

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

Constructor & Destructor Documentation

◆ __construct()

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

public

Parameters
ilDatePeriodinterface ilDatePeriod

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

References $ilLog.

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

Member Function Documentation

◆ adjustTimeZones()

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

Adjust timezone.

protected

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

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

Referenced by calculateDateList().

200  {
201  $this->timezone = $this->event->isFullday() ? ilTimeZone::UTC : $this->recurrence->getTimeZone();
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  }
Set timezone
switchTimeZone($a_timezone_identifier='')
Switch timezone.
Class for DateTime exceptions.
static _setDefaultTimeZone($a_tz)
set default timezone
+ 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.

protected

Parameters
objectilDateList
Returns
object ilDateList

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

References $start, array, 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().

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  }
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule
const IL_CAL_DAY
const IL_CAL_FKT_DATE
Create styles array
The data for the language used.
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
const IL_CAL_FKT_GETDATE
getMonthWeekDays($year, $month)
get a list of month days
+ 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.

protected

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

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, initDateList(), and timezone.

Referenced by calculateDateList().

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  }
Set timezone
$h
const IL_CAL_UNIX
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
$y
Definition: example_007.php:83
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
static _getInstance($a_tz='')
get instance by timezone
+ 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.

protected

Returns
object ilDateList

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

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

Referenced by calculateDateList().

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  }
const IL_CAL_UNIX
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
+ 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.

protected

Parameters
objectilDateList
Returns
object ilDateList

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

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

Referenced by calculateDateList().

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  }
sort()
Sort list.
getAtPosition($a_pos)
get item at specific position
+ 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)

protected

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

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

Referenced by calculateDateList().

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  }
Set timezone
const IL_CAL_UNIX
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
+ 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.

protected

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

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

Referenced by calculateDateList().

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  }
Set timezone
const IL_CAL_UNIX
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
const IL_CAL_FKT_DATE
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
+ 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.

Referenced by calculateDateList().

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  }
+ Here is the caller graph for this function:

◆ applyLimits()

ilCalendarRecurrenceCalculator::applyLimits ( ilDateList  $list)
protected

Apply limits (count or until)

protected

Parameters
objectilDateList

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

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

Referenced by calculateDateList().

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.
sort()
Sort list.
const IL_CAL_DAY
+ 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

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.

References $counter, $period_end, $period_start, $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().

Referenced by ilConsultationHoursGUI\createAppointments(), and ilObjSessionGUI\createRecurringSessions().

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.
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 _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.
applyBYYEARDAYRules(ilDateList $list)
Apply BYYEARDAY rules.
static _restoreDefaultTimeZone()
restore default timezone to server timezone
$counter
const IL_CAL_DAY
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.
incrementByFrequency($start)
increment starting time by frequency
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
applyLimits(ilDateList $list)
Apply limits (count or until)
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calculateDateListByMonth()

ilCalendarRecurrenceCalculator::calculateDateListByMonth (   $a_month,
  $a_year 
)

calculate day list by month(s) uses a cache of calculated recurring events 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

protected

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

References timezone.

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

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  }
Set timezone
Class for single dates.
Date and time handling
+ Here is the caller graph for this function:

◆ getMonthWeekDays()

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

get a list of month days

protected

Parameters

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

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

Referenced by applyBYDAYRules().

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  }
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
Class for single dates.
Create styles array
The data for the language used.
const IL_CAL_FKT_GETDATE
const IL_CAL_DATE
+ 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

protected

Parameters

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

References array.

Referenced by applyBYDAYRules().

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  }
Create styles array
The data for the language used.
+ 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

protected

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

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

Referenced by applyBYDAYRules().

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
Class for single dates.
const IL_CAL_FKT_DATE
get($a_format, $a_format_str='', $a_tz='')
get formatted date
Create styles array
The data for the language used.
const IL_CAL_DATE
+ 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

protected

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

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().

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  }
+ Here is the caller graph for this function:

◆ initDateList()

ilCalendarRecurrenceCalculator::initDateList ( )
protected

init date list

protected

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

References ilDateList\TYPE_DATE, and ilDateList\TYPE_DATETIME.

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

870  {
871  return new ilDateList($this->event->isFullday() ? ilDateList::TYPE_DATE : ilDateList::TYPE_DATETIME);
872  }
List of dates.
+ Here is the caller graph for this function:

◆ optimizeStartingTime()

ilCalendarRecurrenceCalculator::optimizeStartingTime ( )
protected

optimize starting time

protected

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

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

Referenced by calculateDateList().

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  }
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.
const IL_CAL_UNIX
incrementByFrequency($start)
increment starting time by frequency
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ validateRecurrence()

ilCalendarRecurrenceCalculator::validateRecurrence ( )
protected

validate recurrence

protected

Returns
bool

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

Referenced by calculateDateList().

899  {
900  return $this->recurrence->validate();
901  }
+ 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.

Referenced by calculateDateList().

◆ $period_start

ilCalendarRecurrenceCalculator::$period_start = null
protected

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

Referenced by calculateDateList().

◆ $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: