ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
TimeZoneUtil.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\VObject;
4
16
17 static $map = null;
18
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
125 static function getTimeZone($tzid, Component $vcalendar = null, $failIfUncertain = false) {
126
127 // First we will just see if the tzid is a support timezone identifier.
128 //
129 // The only exception is if the timezone starts with (. This is to
130 // handle cases where certain microsoft products generate timezone
131 // identifiers that for instance look like:
132 //
133 // (GMT+01.00) Sarajevo/Warsaw/Zagreb
134 //
135 // Since PHP 5.5.10, the first bit will be used as the timezone and
136 // this method will return just GMT+01:00. This is wrong, because it
137 // doesn't take DST into account.
138 if ($tzid[0] !== '(') {
139
140 // PHP has a bug that logs PHP warnings even it shouldn't:
141 // https://bugs.php.net/bug.php?id=67881
142 //
143 // That's why we're checking if we'll be able to successfull instantiate
144 // \DateTimeZone() before doing so. Otherwise we could simply instantiate
145 // and catch the exception.
146 $tzIdentifiers = \DateTimeZone::listIdentifiers();
147
148 try {
149 if (
150 (in_array($tzid, $tzIdentifiers)) ||
151 (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) ||
152 (in_array($tzid, self::getIdentifiersBC()))
153 ) {
154 return new \DateTimeZone($tzid);
155 }
156 } catch (\Exception $e) {
157 }
158
159 }
160
162
163 // Next, we check if the tzid is somewhere in our tzid map.
164 if (isset(self::$map[$tzid])) {
165 return new \DateTimeZone(self::$map[$tzid]);
166 }
167
168 // Some Microsoft products prefix the offset first, so let's strip that off
169 // and see if it is our tzid map. We don't want to check for this first just
170 // in case there are overrides in our tzid map.
171 if (preg_match('/^\‍((UTC|GMT)(\+|\-)[\d]{2}\:[\d]{2}\‍) (.*)/', $tzid, $matches)) {
172 $tzidAlternate = $matches[3];
173 if (isset(self::$map[$tzidAlternate])) {
174 return new \DateTimeZone(self::$map[$tzidAlternate]);
175 }
176 }
177
178 // Maybe the author was hyper-lazy and just included an offset. We
179 // support it, but we aren't happy about it.
180 if (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) {
181
182 // Note that the path in the source will never be taken from PHP 5.5.10
183 // onwards. PHP 5.5.10 supports the "GMT+0100" style of format, so it
184 // already gets returned early in this function. Once we drop support
185 // for versions under PHP 5.5.10, this bit can be taken out of the
186 // source.
187 // @codeCoverageIgnoreStart
188 return new \DateTimeZone('Etc/GMT' . $matches[1] . ltrim(substr($matches[2], 0, 2), '0'));
189 // @codeCoverageIgnoreEnd
190 }
191
192 if ($vcalendar) {
193
194 // If that didn't work, we will scan VTIMEZONE objects
195 foreach ($vcalendar->select('VTIMEZONE') as $vtimezone) {
196
197 if ((string)$vtimezone->TZID === $tzid) {
198
199 // Some clients add 'X-LIC-LOCATION' with the olson name.
200 if (isset($vtimezone->{'X-LIC-LOCATION'})) {
201
202 $lic = (string)$vtimezone->{'X-LIC-LOCATION'};
203
204 // Libical generators may specify strings like
205 // "SystemV/EST5EDT". For those we must remove the
206 // SystemV part.
207 if (substr($lic, 0, 8) === 'SystemV/') {
208 $lic = substr($lic, 8);
209 }
210
211 return self::getTimeZone($lic, null, $failIfUncertain);
212
213 }
214 // Microsoft may add a magic number, which we also have an
215 // answer for.
216 if (isset($vtimezone->{'X-MICROSOFT-CDO-TZID'})) {
217 $cdoId = (int)$vtimezone->{'X-MICROSOFT-CDO-TZID'}->getValue();
218
219 // 2 can mean both Europe/Lisbon and Europe/Sarajevo.
220 if ($cdoId === 2 && strpos((string)$vtimezone->TZID, 'Sarajevo') !== false) {
221 return new \DateTimeZone('Europe/Sarajevo');
222 }
223
224 if (isset(self::$microsoftExchangeMap[$cdoId])) {
225 return new \DateTimeZone(self::$microsoftExchangeMap[$cdoId]);
226 }
227 }
228
229 }
230
231 }
232
233 }
234
235 if ($failIfUncertain) {
236 throw new \InvalidArgumentException('We were unable to determine the correct PHP timezone for tzid: ' . $tzid);
237 }
238
239 // If we got all the way here, we default to UTC.
240 return new \DateTimeZone(date_default_timezone_get());
241
242 }
243
248 static function loadTzMaps() {
249
250 if (!is_null(self::$map)) return;
251
252 self::$map = array_merge(
253 include __DIR__ . '/timezonedata/windowszones.php',
254 include __DIR__ . '/timezonedata/lotuszones.php',
255 include __DIR__ . '/timezonedata/exchangezones.php',
256 include __DIR__ . '/timezonedata/php-workaround.php'
257 );
258
259 }
260
272 static function getIdentifiersBC() {
273 return include __DIR__ . '/timezonedata/php-bc.php';
274 }
275
276}
An exception for terminatinating execution or to throw for unit testing.
Time zone name translation.
static loadTzMaps()
This method will load in all the tz mapping information, if it's not yet done.
static $microsoftExchangeMap
List of microsoft exchange timezone ids.
static getIdentifiersBC()
This method returns an array of timezone identifiers, that are supported by DateTimeZone(),...
static getTimeZone($tzid, Component $vcalendar=null, $failIfUncertain=false)
This method will try to find out the correct timezone for an iCalendar date-time value.