You are here

public function DateIcalIcalcreatorParser::formatDateTime in Date iCal 7.2

Format date fields.

Return value

FeedsDateTime

File

includes/DateIcalIcalcreatorParser.inc, line 206
Classes implementing Date iCal's iCalcreator-based parser functionality.

Class

DateIcalIcalcreatorParser
@file Classes implementing Date iCal's iCalcreator-based parser functionality.

Code

public function formatDateTime($property_key, $property, DateIcalIcalcreatorComponent $item, DateIcalParserResult $result, FeedsSource $source) {
  $context = get_defined_vars();
  $date_array = $property['value'];

  // It's frustrating that iCalcreator gives us date data in a different
  // format than what it expects us to give back.
  if (isset($property['params']['TZID'])) {
    $date_array['tz'] = $property['params']['TZID'];
  }
  if (isset($property['params']['VALUE']) && $property['params']['VALUE'] == 'DATE') {

    /**
     * DATE values are All Day events, with no time-of-day.
     * They can span over multiple days.
     * FeedsDateTime sets the granularity correctly.
     * However the granularity is not used yet.
     * All Day events handling is not finalized at the time of writing.
     * http://drupal.org/node/874322 To Date & All Day Date Handling
     */
    if ($property_key == 'dtend') {
      $start_prop = $item
        ->getProperty('dtstart');
      $start_array = $start_prop['value'];
      if (isset($start_prop['params']['TZID'])) {
        $start_array['tz'] = $start_prop['params']['TZID'];
      }
      if (module_exists('date_all_day')) {

        // If the Date All Day module is installed, we need to rewind the
        // DTEND by one day, because of the problem with FeedsDateTime
        // mentioned below.
        $date_array['day'] -= 1;
      }
    }

    // The order in which the source -> target mapping is set up matters here: dtstart has to come before dtend.
    // This has been noted in the description for this source field.
    if ($property_key == 'dtstart') {
      if ($duration = $item
        ->getProperty('duration')) {
        $end_array = iCalUtilityFunctions::_duration2date($date_array, $duration['value']);
        $item
          ->setProperty('dtend', $end_array);
      }
      elseif (!$item
        ->getProperty('dtend')) {

        // For cases where a VEVENT component specifies a DTSTART property with a DATE value type
        // but no DTEND nor DURATION property, the event's duration is taken to be one day.
        $end_array = $date_array;
        $end_array['day'] += 1;
        $item
          ->setProperty('dtend', $end_array);
      }
    }

    // FeedsDateTime's implementation of setTimezone() assumes that dates with no time element should just ignore
    // timezone changes, so I had to add the 00:00:00 explicitly, even though it shouldn't be necessary.
    $date_string = sprintf('%d-%d-%d 00:00:00', $date_array['year'], $date_array['month'], $date_array['day']);

    // Set the timezone for All Day events to the server's timezone, rather than letting them default to UTC,
    // so that they don't get improperly offset when saved to the DB.
    $parsed_datetime = new FeedsDateTime($date_string, new DateTimeZone(date_default_timezone_get()));
  }
  else {

    // Date with time.
    $date_string = iCalUtilityFunctions::_format_date_time($date_array);
    $tz = NULL;
    if (isset($date_array['tz'])) {

      // 'Z' == 'Zulu' == 'UTC'. DateTimeZone won't acept Z, so change it to UTC.
      if (strtoupper($date_array['tz']) == 'Z') {
        $date_array['tz'] = 'UTC';
      }

      // Allow modules to alter the timezone string before it gets converted into a DateTimeZone.
      drupal_alter('date_ical_timezone', $date_array['tz'], $context);
      try {
        $tz = new DateTimeZone($date_array['tz']);
      } catch (Exception $e) {
        $source
          ->log('parse', t('"%tzid" is not recognized by PHP as a valid timezone, so UTC was used instead. Try implementing hook_date_ical_timezone_alter() in a custom module to fix this problem.', array(
          '%tzid' => $date_array['tz'],
        )), array(), WATCHDOG_WARNING);
        drupal_set_message(t('"%tzid" is not recognized by PHP as a valid timezone, so UTC was used instead. Try implementing hook_date_ical_timezone_alter() in a custom module to fix this problem.', array(
          '%tzid' => $date_array['tz'],
        )), 'warning');
      }
    }
    else {
      if (!empty($result->timezone)) {

        // Use the timezone that was detected for the entire iCal feed.
        $tz = $result->timezone;
      }
    }

    // If this iCal object has no DTEND, but it does have a DURATION, emulate DTEND as DTSTART + DURATION.
    // Again, this mechanism requires that dtstart be parsed before dtend in the source->target mapping.
    if ($property_key == 'dtstart' && !$item
      ->getProperty('dtend') && ($duration = $item
      ->getProperty('duration'))) {
      $end_array = iCalUtilityFunctions::_duration2date($date_array, $duration['value']);
      $item
        ->setProperty('dtend', $end_array);
    }
    $parsed_datetime = new FeedsDateTime($date_string, $tz);
  }

  // Allow modules to alter the FeedsDateTime object before it's mapped to the target.
  drupal_alter('date_ical_feeds_object', $parsed_datetime, $context);
  return $parsed_datetime;
}