This class is the central point to fetch timezone information from the timezone (Olson) database, parse it, cache it, and generate VTIMEZONE objects. Usage: $tz = new Horde_Timezone(); $tz->getZone('America/New_York')->toVtimezone()->exportVcalendar(); Documentation on the database file formats can be found at ftp://ftp.iana.org/tz/tz-how-to.html
Author: Jan Schneider (jan@horde.org)
Esempio n. 1
0
 /**
  * Adds rules from this ruleset to a VTIMEZONE component.
  *
  * @param Horde_Icalendar_Vtimezone $tz  A VTIMEZONE component.
  * @param string $tzid                   The timezone ID of the component.
  * @param string $name                   A timezone name abbreviation.
  *                                       May contain a placeholder that is
  *                                       replaced the Rules' "Letter(s)"
  *                                       entry.
  * @param array $startOffset             An offset hash describing the
  *                                       base offset of a timezone.
  * @param Horde_Date $start              Start of the period to add rules
  *                                       for.
  * @param Horde_Date $end                End of the period to add rules
  *                                       for.
  */
 public function addRules(Horde_Icalendar_Vtimezone $tz, $tzid, $name, $startOffset, Horde_Date $start, Horde_Date $end = null)
 {
     $offset = $startOffset;
     foreach ($this->_rules as $rule) {
         $year = $rule[3];
         if ($year[0] == 'o') {
             // TO is "only"
             $rule[3] = $rule[2];
         }
         if ($rule[3][0] != 'm' && $rule[3] < $start->year) {
             // TO is not maximum and is before the searched period
             continue;
         }
         if ($end && $rule[2][0] != 'm' && $rule[2] > $end->year) {
             // FROM is not "minimum" and is after the searched period
             break;
         }
         if ($rule[2][0] != 'm' && $rule[2] < $start->year) {
             $rule[2] = $start->year;
         }
         if ($rule[8] == 0) {
             $component = new Horde_Icalendar_Standard();
             $component->setAttribute('TZOFFSETFROM', $offset);
             $component->setAttribute('TZOFFSETTO', $startOffset);
             $offset = $startOffset;
         } else {
             $component = new Horde_Icalendar_Daylight();
             $component->setAttribute('TZOFFSETFROM', $offset);
             $offset = $this->_getOffset($startOffset, $rule[8]);
             $component->setAttribute('TZOFFSETTO', $offset);
         }
         $month = Horde_Timezone::getMonth($rule[5]);
         // Retrieve time of rule start.
         preg_match('/(\\d+)(?::(\\d+))?(?::(\\d+))?(w|s|u)?/', $rule[7], $match);
         if (!isset($match[2])) {
             $match[2] = 0;
         }
         if ($rule[2] == $rule[3] && preg_match('/^\\d+$/', $rule[6])) {
             // Rule lasts only for a single year and starts on a specific
             // date.
             $rdate = new Horde_Date(array('year' => $rule[2], 'month' => Horde_Timezone::getMonth($rule[5]), 'mday' => $rule[6], 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             $component->setAttribute('DTSTART', $rdate);
         } elseif (substr($rule[6], 0, 4) == 'last') {
             // Rule starts on the last of a certain weekday of the month.
             $weekday = $this->_weekdays[substr($rule[6], 4, 3)];
             $last = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2]), 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($last->dayOfWeek() != $weekday) {
                 $last->mday--;
             }
             $component->setAttribute('DTSTART', $last);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2]), 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday--;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYDAY=-1' . Horde_String::upper(substr($rule[6], 4, 2)) . ';BYMONTH=' . $month . $until);
         } elseif (strpos($rule[6], '>=')) {
             // Rule starts on a certain weekday after a certain day of
             // month.
             list($weekday, $day) = explode('>=', $rule[6]);
             $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
             $first = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($first->dayOfWeek() != $weekdayInt) {
                 $first->mday++;
             }
             $component->setAttribute('DTSTART', $first);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday++;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             for ($days = array(), $i = $day, $lastDay = min(Horde_Date_Utils::daysInMonth($month, $rule[2]), $i + 6); $day > 1 && $i <= $lastDay; $i++) {
                 $days[] = $i;
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ($days ? ';BYMONTHDAY=' . implode(',', $days) : '') . ';BYDAY=1' . Horde_String::upper(substr($weekday, 0, 2)) . $until);
         } elseif (strpos($rule[6], '<=')) {
             // Rule starts on a certain weekday before a certain day of
             // month.
             list($weekday, $day) = explode('>=', $rule[6]);
             $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
             $last = new Horde_Date(array('year' => $rule[2], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0));
             while ($last->dayOfWeek() != $weekdayInt) {
                 $last->mday--;
             }
             $component->setAttribute('DTSTART', $last);
             if ($rule[3][0] == 'm') {
                 $until = '';
             } else {
                 $last = new Horde_Date(array('year' => $rule[3], 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => 0), $tzid);
                 while ($last->dayOfWeek() != $weekday) {
                     $last->mday--;
                 }
                 $last->setTimezone('UTC');
                 $until = ';UNTIL=' . $last->format('Ymd\\THIs') . 'Z';
             }
             for ($days = array(), $i = 1; $i <= $day; $i++) {
                 $days[] = $i;
             }
             $component->setAttribute('RRULE', 'FREQ=YEARLY;BYMONTH=' . $month . ';BYMONTHDAY=' . implode(',', $days) . ';BYDAY=-1' . Horde_String::upper(substr($weekday, 0, 2)) . $until);
         }
         $component->setAttribute('TZNAME', sprintf($name, $rule[9]));
         $tz->addComponent($component);
     }
 }
