You are here

protected function DateObject::parse in Date 7

Same name and namespace in other branches
  1. 7.3 date_api/date_api.module \DateObject::parse()
  2. 7.2 date_api/date_api.module \DateObject::parse()
1 call to DateObject::parse()
DateObject::__construct in date_api/date_api.module
Overridden constructor.

File

date_api/date_api.module, line 345
This module will make the date API available to other modules. Designed to provide a light but flexible assortment of functions and constants, with more functionality in additional files that are not loaded unless other modules specifically include them.

Class

DateObject
Extend PHP DateTime class with granularity handling, merge functionality and slightly more flexible initialization parameters.

Code

protected function parse($date, $tz, $format) {
  $array = date_format_patterns();
  foreach ($array as $key => $value) {
    $patterns[] = "`(^|[^\\\\\\\\])" . $key . "`";

    // the letter with no preceding '\'
    $repl1[] = '${1}(.)';

    // a single character
    $repl2[] = '${1}(' . $value . ')';

    // the
  }
  $patterns[] = "`\\\\\\\\([" . implode(array_keys($array)) . "])`";
  $repl1[] = '${1}';
  $repl2[] = '${1}';
  $format_regexp = preg_quote($format);

  // extract letters
  $regex1 = preg_replace($patterns, $repl1, $format_regexp, 1);
  $regex1 = str_replace('A', '(.)', $regex1);
  $regex1 = str_replace('a', '(.)', $regex1);
  preg_match('`^' . $regex1 . '$`', stripslashes($format), $letters);
  array_shift($letters);

  // extract values
  $regex2 = preg_replace($patterns, $repl2, $format_regexp, 1);
  $regex2 = str_replace('A', '(AM|PM)', $regex2);
  $regex2 = str_replace('a', '(am|pm)', $regex2);
  preg_match('`^' . $regex2 . '$`', $date, $values);
  array_shift($values);

  // if we did not find all the values for the patterns in the format, abort
  if (count($letters) != count($values)) {
    return FALSE;
  }
  $this->granularity = array();
  $final_date = array(
    'hour' => 0,
    'minute' => 0,
    'second' => 0,
    'month' => 1,
    'day' => 1,
    'year' => 0,
  );
  foreach ($letters as $i => $letter) {
    $value = $values[$i];
    switch ($letter) {
      case 'd':
      case 'j':
        $final_date['day'] = intval($value);
        $this
          ->addGranularity('day');
        break;
      case 'n':
      case 'm':
        $final_date['month'] = intval($value);
        $this
          ->addGranularity('month');
        break;
      case 'F':
        $array_month_long = array_flip(date_month_names());
        $final_date['month'] = $array_month_long[$value];
        $this
          ->addGranularity('month');
        break;
      case 'M':
        $array_month = array_flip(date_month_names_abbr());
        $final_date['month'] = $array_month[$value];
        $this
          ->addGranularity('month');
        break;
      case 'Y':
        $final_date['year'] = $value;
        $this
          ->addGranularity('year');
        break;
      case 'y':
        $year = $value;

        // if no century, we add the current one ("06" => "2006")
        $final_date['year'] = str_pad($year, 4, substr(date("Y"), 0, 2), STR_PAD_LEFT);
        $this
          ->addGranularity('year');
        break;
      case 'a':
      case 'A':
        $ampm = strtolower($value);
        break;
      case 'g':
      case 'h':
      case 'G':
      case 'H':
        $final_date['hour'] = intval($value);
        $this
          ->addGranularity('hour');
        break;
      case 'i':
        $final_date['minute'] = intval($value);
        $this
          ->addGranularity('minute');
        break;
      case 's':
        $final_date['second'] = intval($value);
        $this
          ->addGranularity('second');
        break;
      case 'U':
        parent::__construct($value, $tz ? $tz : new DateTimeZone("UTC"));
        $this
          ->addGranularity('year');
        $this
          ->addGranularity('month');
        $this
          ->addGranularity('day');
        $this
          ->addGranularity('hour');
        $this
          ->addGranularity('minute');
        $this
          ->addGranularity('second');
        return $this;
        break;
    }
  }
  if (isset($ampm) && $ampm == 'pm' && $final_date['hour'] < 12) {
    $final_date['hour'] += 12;
  }
  elseif (isset($ampm) && $ampm == 'am' && $final_date['hour'] == 12) {
    $final_date['hour'] -= 12;
  }

  // Blank becomes current time, given TZ.
  parent::__construct('', $tz ? $tz : new DateTimeZone("UTC"));
  if ($tz) {
    $this
      ->addGranularity('timezone');
  }

  // SetDate expects an integer value for the year, results can
  // be unexpected if we feed it something like '0100' or '0000';
  $final_date['year'] = intval($final_date['year']);
  $this->errors += $this
    ->arrayErrors($final_date);

  // If the input value is '0000-00-00', PHP's date class will later incorrectly convert
  // it to something like '-0001-11-30' if we do setDate() here. If we don't do
  // setDate() here, it will default to the current date and we will lose any way to
  // tell that there was no date in the orignal input values. So set a flag we can use
  // later to tell that this date object was created using only time and that the date
  // values are artifical.
  if (empty($final_date['year']) && empty($final_date['month']) && empty($final_date['day'])) {
    $this->timeOnly = TRUE;
  }
  elseif (empty($this->errors)) {
    $this
      ->setDate($final_date['year'], $final_date['month'], $final_date['day']);
  }
  if (!isset($final_date['hour']) && !isset($final_date['minute']) && !isset($final_date['second'])) {
    $this->dateOnly = TRUE;
  }
  elseif (empty($this->errors)) {
    $this
      ->setTime($final_date['hour'], $final_date['minute'], $final_date['second']);
  }
  return $this;
}