24include_once 
'./Services/Calendar/classes/class.ilCalendarRecurrence.php';
 
   25include_once(
'./Services/Calendar/classes/class.ilDateList.php');
 
   26include_once(
'./Services/Calendar/classes/class.ilTimeZone.php');
 
   27include_once(
'./Services/Calendar/classes/class.ilCalendarUtil.php');
 
   28include_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);
 
  144        #echo "ZEIT: ADJUST: ".(microtime(true) - $time).'<br>';
 
  152            $this->frequence_context = $this->recurrence->getFrequenceType();
 
  159            #echo "BYMONTH: ".$freq_res;
 
  162            #echo "BYWEEKNO: ".$freq_res;
 
  165            #echo "BYYEARDAY: ".$freq_res;
 
  169            #echo "BYMONTHDAY: ".$freq_res;
 
  171            #$time = microtime(true); 
  173            #echo "ZEIT: ".(microtime(true) - $time);
 
  174            #echo "BYDAY: ".$freq_res;
 
  178            #echo "BYSETPOS: ".$freq_res;
 
  194        $this->valid_dates->sort();
 
  207        $list_copy = clone 
$list;
 
  208        foreach ($list_copy as $start_date) {
 
  209            $end_date = clone $start_date;
 
  220                $this->log->debug(
'Removed invalid date ' . (
string) $start_date . 
' <-> ' . (
string) $end_date);
 
  221                $list->remove($start_date);
 
  233        $this->timezone = $this->
event->isFullday() ? 
ilTimeZone::UTC : $this->recurrence->getTimeZone();
 
  236        $this->period_start = clone $a_start;
 
  237        $this->period_end = clone $a_end;
 
  238        $this->start = clone $this->
event->getStart();
 
  241            if ($this->event->isFullday()) {
 
  246                $this->period_start->switchTimeZone($this->recurrence->getTimeZone());
 
  247                $this->period_end->switchTimeZone($this->recurrence->getTimeZone());
 
  248                $this->start->switchTimeZone($this->recurrence->getTimeZone());
 
  252            $this->log->write(__METHOD__ . 
': ' . $e->getMessage());
 
  264        $time = microtime(
true);
 
  268        if ($this->recurrence->getFrequenceUntilCount() > 0) {
 
  274            $optimized = clone 
$start;
 
  290        $logger = 
$DIC->logger()->cal();
 
  292        switch ($this->recurrence->getFrequenceType()) {
 
  310                $logger->warning(
'No frequence defined.');
 
  325        if (!$this->recurrence->getBYMONTHList()) {
 
  329        foreach ($list->
get() as $date) {
 
  330            #echo "SEED: ".$seed;
 
  332            foreach ($this->recurrence->getBYMONTHList() as $month) {
 
  333                #echo "RULW_MONTH:".$month;
 
  341                    #echo "BYMONTH: ".$month_date;
 
  342                    $month_list->add($month_date);
 
  343                } elseif ($date->get(
IL_CAL_FKT_DATE, 
'n', $this->timezone) == $month) {
 
  344                    $month_list->add($date);
 
  367        if (!$this->recurrence->getBYWEEKNOList()) {
 
  371        foreach ($list->
get() as $seed) {
 
  372            $weeks_in_year = date(
'W', mktime(0, 0, 0, 12, 28, $seed->get(
IL_CAL_FKT_DATE, 
'Y', $this->timezone)));
 
  373            $this->log->write(__METHOD__ . 
': Year ' . $seed->get(
IL_CAL_FKT_DATE, 
'Y', $this->timezone) . 
' has ' . $weeks_in_year . 
' weeks');
 
  374            foreach ($this->recurrence->getBYWEEKNOList() as $week_no) {
 
  375                $week_no = $week_no < 0 ? ($weeks_in_year + $week_no + 1) : $week_no;
 
  377                switch ($this->frequence_context) {
 
  379                        $this->log->write(__METHOD__ . 
': Handling BYWEEKNO in MONTHLY context');
 
  382                            $weeks_list->add($seed);
 
  387                        $this->log->write(__METHOD__ . 
': Handling BYWEEKNO in YEARLY context');
 
  388                        $week_diff = $week_no - $seed->get(
IL_CAL_FKT_DATE, 
'W', $this->timezone);
 
  393                        $weeks_list->add($new_week);
 
  411        if (!$this->recurrence->getBYYEARDAYList()) {
 
  415        foreach ($list->
get() as $seed) {
 
  416            $num_days = date(
'z', mktime(0, 0, 0, 12, 31, $seed->get(
IL_CAL_FKT_DATE, 
'Y', $this->timezone)));
 
  417            $this->log->write(__METHOD__ . 
': Year ' . $seed->get(
IL_CAL_FKT_DATE, 
'Y', $this->timezone) . 
' has ' . $num_days . 
' days.');
 
  419            foreach ($this->recurrence->getBYYEARDAYList() as $day_no) {
 
  420                $day_no = $day_no < 0 ? ($num_days + $day_no + 1) : $day_no;
 
  422                $day_diff = $day_no - $seed->get(
IL_CAL_FKT_DATE, 
'z', $this->timezone);
 
  426                switch ($this->frequence_context) {
 
  430                            $days_list->add($new_day);
 
  436                            $days_list->add($new_day);
 
  442                            $days_list->add($new_day);
 
  447                        $days_list->add($new_day);
 
  465        if (!$this->recurrence->getBYMONTHDAYList()) {
 
  469        foreach ($list->
get() as $seed) {
 
  479            #$this->log->write(__METHOD__.': Month '.$seed->get(IL_CAL_FKT_DATE,'M',$this->timezone).' has '.$num_days.' days.'); 
  481            foreach ($this->recurrence->getBYMONTHDAYList() as $bymonth_no) {
 
  482                $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
 
  484                    if ($day_no < 1 or $day_no > $num_days) {
 
  485                        $this->log->write(__METHOD__ . 
': Ignoring BYMONTHDAY rule: ' . $day_no . 
' for month ' .
 
  490                $day_diff = $day_no - $seed->get(
IL_CAL_FKT_DATE, 
'j', $this->timezone);
 
  494                switch ($this->frequence_context) {
 
  497                        #var_dump("<pre>",$seed->get(IL_CAL_FKT_DATE,'z',$this->timezone),$day_no,"</pre>");
 
  499                            $days_list->add($new_day);
 
  506                            $days_list->add($new_day);
 
  512                        $days_list->add($new_day);
 
  516                        $h = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE, 
'H', $this->timezone);
 
  517                        $i = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE, 
'i', $this->timezone);
 
  518                        $s = $this->
event->isFullday() ? 0 : $seed->get(
IL_CAL_FKT_DATE, 
's', $this->timezone);
 
  522                        for ($month = 1;$month <= 12;$month++) {
 
  523                            #$num_days = cal_days_in_month(CAL_GREGORIAN, 
  530                            $day_no = $bymonth_no < 0 ? ($num_days + $bymonth_no + 1) : $bymonth_no;
 
  531                            if ($day_no < 1 or $day_no > $num_days) {
 
  532                                $this->log->write(__METHOD__ . 
': Ignoring BYMONTHDAY rule: ' . $day_no . 
' for month ' . $month);
 
  536                                $unix = mktime(
$h, 
$i, 
$s, $month, $day_no, 
$y);
 
  537                                $tz_obj->restoreTZ();
 
  539                                $days_list->add($new_day);
 
  561        if (!$this->recurrence->getBYDAYList()) {
 
  569        foreach ($list->
get() as $seed) {
 
  574            $date_info[
'mday'] = 1;
 
  575            $date_info[
'mon'] = 1;
 
  578            switch ($this->frequence_context) {
 
  584                    $day_sequence = $this->
getMonthWeekDays($seed_info[
'year'], $seed_info[
'mon']);
 
  594                    $day_sequence[strtoupper(substr($seed->get(
IL_CAL_FKT_DATE, 
'D'), 0, 2))] = array($seed_info[
'yday']);
 
  598            foreach ($this->recurrence->getBYDAYList() as $byday) {
 
  600                $day = strtoupper(substr($byday, -2));
 
  601                $num_by_day = (int) $byday;
 
  604                    if ($num_by_day > 0) {
 
  605                        if (isset($day_sequence[$day][$num_by_day - 1])) {
 
  606                            $year_day = array($day_sequence[$day][$num_by_day - 1]);
 
  609                        if (isset($day_sequence[$day][count($day_sequence[$day]) + $num_by_day])) {
 
  610                            $year_day = array($day_sequence[$day][count($day_sequence[$day]) + $num_by_day]);
 
  614                    if (isset($day_sequence[$day])) {
 
  615                        $year_day = $day_sequence[$day];
 
  618                foreach ($year_day as $day) {
 
  619                    switch ($this->frequence_context) {
 
  626                            $days_list->add($tmp_date);
 
  644        $time = microtime(
true);
 
  646        $year_days = array();
 
  651        $days = array(0 => 
'SU',1 => 
'MO',2 => 
'TU',3 => 
'WE',4 => 
'TH',5 => 
'FR',6 => 
'SA');
 
  652        for (
$i = 0;
$i < $offset;
$i++) {
 
  657        for (
$i = 0;
$i < $num_days;
$i++) {
 
  658            if (($current_day = current($days)) == 
false) {
 
  659                $current_day = reset($days);
 
  661            $year_days[$current_day][] = 
$i;
 
  676        static $month_days = array();
 
  678        if (isset($month_days[$year][$month])) {
 
  679            return $month_days[$year][$month];
 
  682        $month_str = $month < 10 ? (
'0' . $month) : $month;
 
  686        $days = array(0 => 
'SU',1 => 
'MO',2 => 
'TU',3 => 
'WE',4 => 
'TH',5 => 
'FR',6 => 
'SA');
 
  687        for (
$i = 0;
$i < $begin_month_info[
'wday'];
$i++) {
 
  691            if (($current_day = current($days)) == 
false) {
 
  692                $current_day = reset($days);
 
  694            $month_days[$year][$month][$current_day][] = 
$i;
 
  697        return $month_days[$year][$month];
 
  709        $days = array(0 => 
'SU',1 => 
'MO',2 => 
'TU',3 => 
'WE',4 => 
'TH',5 => 
'FR',6 => 
'SA');
 
  711        $start_day = $seed_info[
'yday'] - $seed_info[
'wday'];
 
  712        foreach ($days as $num => $day) {
 
  713            $week_days[$day][] = $start_day++;
 
  729        if (!$this->recurrence->getBYSETPOSList()) {
 
  734        $candidates = 
$list->get();
 
  735        $candidates_count = count($candidates);
 
  736        foreach ($this->recurrence->getBYSETPOSList() as $position) {
 
  737            if ($position > 0 and $date = 
$list->getAtPosition($position)) {
 
  738                $pos_list->add($date);
 
  740            if ($position < 0 and $date = $list->getAtPosition($candidates_count + $position + 1)) {
 
  741                $pos_list->add($date);
 
  763        foreach (
$list->get() as $check_date) {
 
  765                $this->log->debug(
'Removed invalid date: ' . (
string) $check_date . 
' before starting date:  ' . (
string) $this->event->getStart());
 
  766                $list->remove($check_date);
 
  770        #echo 'Until date '.$this->recurrence->getFrequenceUntilDate(); 
  773        if ($this->recurrence->getFrequenceUntilCount()) {
 
  776                if (count($this->valid_dates->get()) < $this->recurrence->getFrequenceUntilCount()) {
 
  777                    $this->valid_dates->add(
$res);
 
  779                    $this->limit_reached = 
true;
 
  784        } elseif ($this->recurrence->getFrequenceUntilDate()) {
 
  785            #echo 'Until date '.$this->recurrence->getFrequenceUntilDate(); 
  786            $date = $this->recurrence->getFrequenceUntilDate();
 
  788                #echo 'Check date '.$res; 
  790                    #echo 'Limit reached'; 
  791                    $this->limit_reached = 
true;
 
  794                $this->valid_dates->add(
$res);
 
  799        $this->valid_dates->merge(
$list);
 
  810        if (!$this->recurrence->getExclusionDates()) {
 
  813        foreach ($this->recurrence->getExclusionDates() as $excl) {
 
  814            $this->valid_dates->removeByDAY($excl->getDate());
 
  835        if ($this->event->isFullday()) {
 
  836            return new ilDate($a_date, $a_format_type);
 
  839            return new ilDateTime($a_date, $a_format_type, $this->timezone);
 
  851        return $this->recurrence->validate();
 
An exception for terminatinating execution or to throw for unit testing.
Calculates an ilDateList for a given calendar entry and recurrence rule.
getMonthWeekDays($year, $month)
get a list of month days
validateRecurrence()
validate recurrence
createDate($a_date, $a_format_type=IL_CAL_UNIX)
create date
applyBYMONTHDAYRules(ilDateList $list)
Apply BYMONTHDAY rules.
__construct(ilDatePeriod $entry, ilCalendarRecurrenceCalculation $rec)
@access public
applyBYSETPOSRules(ilDateList $list)
Apply BYSETPOST rules.
applyBYMONTHRules(ilDateList $list)
Apply BYMONTH rules.
applyBYYEARDAYRules(ilDateList $list)
Apply BYYEARDAY rules.
getYearWeekDays(ilDateTime $seed)
get a list of year week days according to the BYMONTH rule
incrementByFrequency($start)
increment starting time by frequency
calculateDateListByMonth($a_month, $a_year)
calculate day list by month(s) uses a cache of calculated recurring events @access public
calculateDateList(ilDateTime $a_start, ilDateTime $a_end, $a_limit=-1)
calculate date list
initDateList()
init date list
applyLimits(ilDateList $list)
Apply limits (count or until)
adjustTimeZones(ilDateTime $a_start, ilDateTime $a_end)
Adjust timezone.
getWeekWeekDays($seed_info)
get weedays of week
applyBYWEEKNORules(ilDateList $list)
Apply BYWEEKNO rules (1 to 53 and -1 to -53).
getDuration()
Get duration of event.
optimizeStartingTime()
optimize starting time
applyDurationPeriod(ilDateList $list, ilDateTime $start, ilDateTime $end)
Apply duration period.
applyBYDAYRules(ilDateList $list)
Apply BYDAY rules.
static _getMaxDayOfMonth($a_year, $a_month)
get max day of month 2008,2 => 29
static _isLeapYear($a_year)
check if a given year is a leap year
Class for DateTime exceptions.
@classDescription Date and time handling
static _equals(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
Check if two date are equal.
switchTimeZone($a_timezone_identifier='')
Switch timezone.
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.
get($a_format, $a_format_str='', $a_tz='')
get formatted date
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.
static _restoreDefaultTimeZone()
restore default timezone to server timezone
static _setDefaultTimeZone($a_tz)
set default timezone
static _getInstance($a_tz='')
get instance by timezone
getEnd()
Interface method get end.
getStart()
Interface method get start.
$GLOBALS['JPEG_Segment_Names']
Global Variable: XMP_tag_captions.
if(isset($_REQUEST['delete'])) $list
foreach($_POST as $key=> $value) $res