You are here

function node_recur_generate_dates_days in Node recur 7

Generate an array of recurring dates based on days

Parameters

$node: The node that's being recurred

$date: The initial starting date belonging to the node that will be recurring. Can be in string or numeric format.

$days: An array of days (monday, tuesday, etc)

$until: The date to recur until. Can be in string or numeric format.

$offset: The amount of days the $days should be offset by, ie if $days = 'monday', and offset = 2, $days becomes 'wednesday'. This is used to calculate end dates that are N days apart from the start dates.

Return value

An array of timestamps

1 call to node_recur_generate_dates_days()
node_recur_generate_dates_from_form in ./node_recur.module
Generate dates from a form state

File

./node_recur.module, line 393

Code

function node_recur_generate_dates_days($node, $date, $days, $until, $offset = NULL) {
  $dates = array();

  // Convert date and until date to timestamp, if needed
  $date = is_string($date) ? strtotime($date) : $date;
  $until = is_string($until) ? strtotime($until) : $until;

  // Determine the hour of the date
  $hour = date('G', $date);

  // Move the date back based on the offset
  if ($offset) {
    $date = $date - $offset * 86400;
  }

  // Make sure we have valid timestamps
  if (!is_numeric($date) || !is_numeric($until)) {
    return FALSE;
  }

  // Make sure the until is ahead of the date
  if ($date >= $until) {
    return FALSE;
  }

  // Track the current date
  $current = $date;

  // Determine which day to start with which would be the closest
  // "next" day, ie, depending on the initial date, next friday
  // may be sooner than next monday.
  $first_day = NULL;
  foreach ($days as $day) {

    // Determine how many days until the next "day"
    $z = date('z', strtotime("next {$day}", $current));
    if (!$first_day || $z < $first_day) {
      $first_day = $z;
    }
  }

  // Iterate and generate dates until we reach the end
  while (TRUE) {
    foreach ($days as $day) {

      // Determine how many days until the next "day"
      $next_day = date('z', strtotime("next {$day}", $current));
      $days_apart = $next_day - date('z', $current);

      // If days apart is negative, we've jumped to a new year
      if ($days_apart < 0) {

        // Use 366 instead of 365 because the first day is 1, not 0
        $days_apart += 366;
      }

      // Apply the day differential
      $current += $days_apart * 86400;

      // Make sure the hours match, to avoid DST issue
      $current_hour = date('G', $current);
      if ($current_hour != $hour) {

        // Adjust to match
        $current += ($hour - $current_hour) * 3600;
      }

      // See if this date puts us past the limit
      if ($current > $until) {
        break 2;
      }

      // Apply the offset, if one
      $date_to_use = $current;
      if ($offset) {
        $date_to_use = $current + $offset * 86400;
      }

      // Make sure date is in the future, if the settings dictate that
      if (!node_recur_allow_past_dates($node->type) && $date_to_use < REQUEST_TIME) {
        continue;
      }

      // See if we have to skip until we use the first day
      if ($first_day && $first_day != $next_day && $first_day > $next_day) {
        continue;
      }
      $first_day = NULL;
      $dates[] = $date_to_use;
    }
  }
  return $dates;
}