You are here

protected function DateRRuleCalc::get_absolute_bydays in Date 8

Get values for absolute BYDAYs.

For BYDAYs without parameters,like TU,TH (every Tues and Thur), we look for every one of those days during the frequency period. Iterate through periods of a WEEK, MONTH, or YEAR, checking for the days of the week that match our criteria for each week in the period, then jumping ahead to the next week, month, or year, an INTERVAL at a time.

1 call to DateRRuleCalc::get_absolute_bydays()
DateRRuleCalc::get_byday_results in date_repeat/lib/Drupal/date_repeat/DateRRuleCalc.php
Processing for BYDAY values.

File

date_repeat/lib/Drupal/date_repeat/DateRRuleCalc.php, line 502
Code to compute the dates that match an iCal RRULE.

Class

DateRRuleCalc

Namespace

Drupal\date_repeat

Code

protected function get_absolute_bydays($week_days) {
  $finished = FALSE;
  $this->current_day = clone $this->start_date;
  $format = $this->rrule['FREQ'] == 'YEARLY' ? 'Y' : 'n';
  $current_period = $this->current_day
    ->format($format);

  // Back up to the beginning of the week in case we are somewhere
  // in the middle of the possible week days, needed so we don't
  // prematurely jump to the next week. The add_dates() function
  // will keep dates outside the range from getting added.
  if ($this->current_day
    ->format('l') != $this->week_start_day) {
    date_modify($this->current_day, 'last ' . $this->week_start_day . $this->time_string);
  }
  while (!$finished) {
    $period_finished = FALSE;
    while (!$period_finished) {
      $moved = FALSE;
      foreach ($week_days as $delta => $day) {

        // Find the next occurence of each day in this week, only
        // add it if we are still in the current month or year. The
        // add_current_date() function is insufficient to test whether
        // to include this date if we are using a rule like 'every
        // other month', so we must explicitly test it here.
        // If we're already on the right day, don't jump or we
        // will prematurely move into the next week.
        if ($this->current_day
          ->format('l') != $day) {
          date_modify($this->current_day, '+1 ' . $day . $this->time_string);
          $moved = TRUE;
        }
        if ($this->rrule['FREQ'] == 'WEEKLY' || $this->current_day
          ->format($format) == $current_period) {
          $this
            ->add_current_day();
        }
      }
      $finished = $this
        ->is_finished();

      // Make sure we don't get stuck in endless loop if the current
      // day never got changed above.
      if (!$moved) {
        date_modify($this->current_day, '+1 day' . $this->time_string);
      }

      // If this is a WEEKLY frequency, stop after each week,
      // otherwise, stop when we've moved outside the current period.
      // Jump to the end of the week, then test the period.
      if ($finished || $this->rrule['FREQ'] == 'WEEKLY') {
        $period_finished = TRUE;
      }
      elseif ($this->rrule['FREQ'] != 'WEEKLY' && $this->current_day
        ->format($format) != $current_period) {
        $period_finished = TRUE;
      }
    }
    if ($finished) {
      continue;
    }

    // We'll be at the end of a week, month, or year when
    // we get to this point in the code.
    // Go back to the beginning of this period before we jump, to
    // ensure we jump to the first day of the next period.
    switch ($this->rrule['FREQ']) {
      case 'WEEKLY':
        date_modify($this->current_day, '+1 ' . $this->week_start_day . $this->time_string);
        date_modify($this->current_day, '-1 week' . $this->time_string);
        break;
      case 'MONTHLY':
        date_modify($this->current_day, '-' . ($this->current_day
          ->format('j') - 1) . ' days' . $this->time_string);
        date_modify($this->current_day, '-1 month' . $this->time_string);
        break;
      case 'YEARLY':
        date_modify($this->current_day, '-' . $this->current_day
          ->format('z') . ' days' . $this->time_string);
        date_modify($this->current_day, '-1 year' . $this->time_string);
        break;
    }

    // Jump ahead to the next period to be evaluated.
    $this->current_day
      ->add($this->jump);
    $current_period = $this->current_day
      ->format($format);
    $finished = $this
      ->is_finished();
  }
}