You are here

private static function SmartDateTrait::rangeDateReduce in Smart Date 3.1.x

Same name and namespace in other branches
  1. 8.2 src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()
  2. 3.x src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()
  3. 3.0.x src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()
  4. 3.2.x src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()
  5. 3.3.x src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()
  6. 3.4.x src/SmartDateTrait.php \Drupal\smart_date\SmartDateTrait::rangeDateReduce()

Reduce duplication in a provided date range.

Parameters

array $range: The date/time range to format.

array $settings: The date/time range to format.

object $start_ts: A timestamp.

object $end_ts: A timestamp.

string|null $timezone: Timezone.

Return value

string|array The range, with duplicate elements removed.

1 call to SmartDateTrait::rangeDateReduce()
SmartDateTrait::formatSmartDate in src/SmartDateTrait.php
Creates a formatted date value as a string.

File

src/SmartDateTrait.php, line 350

Class

SmartDateTrait
Provides friendly methods for smart date range.

Namespace

Drupal\smart_date

Code

private static function rangeDateReduce(array $range, array $settings, $start_ts, $end_ts, $timezone = NULL) {

  // First attempt has the following limitations, to reduce complexity:
  // * Day ranges only work either d or j, and no other day tokens.
  // * Not able to handle S token unless adjacent to day.
  // * Month, day ranges only work if year at start or end.
  $start = getdate($start_ts);
  $end = getdate($end_ts);

  // If the years are different, no deduplication necessary.
  if ($start['year'] != $end['year']) {
    return $range;
  }
  $valid_days = [];
  $invalid_days = [];

  // Check for workable day tokens.
  preg_match_all('/[dj]/', $settings['date_format'], $valid_days, PREG_OFFSET_CAPTURE);

  // Check for challenging day tokens.
  preg_match_all('/[DNlwz]/', $settings['date_format'], $invalid_days, PREG_OFFSET_CAPTURE);

  // If specific conditions are met format as a range within the month.
  if ($start['month'] == $end['month'] && count($valid_days[0]) == 1 && count($invalid_days[0]) == 0) {

    // Split the date string at the valid day token.
    $day_loc = $valid_days[0][0][1];

    // Don't remove the S token from the start if present.
    if ($s_loc = strpos($settings['date_format'], 'S', $day_loc)) {
      $offset = 1 + $s_loc - $day_loc;
    }
    elseif ($p_loc = strpos($settings['date_format'], '.', $day_loc)) {
      $offset = 1 + $p_loc - $day_loc;
    }
    else {
      $offset = 1;
    }
    $start_format = substr($settings['date_format'], 0, $day_loc + $offset);
    $end_format = substr($settings['date_format'], $day_loc);
    $range['start']['date'] = \Drupal::service('date.formatter')
      ->format($start_ts, '', $start_format, $timezone);
    $range['end']['date'] = \Drupal::service('date.formatter')
      ->format($end_ts, '', $end_format, $timezone);
  }
  else {

    // Only remaining possibility is to deduplicate the year.
    // NOTE: Our code only works with a 4 digit year format.
    if (strpos($settings['date_format'], 'Y') === 0) {
      $year_pos = 0;
    }
    elseif (strpos($settings['date_format'], 'Y') == strlen($settings['date_format']) - 1) {
      $year_pos = -1;
    }
    else {

      // Too complicated if year is in the middle.
      $year_pos = FALSE;
    }
    if ($year_pos !== FALSE) {
      $valid_tokens = [];

      // Check for workable day or month tokens.
      preg_match_all('/[djDNlwzSFmMn]/', $settings['date_format'], $valid_tokens, PREG_OFFSET_CAPTURE);
      if ($valid_tokens) {
        if ($year_pos == 0) {

          // Year is at the beginning, so change the end to start at the
          // first valid token after it.
          $first_token = $valid_tokens[0][0];
          $end_format = substr($settings['date_format'], $first_token[1]);
          $range['end']['date'] = \Drupal::service('date.formatter')
            ->format($end_ts, '', $end_format, $timezone);
        }
        else {
          $last_token = array_pop($valid_tokens[0]);
          $start_format = substr($settings['date_format'], 0, $last_token[1] + 1);
          $range['start']['date'] = \Drupal::service('date.formatter')
            ->format($start_ts, '', $start_format, $timezone);
        }
      }
    }
  }
  return $range;
}