You are here

protected function DateRRuleCalc::get_bymonthday_results in Date 8

Processing for BYMONTHDAY values.

BYMONTHDAY will look for specific days of the month in one or more months. This process is only valid when frequency is monthly or yearly. BYMONTHDAY values will look like '11' (the 11th day) or '-1' (the last day) or '10,11,12' (the 10th, 11th, and 12th days).

1 call to DateRRuleCalc::get_bymonthday_results()
DateRRuleCalc::compute in date_repeat/lib/Drupal/date_repeat/DateRRuleCalc.php

File

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

Class

DateRRuleCalc

Namespace

Drupal\date_repeat

Code

protected function get_bymonthday_results() {
  $finished = FALSE;
  $time = $this->time_string;
  $this->current_day = clone $this->start_date;
  $month_days = array();

  // Deconstruct the day in case it has a negative modifier.
  foreach ($this->rrule['BYMONTHDAY'] as $day) {
    preg_match("@(-)?([0-9]{1,2})@", $day, $regs);
    if (!empty($regs[2])) {

      // Convert parameters into count, and direction.
      $month_days[$day] = array(
        'direction' => !empty($regs[1]) ? $regs[1] : '+',
        'count' => $regs[2],
      );
    }
  }
  while (!$finished) {
    $year_finished = FALSE;
    while (!$year_finished) {

      // Check each requested day in the month.
      foreach ($this->rrule['BYMONTHDAY'] as $monthday) {
        $day = $month_days[$monthday];
        if ($this
          ->set_month_day(NULL, $day['count'], $day['direction'])) {
          $this
            ->add_current_day();
        }
        if ($finished = $this
          ->is_finished()) {
          $year_finished = TRUE;
        }
      }
      switch ($this->rrule['FREQ']) {
        case 'MONTHLY':

          // If it's monthly, keep looping through months.
          if ($finished = $this
            ->is_finished()) {
            $year_finished = TRUE;
          }

          // Back up to first of month and jump.
          $this->current_day
            ->modify("first day of this month {$time}");
          $this->current_day
            ->add($this->jump);
          break;
        case 'YEARLY':

          // If it's yearly, break out of the loop at the
          // end of every year.
          if ($this->current_day
            ->format('n') == 12) {
            $year_finished = TRUE;
          }
          else {

            // Jump to first day of next month.
            $this->current_day
              ->modify("first day of next month {$time}");
          }
          break;
      }
    }
    if ($this->rrule['FREQ'] == 'YEARLY') {

      // Back up to first of year and jump to next year.
      $this->current_day
        ->modify("this year January 1");
      $this->current_day
        ->add($this->jump);
    }
    $finished = $this
      ->is_finished();
  }
}