/**
  * create timezone and standard/daylight components
  *
  * Result when 'Europe/Stockholm' and no from/to arguments is used as timezone:
  *
  * BEGIN:VTIMEZONE
  * TZID:Europe/Stockholm
  * BEGIN:STANDARD
  * DTSTART:20101031T020000
  * TZOFFSETFROM:+0200
  * TZOFFSETTO:+0100
  * TZNAME:CET
  * END:STANDARD
  * BEGIN:DAYLIGHT
  * DTSTART:20100328T030000
  * TZOFFSETFROM:+0100
  * TZOFFSETTO:+0200
  * TZNAME:CEST
  * END:DAYLIGHT
  * END:VTIMEZONE
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.11.8 - 2012-02-06
  * Generates components for all transitions in a date range, based on contribution by Yitzchok Lavi <*****@*****.**>
  * @param object $calendar, reference to an iCalcreator calendar instance
  * @param string $timezone, a PHP5 (DateTimeZone) valid timezone
  * @param array  $xProp,    *[x-propName => x-propValue], optional
  * @param int    $from      an unix timestamp
  * @param int    $to        an unix timestamp
  * @return bool
  */
 public static function createTimezone(&$calendar, $timezone, $xProp = array(), $from = null, $to = null)
 {
     if (!class_exists('DateTimeZone')) {
         return FALSE;
     }
     if (empty($timezone)) {
         return FALSE;
     }
     try {
         $dtz = new DateTimeZone($timezone);
         $transitions = $dtz->getTransitions();
         unset($dtz);
         $utcTz = new DateTimeZone('UTC');
     } catch (Exception $e) {
         return FALSE;
     }
     if (empty($to)) {
         $dates = array_keys($calendar->getProperty('dtstart'));
     }
     $transCnt = 2;
     // number of transitions in output if empty input $from/$to and an empty dates-array
     $dateFrom = new DateTime('now');
     $dateTo = new DateTime('now');
     if (!empty($from)) {
         $dateFrom->setTimestamp($from);
     } else {
         if (!empty($dates)) {
             $dateFrom = new DateTime(reset($dates));
         }
         // set lowest date to the lowest dtstart date
         $dateFrom->modify('-1 month');
         // set $dateFrom to one month before the lowest date
     }
     $dateFrom->setTimezone($utcTz);
     // convert local date to UTC
     if (!empty($to)) {
         $dateTo->setTimestamp($to);
     } else {
         if (!empty($dates)) {
             $dateTo = new DateTime(end($dates));
             // set highest date to the highest dtstart date
             $to = $dateTo->getTimestamp();
             // set mark that a highest date is found
         }
         $dateTo->modify('+1 year');
         // set $dateTo to one year after the highest date
     }
     $dateTo->setTimezone($utcTz);
     // convert local date to UTC
     $transTemp = array();
     $prevOffsetfrom = $stdCnt = $dlghtCnt = 0;
     $stdIx = $dlghtIx = null;
     $date = new DateTime('now', $utcTz);
     foreach ($transitions as $tix => $trans) {
         // all transitions in date-time order!!
         $date->setTimestamp($trans['ts']);
         // set transition date (UTC)
         if ($date < $dateFrom) {
             $prevOffsetfrom = $trans['offset'];
             // previous trans offset will be 'next' trans offsetFrom
             continue;
         }
         if ($date > $dateTo) {
             break;
         }
         // loop always (?) breaks here
         if (!empty($prevOffsetfrom) || 0 == $prevOffsetfrom) {
             $trans['offsetfrom'] = $prevOffsetfrom;
             // i.e. set previous offsetto as offsetFrom
             $date->modify($trans['offsetfrom'] . 'seconds');
             // convert utc date to local date
             $trans['time'] = array('year' => $date->format('Y'), 'month' => $date->format('n'), 'day' => $date->format('j'), 'hour' => $date->format('G'), 'min' => $date->format('i'), 'sec' => $date->format('s'));
         }
         $prevOffsetfrom = $trans['offset'];
         $trans['prevYear'] = $trans['time']['year'];
         if (TRUE !== $trans['isdst']) {
             // standard timezone
             if (!empty($stdIx) && isset($transTemp[$stdIx]['offsetfrom']) && $transTemp[$stdIx]['abbr'] == $trans['abbr'] && $transTemp[$stdIx]['offsetfrom'] == $trans['offsetfrom'] && $transTemp[$stdIx]['offset'] == $trans['offset'] && $transTemp[$stdIx]['prevYear'] + 1 == $trans['time']['year']) {
                 $transTemp[$stdIx]['prevYear'] = $trans['time']['year'];
                 $transTemp[$stdIx]['rdate'][] = $trans['time'];
                 continue;
             }
             $stdIx = $tix;
             $stdCnt += 1;
         } else {
             // daylight timezone
             if (!empty($dlghtIx) && isset($transTemp[$dlghtIx]['offsetfrom']) && $transTemp[$dlghtIx]['abbr'] == $trans['abbr'] && $transTemp[$dlghtIx]['offsetfrom'] == $trans['offsetfrom'] && $transTemp[$dlghtIx]['offset'] == $trans['offset'] && $transTemp[$dlghtIx]['prevYear'] + 1 == $trans['time']['year']) {
                 $transTemp[$dlghtIx]['prevYear'] = $trans['time']['year'];
                 $transTemp[$dlghtIx]['rdate'][] = $trans['time'];
                 continue;
             }
             $dlghtIx = $tix;
             $dlghtCnt += 1;
         }
         // end daylight timezone
         if (empty($to) && $transCnt == count($transTemp)) {
             // store only $transCnt transitions
             if (TRUE !== $transTemp[0]['isdst']) {
                 $stdCnt -= 1;
             } else {
                 $dlghtCnt -= 1;
             }
             array_shift($transTemp);
         }
         // end if( empty( $to ) && ( $transCnt == count( $transTemp )))
         $transTemp[$tix] = $trans;
     }
     // end foreach( $transitions as $tix => $trans )
     unset($transitions);
     if (empty($transTemp)) {
         return FALSE;
     }
     $tz =& $calendar->newComponent('vtimezone');
     $tz->setproperty('tzid', $timezone);
     if (!empty($xProp)) {
         foreach ($xProp as $xPropName => $xPropValue) {
             if ('x-' == strtolower(substr($xPropName, 0, 2))) {
                 $tz->setproperty($xPropName, $xPropValue);
             }
         }
     }
     foreach ($transTemp as $trans) {
         $type = TRUE !== $trans['isdst'] ? 'standard' : 'daylight';
         $scomp =& $tz->newComponent($type);
         $scomp->setProperty('dtstart', $trans['time']);
         //      $scomp->setProperty( 'x-utc-timestamp', $trans['ts'] );   // test ###
         if (!empty($trans['abbr'])) {
             $scomp->setProperty('tzname', $trans['abbr']);
         }
         $scomp->setProperty('tzoffsetfrom', iCalUtilityFunctions::offsetSec2His($trans['offsetfrom']));
         $scomp->setProperty('tzoffsetto', iCalUtilityFunctions::offsetSec2His($trans['offset']));
         if (isset($trans['rdate'])) {
             $scomp->setProperty('RDATE', $trans['rdate']);
         }
     }
     return TRUE;
 }
