/**
  * Overridden constructor.
  *
  * @param $time
  *   time string, flexible format including timestamp.
  * @param $tz
  *   PHP DateTimeZone object, string or NULL allowed, defaults to site timezone.
  * @param $format
  *   PHP date() type format for parsing. Doesn't support timezones; if you have a timezone, send NULL
  *   and the default constructor method will hopefully parse it.
  *   $format is recommended in order to use negative or large years, which php's parser fails on.
  */
 public function __construct($time = 'now', $tz = NULL, $format = NULL)
 {
     $this->timeOnly = FALSE;
     $this->dateOnly = FALSE;
     // Allow string timezones
     if (!empty($tz) && !is_object($tz)) {
         $tz = new DateTimeZone($tz);
     } elseif (empty($tz)) {
         $tz = date_default_timezone_object();
     }
     // Special handling for Unix timestamps expressed in the local timezone.
     // Create a date object in UTC and convert it to the local timezone.
     // Don't try to turn things like '2010' with a format of 'Y' into a timestamp.
     if (is_numeric($time) && (empty($format) || $format == 'U')) {
         // Assume timestamp.
         $time = "@" . $time;
         $date = new DateObject($time, 'UTC');
         if ($tz->getName() != 'UTC') {
             $date->setTimezone($tz);
         }
         $time = $date->format(DATE_FORMAT_DATETIME);
         $format = DATE_FORMAT_DATETIME;
     }
     if (is_array($time)) {
         // Assume we were passed an indexed array.
         if (empty($time['year']) && empty($time['month']) && empty($time['day'])) {
             $this->timeOnly = TRUE;
         }
         if (empty($time['hour']) && empty($time['minute']) && empty($time['second'])) {
             $this->dateOnly = TRUE;
         }
         $this->errors = $this->arrayErrors($time);
         // Make this into an ISO date,
         // forcing a full ISO date even if some values are missing.
         $time = $this->toISO($time, TRUE);
         // We checked for errors already, skip the step of parsing the input values.
         $format = NULL;
     }
     // The parse function will also set errors on the date parts.
     if (!empty($format)) {
         $arg = self::$allgranularity;
         $element = array_pop($arg);
         while (!$this->parse($time, $tz, $format) && $element != 'year') {
             $element = array_pop($arg);
             $format = date_limit_format($format, $arg);
         }
         if ($element == 'year') {
             return FALSE;
         }
     } elseif (is_string($time)) {
         // PHP < 5.3 doesn't like the GMT- notation for parsing timezones.
         $time = str_replace("GMT-", "-", $time);
         $time = str_replace("GMT+", "+", $time);
         // We are going to let the parent dateObject do a best effort attempt to turn this
         // string into a valid date. It might fail and we want to control the error messages.
         try {
             @parent::__construct($time, $tz);
         } catch (Exception $e) {
             $this->errors['date'] = $e;
             return;
         }
         $this->setGranularityFromTime($time, $tz);
     }
     // This tz was given as just an offset, which causes problems,
     // or the timezone was invalid.
     if (!$this->getTimezone() || !preg_match('/[a-zA-Z]/', $this->getTimezone()->getName())) {
         $this->setTimezone(new DateTimeZone("UTC"));
     }
 }
 /**
  * Build a description of an iCal rule.
  *
  * Constructs a human-readable description of the rule.
  */
 function date_repeat_rrule_description($rrule, $format = 'D M d Y')
 {
     // Empty or invalid value.
     if (empty($rrule) || !strstr($rrule, 'RRULE')) {
         return;
     }
     // Make sure there will be an empty description for any unused parts.
     $description = array('!interval' => '', '!byday' => '', '!bymonth' => '', '!count' => '', '!until' => '', '!except' => '', '!additional' => '', '!week_starts_on' => '');
     $parts = self::date_repeat_split_rrule($rrule);
     $additions = $parts[2];
     $exceptions = $parts[1];
     $rrule = $parts[0];
     $interval = self::INTERVAL_options();
     switch ($rrule['FREQ']) {
         case 'WEEKLY':
             $description['!interval'] = format_plural($rrule['INTERVAL'], 'every week', 'every @count weeks') . ' ';
             break;
         case 'MONTHLY':
             $description['!interval'] = format_plural($rrule['INTERVAL'], 'every month', 'every @count months') . ' ';
             break;
         case 'YEARLY':
             $description['!interval'] = format_plural($rrule['INTERVAL'], 'every year', 'every @count years') . ' ';
             break;
         default:
             $description['!interval'] = format_plural($rrule['INTERVAL'], 'every day', 'every @count days') . ' ';
             break;
     }
     if (!empty($rrule['BYDAY'])) {
         $days = date_repeat_dow_day_options();
         $counts = date_repeat_dow_count_options();
         $results = array();
         foreach ($rrule['BYDAY'] as $byday) {
             $day = substr($byday, -2);
             $count = intval(str_replace(' ' . $day, '', $byday));
             if ($count = intval(str_replace(' ' . $day, '', $byday))) {
                 $results[] = trim(t('!repeats_every_interval on the !date_order !day_of_week', array('!repeats_every_interval ' => '', '!date_order' => strtolower($counts[substr($byday, 0, 2)]), '!day_of_week' => $days[$day])));
             } else {
                 $results[] = trim(t('!repeats_every_interval every !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => $days[$day])));
             }
         }
         $description['!byday'] = implode(' ' . t('and') . ' ', $results);
     }
     if (!empty($rrule['BYMONTH'])) {
         if (sizeof($rrule['BYMONTH']) < 12) {
             $results = array();
             $months = Yii::app()->getLocale()->getMonthNames();
             foreach ($rrule['BYMONTH'] as $month) {
                 $results[] = $months[$month];
             }
             if (!empty($rrule['BYMONTHDAY'])) {
                 $description['!bymonth'] = trim(t('!repeats_every_interval on the !month_days of !month_names', array('!repeats_every_interval ' => '', '!month_days' => implode(', ', $rrule['BYMONTHDAY']), '!month_names' => implode(', ', $results))));
             } else {
                 $description['!bymonth'] = trim(t('!repeats_every_interval on !month_names', array('!repeats_every_interval ' => '', '!month_names' => implode(', ', $results))));
             }
         }
     }
     if ($rrule['INTERVAL'] < 1) {
         $rrule['INTERVAL'] = 1;
     }
     if (!empty($rrule['COUNT'])) {
         $description['!count'] = trim(t('!repeats_every_interval !count times', array('!repeats_every_interval ' => '', '!count' => $rrule['COUNT'])));
     }
     if (!empty($rrule['UNTIL'])) {
         $until = date_ical_date($rrule['UNTIL'], 'UTC');
         date_timezone_set($until, date_default_timezone_object());
         $description['!until'] = trim(t('!repeats_every_interval until !until_date', array('!repeats_every_interval ' => '', '!until_date' => date_format_date($until, 'custom', $format))));
     }
     if ($exceptions) {
         $values = array();
         foreach ($exceptions as $exception) {
             $values[] = date_format_date(date_ical_date($exception), 'custom', $format);
         }
         $description['!except'] = trim(t('!repeats_every_interval except !except_dates', array('!repeats_every_interval ' => '', '!except_dates' => implode(', ', $values))));
     }
     if (!empty($rrule['WKST'])) {
         $day_names = date_repeat_dow_day_options();
         $description['!week_starts_on'] = trim(t('!repeats_every_interval where the week start on !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => $day_names[trim($rrule['WKST'])])));
     }
     if ($additions) {
         $values = array();
         foreach ($additions as $addition) {
             $values[] = date_format_date(date_ical_date($addition), 'custom', $format);
         }
         $description['!additional'] = trim(t('Also includes !additional_dates.', array('!additional_dates' => implode(', ', $values))));
     }
     return t('Repeats !interval !bymonth !byday !count !until !except. !additional', $description);
 }
/**
 * Custom repeat rule theme function for dates.
 *
 * @see date_repeat_rrule_description().
 */
function ringstedtheme_repeat_rrule_description($rrule, $format = 'd.M')
{
    // Empty or invalid value.
    if (empty($rrule) || !strstr($rrule, 'RRULE')) {
        return;
    }
    module_load_include('inc', 'date_api', 'date_api_ical');
    module_load_include('inc', 'date_repeat', 'date_repeat_calc');
    $parts = date_repeat_split_rrule($rrule);
    $rrule = $parts[0];
    if ($rrule['FREQ'] == 'NONE') {
        return;
    }
    // Make sure there will be an empty description for any unused parts.
    $description = array('!interval' => '', '!byday' => '', '!bymonth' => '', '!count' => '', '!until' => '', '!except' => '', '!additional' => '', '!week_starts_on' => '');
    $interval = date_repeat_interval_options();
    switch ($rrule['FREQ']) {
        case 'WEEKLY':
            if (isset($rrule['BYDAY'])) {
                $description['!interval'] = format_plural($rrule['INTERVAL'], '', 'every @count weeks') . ' ';
            } else {
                $description['!interval'] = format_plural($rrule['INTERVAL'], 'every week', 'every @count weeks') . ' ';
            }
            break;
        case 'MONTHLY':
            $description['!interval'] = format_plural($rrule['INTERVAL'], 'every month', 'every @count months') . ' ';
            break;
        case 'YEARLY':
            $description['!interval'] = format_plural($rrule['INTERVAL'], 'every year', 'every @count years') . ' ';
            break;
        default:
            $description['!interval'] = format_plural($rrule['INTERVAL'], 'every day', 'every @count days') . ' ';
            break;
    }
    if (!empty($rrule['BYDAY'])) {
        $days = date_repeat_dow_day_options();
        $counts = date_repeat_dow_count_options();
        $results = array();
        $first_day = $rrule['BYDAY'][0];
        foreach ($rrule['BYDAY'] as $byday) {
            // Get the numeric part of the BYDAY option, i.e. +3 from +3MO.
            $day = substr($byday, -2);
            $count = str_replace($day, '', $byday);
            if (!empty($count)) {
                // See if there is a 'pretty' option for this count, i.e. +1 => First.
                $order = array_key_exists($count, $counts) ? strtolower($counts[$count]) : $count;
                $results[] = trim(t('!repeats_every_interval on the !date_order !day_of_week', array('!repeats_every_interval ' => '', '!date_order' => $order, '!day_of_week' => strtolower($days[$day]))));
            } else {
                if ($first_day === $byday) {
                    $results[] = trim(t('!repeats_every_interval every  !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => strtolower($days[$day]))));
                } else {
                    $results[] = trim(t('!repeats_every_interval !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => strtolower($days[$day]))));
                }
            }
        }
        $days_count = count($rrule['BYDAY']);
        if ($days_count > 2) {
            $last_day = array_pop($results);
            $description['!byday'] = implode(' , ', $results);
            $description['!byday'] .= ' ' . t('and') . ' ' . $last_day;
        } else {
            $description['!byday'] = implode(' ' . t('and') . ' ', $results);
        }
    }
    if (!empty($rrule['BYMONTH'])) {
        if (sizeof($rrule['BYMONTH']) < 12) {
            $results = array();
            $months = date_month_names();
            foreach ($rrule['BYMONTH'] as $month) {
                $results[] = $months[$month];
            }
            if (!empty($rrule['BYMONTHDAY'])) {
                $description['!bymonth'] = trim(t('!repeats_every_interval on the !month_days of !month_names', array('!repeats_every_interval ' => '', '!month_days' => implode(', ', $rrule['BYMONTHDAY']), '!month_names' => implode(', ', $results))));
            } else {
                $description['!bymonth'] = trim(t('!repeats_every_interval on !month_names', array('!repeats_every_interval ' => '', '!month_names' => implode(', ', $results))));
            }
        }
    }
    if ($rrule['INTERVAL'] < 1) {
        $rrule['INTERVAL'] = 1;
    }
    if (!empty($rrule['COUNT'])) {
        $description['!count'] = trim(t('!repeats_every_interval !count times', array('!repeats_every_interval ' => '', '!count' => $rrule['COUNT'])));
    }
    if (!empty($rrule['UNTIL'])) {
        $until = date_ical_date($rrule['UNTIL'], 'UTC');
        date_timezone_set($until, date_default_timezone_object());
        $description['!until'] = trim(t('!repeats_every_interval until !until_date', array('!repeats_every_interval ' => '', '!until_date' => strtolower(date_format_date($until, 'custom', $format)))));
    }
    if (!empty($rrule['WKST'])) {
        $day_names = date_repeat_dow_day_options();
        $description['!week_starts_on'] = trim(t('!repeats_every_interval where the week start on !day_of_week', array('!repeats_every_interval ' => '', '!day_of_week' => $day_names[trim($rrule['WKST'])])));
    }
    return preg_replace('/\\s*\\./', '.', t('Repeats !interval !bymonth !byday !count !until !except. !additional', $description));
}