getTransitions($from - $year, $to + $year); $vcalendar = new VCalendar(); $vtimezone = $vcalendar->createComponent('VTIMEZONE'); $vtimezone->TZID = $timezone; $standard = $daylightStart = null; foreach ($transitions as $i => $trans) { $component = null; // daylight saving time definition if ($trans['isdst']) { $daylightDefinition = $trans['ts']; $daylightStart = $vcalendar->createComponent('DAYLIGHT'); $component = $daylightStart; } // standard time definition else { $standardDefinition = $trans['ts']; $standard = $vcalendar->createComponent('STANDARD'); $component = $standard; } if ($component) { if ($i === 0) { $date = new \DateTime('19700101T000000'); $tzfrom = $trans['offset'] / 3600; $offset = $tzfrom; } else { $date = new \DateTime($trans['time']); $offset = $trans['offset'] / 3600; } $component->DTSTART = $date->format('Ymd\THis'); $component->TZOFFSETFROM = sprintf('%s%02d%02d', $tzfrom >= 0 ? '+' : '-', abs(floor($tzfrom)), ((float)$tzfrom - floor($tzfrom)) * 60.0); $component->TZOFFSETTO = sprintf('%s%02d%02d', $offset >= 0 ? '+' : '-', abs(floor($offset)), ((float)$offset - floor($offset)) * 60.0); // add abbreviated timezone name if available if (!empty($trans['abbr'])) { $component->TZNAME = $trans['abbr']; } $tzfrom = $offset; $vtimezone->add($component); } // we covered the entire date range if ($standard && $daylightStart && min($standardDefinition, $daylightDefinition) < $from && max($standardDefinition, $daylightDefinition) > $to) { break; } } // add X-MICROSOFT-CDO-TZID if available $microsoftExchangeMap = array_flip(TimeZoneUtil::$microsoftExchangeMap); if (!empty($microsoftExchangeMap) && array_key_exists($tz->getName(), $microsoftExchangeMap)) { $vtimezone->add('X-MICROSOFT-CDO-TZID', $microsoftExchangeMap[$tz->getName()]); } return $vtimezone; } }