예제 #2
0
 /**
  * create a calendar timezone and standard/daylight components
  *
  * Result when 'Europe/Stockholm' and no from/to arguments is used as timezone:
  *
  * BEGIN:VTIMEZONE
  * TZID:Europe/Stockholm
  * BEGIN:STANDARD
  * DTSTART:20101031T020000
  * TZOFFSETFROM:+0200
  * TZOFFSETTO:+0100
  * TZNAME:CET
  * END:STANDARD
  * BEGIN:DAYLIGHT
  * DTSTART:20100328T030000
  * TZOFFSETFROM:+0100
  * TZOFFSETTO:+0200
  * TZNAME:CEST
  * END:DAYLIGHT
  * END:VTIMEZONE
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.16.1 - 2012-11-26
  * Generates components for all transitions in a date range, based on contribution by Yitzchok Lavi <*****@*****.**>
  * Additional changes jpirkey
  * @param object $calendar, reference to an iCalcreator calendar instance
  * @param string $timezone, a PHP5 (DateTimeZone) valid timezone
  * @param array  $xProp,    *[x-propName => x-propValue], optional
  * @param int    $from      a unix timestamp
  * @param int    $to        a unix timestamp
  * @return bool
  */
 public static function createTimezone(&$calendar, $timezone, $xProp = array(), $from = null, $to = null)
 {
     if (empty($timezone)) {
         return FALSE;
     }
     if (!empty($from) && !is_int($from)) {
         return FALSE;
     }
     if (!empty($to) && !is_int($to)) {
         return FALSE;
     }
     try {
         $dtz = new DateTimeZone($timezone);
         $transitions = $dtz->getTransitions();
         $utcTz = new DateTimeZone('UTC');
     } catch (Exception $e) {
         return FALSE;
     }
     if (empty($to)) {
         $dates = array_keys($calendar->getProperty('dtstart'));
         if (empty($dates)) {
             $dates = array(date('Ymd'));
         }
     }
     if (!empty($from)) {
         $dateFrom = new DateTime("@{$from}");
     } else {
         $from = reset($dates);
         // set lowest date to the lowest dtstart date
         $dateFrom = new DateTime($from . 'T000000', $dtz);
         $dateFrom->modify('-1 month');
         // set $dateFrom to one month before the lowest date
         $dateFrom->setTimezone($utcTz);
         // convert local date to UTC
     }
     $dateFromYmd = $dateFrom->format('Y-m-d');
     if (!empty($to)) {
         $dateTo = new DateTime("@{$to}");
     } else {
         $to = end($dates);
         // set highest date to the highest dtstart date
         $dateTo = new DateTime($to . 'T235959', $dtz);
         $dateTo->modify('+1 year');
         // set $dateTo to one year after the highest date
         $dateTo->setTimezone($utcTz);
         // convert local date to UTC
     }
     $dateToYmd = $dateTo->format('Y-m-d');
     unset($dtz);
     $transTemp = array();
     $prevOffsetfrom = 0;
     $stdIx = $dlghtIx = null;
     $prevTrans = FALSE;
     foreach ($transitions as $tix => $trans) {
         // all transitions in date-time order!!
         $date = new DateTime("@{$trans['ts']}");
         // set transition date (UTC)
         $transDateYmd = $date->format('Y-m-d');
         if ($transDateYmd < $dateFromYmd) {
             $prevOffsetfrom = $trans['offset'];
             // previous trans offset will be 'next' trans offsetFrom
             $prevTrans = $trans;
             // save it in case we don't find any that match
             $prevTrans['offsetfrom'] = 0 < $tix ? $transitions[$tix - 1]['offset'] : 0;
             continue;
         }
         if ($transDateYmd > $dateToYmd) {
             break;
         }
         // loop always (?) breaks here
         if (!empty($prevOffsetfrom) || 0 == $prevOffsetfrom) {
             $trans['offsetfrom'] = $prevOffsetfrom;
             // i.e. set previous offsetto as offsetFrom
             $date->modify($trans['offsetfrom'] . 'seconds');
             // convert utc date to local date
             $d = $date->format('Y-n-j-G-i-s');
             // set date to array to ease up dtstart and (opt) rdate setting
             $d = explode('-', $d);
             $trans['time'] = array('year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5]);
         }
         $prevOffsetfrom = $trans['offset'];
         if (TRUE !== $trans['isdst']) {
             // standard timezone
             if (!empty($stdIx) && isset($transTemp[$stdIx]['offsetfrom']) && $transTemp[$stdIx]['abbr'] == $trans['abbr'] && $transTemp[$stdIx]['offsetfrom'] == $trans['offsetfrom'] && $transTemp[$stdIx]['offset'] == $trans['offset']) {
                 $transTemp[$stdIx]['rdate'][] = $trans['time'];
                 continue;
             }
             $stdIx = $tix;
         } else {
             // daylight timezone
             if (!empty($dlghtIx) && isset($transTemp[$dlghtIx]['offsetfrom']) && $transTemp[$dlghtIx]['abbr'] == $trans['abbr'] && $transTemp[$dlghtIx]['offsetfrom'] == $trans['offsetfrom'] && $transTemp[$dlghtIx]['offset'] == $trans['offset']) {
                 $transTemp[$dlghtIx]['rdate'][] = $trans['time'];
                 continue;
             }
             $dlghtIx = $tix;
         }
         // end daylight timezone
         $transTemp[$tix] = $trans;
     }
     // end foreach( $transitions as $tix => $trans )
     $tz =& $calendar->newComponent('vtimezone');
     $tz->setproperty('tzid', $timezone);
     if (!empty($xProp)) {
         foreach ($xProp as $xPropName => $xPropValue) {
             if ('x-' == strtolower(substr($xPropName, 0, 2))) {
                 $tz->setproperty($xPropName, $xPropValue);
             }
         }
     }
     if (empty($transTemp)) {
         // if no match found
         if ($prevTrans) {
             // then we use the last transition (before startdate) for the tz info
             $date = new DateTime("@{$prevTrans['ts']}");
             // set transition date (UTC)
             $date->modify($prevTrans['offsetfrom'] . 'seconds');
             // convert utc date to local date
             $d = $date->format('Y-n-j-G-i-s');
             // set date to array to ease up dtstart setting
             $d = explode('-', $d);
             $prevTrans['time'] = array('year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5]);
             $transTemp[0] = $prevTrans;
         } else {
             // or we use the timezone identifier to BUILD the standard tz info (?)
             $date = new DateTime('now', new DateTimeZone($timezone));
             $transTemp[0] = array('time' => $date->format('Y-m-d\\TH:i:s O'), 'offset' => $date->format('Z'), 'offsetfrom' => $date->format('Z'), 'isdst' => FALSE);
         }
     }
     unset($transitions, $date, $prevTrans);
     foreach ($transTemp as $tix => $trans) {
         $type = TRUE !== $trans['isdst'] ? 'standard' : 'daylight';
         $scomp =& $tz->newComponent($type);
         $scomp->setProperty('dtstart', $trans['time']);
         //      $scomp->setProperty( 'x-utc-timestamp', $tix.' : '.$trans['ts'] );   // test ###
         if (!empty($trans['abbr'])) {
             $scomp->setProperty('tzname', $trans['abbr']);
         }
         if (isset($trans['offsetfrom'])) {
             $scomp->setProperty('tzoffsetfrom', iCalUtilityFunctions::offsetSec2His($trans['offsetfrom']));
         }
         $scomp->setProperty('tzoffsetto', iCalUtilityFunctions::offsetSec2His($trans['offset']));
         if (isset($trans['rdate'])) {
             $scomp->setProperty('RDATE', $trans['rdate']);
         }
     }
     return TRUE;
 }
 /**
  * create (very simple) timezone and standard/daylight components
  *
  * Result when 'Europe/Stockholm' is used as timezone:
  *
  * BEGIN:VTIMEZONE
  * TZID:Europe/Stockholm
  * BEGIN:STANDARD
  * DTSTART:20101031T020000
  * TZOFFSETFROM:+0200
  * TZOFFSETTO:+0100
  * RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
  * TZNAME:CET
  * END:STANDARD
  * BEGIN:DAYLIGHT
  * DTSTART:20100328T030000
  * TZOFFSETFROM:+0100
  * TZOFFSETTO:+0200
  * RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
  * TZNAME:CEST
  * END:DAYLIGHT
  * END:VTIMEZONE
  *
  * @author Kjell-Inge Gustafsson, kigkonsult <*****@*****.**>
  * @since 2.10.3 - 2011-08-01
  * @param object $calendar, reference to an iCalcreator calendar instance
  * @param string $timezone, a PHP5 (DateTimeZone) valid timezone
  * @param array $xProp, *[x-propName => x-propValue], optional
  * @return bool
  */
 public static function createTimezone(&$calendar, $timezone, $xProp = array())
 {
     if (!class_exists('DateTimeZone')) {
         return FALSE;
     }
     if (empty($timezone)) {
         return FALSE;
     }
     try {
         $dtz = new DateTimeZone($timezone);
     } catch (Exception $e) {
         return FALSE;
     }
     $stdDTSTART = $stdTZOFFSETTO = $stdTZOFFSETFROM = $stdTZNAME = $dlghtDTSTART = $dlghtTZOFFSETTO = $dlghtTZOFFSETFROM = $dlghtTZNAME = FALSE;
     $dateNow = new DateTime();
     $transitions = $dtz->getTransitions();
     foreach ($transitions as $trans) {
         if (FALSE === ($date = DateTime::createFromFormat('Y-m-d', substr($trans['time'], 0, 10)))) {
             continue;
         }
         if ($date > $dateNow) {
             break;
         }
         if (TRUE !== $trans['isdst']) {
             $stdDTSTART = $trans['time'];
             $stdTZOFFSETTO = $dlghtTZOFFSETFROM = iCalUtilityFunctions::offsetSec2His($trans['offset']);
             $stdTZNAME = $trans['abbr'];
         } else {
             $dlghtDTSTART = $trans['time'];
             $dlghtTZOFFSETTO = $stdTZOFFSETFROM = iCalUtilityFunctions::offsetSec2His($trans['offset']);
             $dlghtTZNAME = $trans['abbr'];
         }
     }
     if (!$stdDTSTART || !$stdTZOFFSETTO || !$stdTZOFFSETFROM) {
         return FALSE;
     }
     $tz =& $calendar->newComponent('vtimezone');
     $tz->setproperty('tzid', $timezone);
     if (!empty($xProp)) {
         foreach ($xProp as $xPropName => $xPropValue) {
             if ('x-' == strtolower(substr($xPropName, 0, 2))) {
                 $tz->setproperty($xPropName, $xPropValue);
             }
         }
     }
     $std =& $tz->newComponent('standard');
     $std->setProperty('dtstart', $stdDTSTART);
     if ($stdTZNAME) {
         $std->setProperty('tzname', $stdTZNAME);
     }
     $std->setProperty('tzoffsetto', $stdTZOFFSETTO);
     $std->setProperty('tzoffsetfrom', $stdTZOFFSETFROM);
     if ($stdTZOFFSETTO != $stdTZOFFSETFROM && FALSE === iCalUtilityFunctions::_setTZrrule($std)) {
         $std->setProperty('RRULE', array('FREQ' => 'YEARLY', 'BYDAY' => array('-1', 'DAY' => 'SU'), 'BYMONTH' => 10));
     }
     if (!$dlghtDTSTART || !$dlghtTZOFFSETTO || !$dlghtTZOFFSETFROM || $dlghtTZOFFSETTO == $dlghtTZOFFSETFROM) {
         return TRUE;
     }
     $dlght =& $tz->newComponent('daylight');
     $dlght->setProperty('dtstart', $dlghtDTSTART);
     if ($dlghtTZNAME) {
         $dlght->setProperty('tzname', $dlghtTZNAME);
     }
     $dlght->setProperty('tzoffsetto', $dlghtTZOFFSETTO);
     $dlght->setProperty('tzoffsetfrom', $dlghtTZOFFSETFROM);
     if (FALSE === iCalUtilityFunctions::_setTZrrule($dlght)) {
         $dlght->setProperty('RRULE', array('FREQ' => 'YEARLY', 'BYDAY' => array('-1', 'DAY' => 'SU'), 'BYMONTH' => 3));
     }
     return TRUE;
 }