Mercurial > hg > rc1
comparison vendor/sabre/vobject/lib/TimeZoneUtil.php @ 7:430dbd5346f7
vendor sabre as distributed
| author | Charlie Root |
|---|---|
| date | Sat, 13 Jan 2018 09:06:10 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 6:cec75ba50afc | 7:430dbd5346f7 |
|---|---|
| 1 <?php | |
| 2 | |
| 3 namespace Sabre\VObject; | |
| 4 | |
| 5 /** | |
| 6 * Time zone name translation | |
| 7 * | |
| 8 * This file translates well-known time zone names into "Olson database" time zone names. | |
| 9 * | |
| 10 * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/). | |
| 11 * @author Frank Edelhaeuser (fedel@users.sourceforge.net) | |
| 12 * @author Evert Pot (http://evertpot.com/) | |
| 13 * @license http://sabre.io/license/ Modified BSD License | |
| 14 */ | |
| 15 class TimeZoneUtil { | |
| 16 | |
| 17 public static $map = null; | |
| 18 | |
| 19 /** | |
| 20 * List of microsoft exchange timezone ids. | |
| 21 * | |
| 22 * Source: http://msdn.microsoft.com/en-us/library/aa563018(loband).aspx | |
| 23 */ | |
| 24 public static $microsoftExchangeMap = array( | |
| 25 0 => 'UTC', | |
| 26 31 => 'Africa/Casablanca', | |
| 27 | |
| 28 // Insanely, id #2 is used for both Europe/Lisbon, and Europe/Sarajevo. | |
| 29 // I'm not even kidding.. We handle this special case in the | |
| 30 // getTimeZone method. | |
| 31 2 => 'Europe/Lisbon', | |
| 32 1 => 'Europe/London', | |
| 33 4 => 'Europe/Berlin', | |
| 34 6 => 'Europe/Prague', | |
| 35 3 => 'Europe/Paris', | |
| 36 69 => 'Africa/Luanda', // This was a best guess | |
| 37 7 => 'Europe/Athens', | |
| 38 5 => 'Europe/Bucharest', | |
| 39 49 => 'Africa/Cairo', | |
| 40 50 => 'Africa/Harare', | |
| 41 59 => 'Europe/Helsinki', | |
| 42 27 => 'Asia/Jerusalem', | |
| 43 26 => 'Asia/Baghdad', | |
| 44 74 => 'Asia/Kuwait', | |
| 45 51 => 'Europe/Moscow', | |
| 46 56 => 'Africa/Nairobi', | |
| 47 25 => 'Asia/Tehran', | |
| 48 24 => 'Asia/Muscat', // Best guess | |
| 49 54 => 'Asia/Baku', | |
| 50 48 => 'Asia/Kabul', | |
| 51 58 => 'Asia/Yekaterinburg', | |
| 52 47 => 'Asia/Karachi', | |
| 53 23 => 'Asia/Calcutta', | |
| 54 62 => 'Asia/Kathmandu', | |
| 55 46 => 'Asia/Almaty', | |
| 56 71 => 'Asia/Dhaka', | |
| 57 66 => 'Asia/Colombo', | |
| 58 61 => 'Asia/Rangoon', | |
| 59 22 => 'Asia/Bangkok', | |
| 60 64 => 'Asia/Krasnoyarsk', | |
| 61 45 => 'Asia/Shanghai', | |
| 62 63 => 'Asia/Irkutsk', | |
| 63 21 => 'Asia/Singapore', | |
| 64 73 => 'Australia/Perth', | |
| 65 75 => 'Asia/Taipei', | |
| 66 20 => 'Asia/Tokyo', | |
| 67 72 => 'Asia/Seoul', | |
| 68 70 => 'Asia/Yakutsk', | |
| 69 19 => 'Australia/Adelaide', | |
| 70 44 => 'Australia/Darwin', | |
| 71 18 => 'Australia/Brisbane', | |
| 72 76 => 'Australia/Sydney', | |
| 73 43 => 'Pacific/Guam', | |
| 74 42 => 'Australia/Hobart', | |
| 75 68 => 'Asia/Vladivostok', | |
| 76 41 => 'Asia/Magadan', | |
| 77 17 => 'Pacific/Auckland', | |
| 78 40 => 'Pacific/Fiji', | |
| 79 67 => 'Pacific/Tongatapu', | |
| 80 29 => 'Atlantic/Azores', | |
| 81 53 => 'Atlantic/Cape_Verde', | |
| 82 30 => 'America/Noronha', | |
| 83 8 => 'America/Sao_Paulo', // Best guess | |
| 84 32 => 'America/Argentina/Buenos_Aires', | |
| 85 60 => 'America/Godthab', | |
| 86 28 => 'America/St_Johns', | |
| 87 9 => 'America/Halifax', | |
| 88 33 => 'America/Caracas', | |
| 89 65 => 'America/Santiago', | |
| 90 35 => 'America/Bogota', | |
| 91 10 => 'America/New_York', | |
| 92 34 => 'America/Indiana/Indianapolis', | |
| 93 55 => 'America/Guatemala', | |
| 94 11 => 'America/Chicago', | |
| 95 37 => 'America/Mexico_City', | |
| 96 36 => 'America/Edmonton', | |
| 97 38 => 'America/Phoenix', | |
| 98 12 => 'America/Denver', // Best guess | |
| 99 13 => 'America/Los_Angeles', // Best guess | |
| 100 14 => 'America/Anchorage', | |
| 101 15 => 'Pacific/Honolulu', | |
| 102 16 => 'Pacific/Midway', | |
| 103 39 => 'Pacific/Kwajalein', | |
| 104 ); | |
| 105 | |
| 106 /** | |
| 107 * This method will try to find out the correct timezone for an iCalendar | |
| 108 * date-time value. | |
| 109 * | |
| 110 * You must pass the contents of the TZID parameter, as well as the full | |
| 111 * calendar. | |
| 112 * | |
| 113 * If the lookup fails, this method will return the default PHP timezone | |
| 114 * (as configured using date_default_timezone_set, or the date.timezone ini | |
| 115 * setting). | |
| 116 * | |
| 117 * Alternatively, if $failIfUncertain is set to true, it will throw an | |
| 118 * exception if we cannot accurately determine the timezone. | |
| 119 * | |
| 120 * @param string $tzid | |
| 121 * @param Sabre\VObject\Component $vcalendar | |
| 122 * @return DateTimeZone | |
| 123 */ | |
| 124 static public function getTimeZone($tzid, Component $vcalendar = null, $failIfUncertain = false) { | |
| 125 | |
| 126 // First we will just see if the tzid is a support timezone identifier. | |
| 127 // | |
| 128 // The only exception is if the timezone starts with (. This is to | |
| 129 // handle cases where certain microsoft products generate timezone | |
| 130 // identifiers that for instance look like: | |
| 131 // | |
| 132 // (GMT+01.00) Sarajevo/Warsaw/Zagreb | |
| 133 // | |
| 134 // Since PHP 5.5.10, the first bit will be used as the timezone and | |
| 135 // this method will return just GMT+01:00. This is wrong, because it | |
| 136 // doesn't take DST into account. | |
| 137 if ($tzid[0]!=='(') { | |
| 138 | |
| 139 // PHP has a bug that logs PHP warnings even it shouldn't: | |
| 140 // https://bugs.php.net/bug.php?id=67881 | |
| 141 // | |
| 142 // That's why we're checking if we'll be able to successfull instantiate | |
| 143 // \DateTimeZone() before doing so. Otherwise we could simply instantiate | |
| 144 // and catch the exception. | |
| 145 $tzIdentifiers = \DateTimeZone::listIdentifiers(); | |
| 146 | |
| 147 try { | |
| 148 if ( | |
| 149 (in_array($tzid, $tzIdentifiers)) || | |
| 150 (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) || | |
| 151 (in_array($tzid, self::getIdentifiersBC())) | |
| 152 ) { | |
| 153 return new \DateTimeZone($tzid); | |
| 154 } | |
| 155 } catch(\Exception $e) { | |
| 156 } | |
| 157 | |
| 158 } | |
| 159 | |
| 160 self::loadTzMaps(); | |
| 161 | |
| 162 // Next, we check if the tzid is somewhere in our tzid map. | |
| 163 if (isset(self::$map[$tzid])) { | |
| 164 return new \DateTimeZone(self::$map[$tzid]); | |
| 165 } | |
| 166 | |
| 167 // Maybe the author was hyper-lazy and just included an offset. We | |
| 168 // support it, but we aren't happy about it. | |
| 169 if (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) { | |
| 170 | |
| 171 // Note that the path in the source will never be taken from PHP 5.5.10 | |
| 172 // onwards. PHP 5.5.10 supports the "GMT+0100" style of format, so it | |
| 173 // already gets returned early in this function. Once we drop support | |
| 174 // for versions under PHP 5.5.10, this bit can be taken out of the | |
| 175 // source. | |
| 176 // @codeCoverageIgnoreStart | |
| 177 return new \DateTimeZone('Etc/GMT' . $matches[1] . ltrim(substr($matches[2],0,2),'0')); | |
| 178 // @codeCoverageIgnoreEnd | |
| 179 } | |
| 180 | |
| 181 if ($vcalendar) { | |
| 182 | |
| 183 // If that didn't work, we will scan VTIMEZONE objects | |
| 184 foreach($vcalendar->select('VTIMEZONE') as $vtimezone) { | |
| 185 | |
| 186 if ((string)$vtimezone->TZID === $tzid) { | |
| 187 | |
| 188 // Some clients add 'X-LIC-LOCATION' with the olson name. | |
| 189 if (isset($vtimezone->{'X-LIC-LOCATION'})) { | |
| 190 | |
| 191 $lic = (string)$vtimezone->{'X-LIC-LOCATION'}; | |
| 192 | |
| 193 // Libical generators may specify strings like | |
| 194 // "SystemV/EST5EDT". For those we must remove the | |
| 195 // SystemV part. | |
| 196 if (substr($lic,0,8)==='SystemV/') { | |
| 197 $lic = substr($lic,8); | |
| 198 } | |
| 199 | |
| 200 return self::getTimeZone($lic, null, $failIfUncertain); | |
| 201 | |
| 202 } | |
| 203 // Microsoft may add a magic number, which we also have an | |
| 204 // answer for. | |
| 205 if (isset($vtimezone->{'X-MICROSOFT-CDO-TZID'})) { | |
| 206 $cdoId = (int)$vtimezone->{'X-MICROSOFT-CDO-TZID'}->getValue(); | |
| 207 | |
| 208 // 2 can mean both Europe/Lisbon and Europe/Sarajevo. | |
| 209 if ($cdoId===2 && strpos((string)$vtimezone->TZID, 'Sarajevo')!==false) { | |
| 210 return new \DateTimeZone('Europe/Sarajevo'); | |
| 211 } | |
| 212 | |
| 213 if (isset(self::$microsoftExchangeMap[$cdoId])) { | |
| 214 return new \DateTimeZone(self::$microsoftExchangeMap[$cdoId]); | |
| 215 } | |
| 216 } | |
| 217 | |
| 218 } | |
| 219 | |
| 220 } | |
| 221 | |
| 222 } | |
| 223 | |
| 224 if ($failIfUncertain) { | |
| 225 throw new \InvalidArgumentException('We were unable to determine the correct PHP timezone for tzid: ' . $tzid); | |
| 226 } | |
| 227 | |
| 228 // If we got all the way here, we default to UTC. | |
| 229 return new \DateTimeZone(date_default_timezone_get()); | |
| 230 | |
| 231 } | |
| 232 | |
| 233 /** | |
| 234 * This method will load in all the tz mapping information, if it's not yet | |
| 235 * done. | |
| 236 */ | |
| 237 static public function loadTzMaps() { | |
| 238 | |
| 239 if (!is_null(self::$map)) return; | |
| 240 | |
| 241 self::$map = array_merge( | |
| 242 include __DIR__ . '/timezonedata/windowszones.php', | |
| 243 include __DIR__ . '/timezonedata/lotuszones.php', | |
| 244 include __DIR__ . '/timezonedata/exchangezones.php', | |
| 245 include __DIR__ . '/timezonedata/php-workaround.php' | |
| 246 ); | |
| 247 | |
| 248 } | |
| 249 | |
| 250 /** | |
| 251 * This method returns an array of timezone identifiers, that are supported | |
| 252 * by DateTimeZone(), but not returned by DateTimeZone::listIdentifiers() | |
| 253 * | |
| 254 * We're not using DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC) because: | |
| 255 * - It's not supported by some PHP versions as well as HHVM. | |
| 256 * - It also returns identifiers, that are invalid values for new DateTimeZone() on some PHP versions. | |
| 257 * (See timezonedata/php-bc.php and timezonedata php-workaround.php) | |
| 258 * | |
| 259 * @return array | |
| 260 */ | |
| 261 static public function getIdentifiersBC() { | |
| 262 return include __DIR__ . '/timezonedata/php-bc.php'; | |
| 263 } | |
| 264 | |
| 265 } |