Esempio n. 2
0
File: Rule.php Progetto: horde/horde
 /**
  * Finds a date matching a rule definition.
  *
  * @param array $rule      A rule definition hash from addRules().
  * @param integer $year    A year when the rule should be applied.
  *
  * @return Horde_Date  The first matching date.
  */
 protected function _getFirstMatch($rule, $year)
 {
     $month = Horde_Timezone::getMonth($rule[5]);
     if (preg_match('/^\\d+$/', $rule[6])) {
         // Rule starts on a specific date.
         $date = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $rule[6]));
     } elseif (substr($rule[6], 0, 4) == 'last') {
         // Rule starts on the last of a certain weekday of the month.
         $weekday = $this->_weekdays[substr($rule[6], 4, 3)];
         $date = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => Horde_Date_Utils::daysInMonth($month, $rule[2])));
         while ($date->dayOfWeek() != $weekday) {
             $date->mday--;
         }
     } elseif (strpos($rule[6], '>=')) {
         // Rule starts on a certain weekday after a certain day of month.
         list($weekday, $day) = explode('>=', $rule[6]);
         $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
         $date = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $day));
         while ($date->dayOfWeek() != $weekdayInt) {
             $date->mday++;
         }
     } elseif (strpos($rule[6], '<=')) {
         // Rule starts on a certain weekday before a certain day of month.
         list($weekday, $day) = explode('>=', $rule[6]);
         $weekdayInt = $this->_weekdays[substr($weekday, 0, 3)];
         $date = new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $day));
         while ($date->dayOfWeek() != $weekdayInt) {
             $date->mday--;
         }
     } else {
         throw new Horde_Timezone_Exception('Cannot parse rule ' . $rule[6]);
     }
     return $date;
 }
Esempio n. 3
0
 /**
  * Calculates a date from the date columns of a Zone line.
  *
  * @param integer $line  A line number.
  *
  * @return Horde_Date  The date of this line.
  */
 protected function _getDate($line)
 {
     $date = array_slice($this->_info[$line], 3);
     $year = $date[0];
     $month = isset($date[1]) ? Horde_Timezone::getMonth($date[1]) : 1;
     $day = isset($date[2]) ? $date[2] : 1;
     $time = isset($date[3]) && $date[3] != '-' ? $date[3] : 0;
     preg_match('/(\\d+)(?::(\\d+))?(?::(\\d+))?(w|s|u)?/', $time, $match);
     if (!isset($match[2])) {
         $match[2] = 0;
     }
     if (!isset($match[3])) {
         $match[3] = 0;
     }
     switch (substr($time, -1)) {
         case 's':
             // Standard time. Not sure what to do about this.
             break;
         case 'u':
             // UTC, add offset.
             $offset = $this->_getOffset($line);
             $factor = $offset['ahead'] ? 1 : -1;
             $match[1] += $factor * $offset['hour'];
             $match[2] += $factor * $offset['minute'];
         case 'w':
         default:
             // Wall time, nothing to do.
             break;
     }
     return new Horde_Date(array('year' => $year, 'month' => $month, 'mday' => $day, 'hour' => $match[1], 'min' => $match[2], 'sec' => $match[3]));
 }
Esempio n. 4
0
 public function __construct($zone)
 {
     parent::__construct();
     $this->_zone = $zone;
 }