PluginProbe
Import Social Events / 1.8.5
Import Social Events v1.8.5
1.9.1 1.9.0 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.3.0 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 All 61 releases
import-facebook-events / includes / lib / icalcreator / src / Util / DateTimeZoneFactory.php

DateTimeZoneFactory.php in Import Social Events 1.8.5, at includes/lib/icalcreator/src/Util/DateTimeZoneFactory.php

461 lines 18.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * iCalcreator, the PHP class package managing iCal (rfc2445/rfc5445) calendar information.
4 *
5 * copyright (c) 2007-2021 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
6 * Link https://kigkonsult.se
7 * Package iCalcreator
8 * Version 2.30
9 * License Subject matter of licence is the software iCalcreator.
10 * The above copyright, link, package and version notices,
11 * this licence notice and the invariant [rfc5545] PRODID result use
12 * as implemented and invoked in iCalcreator shall be included in
13 * all copies or substantial portions of the iCalcreator.
14 *
15 * iCalcreator is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published
17 * by the Free Software Foundation, either version 3 of the License,
18 * or (at your option) any later version.
19 *
20 * iCalcreator is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with iCalcreator. If not, see <https://www.gnu.org/licenses/>.
27 *
28 * This file is a part of iCalcreator.
29 */
30
31 namespace Kigkonsult\Icalcreator\Util;
32
33 use DateTimeZone;
34 use Exception;
35 use InvalidArgumentException;
36 use Kigkonsult\Icalcreator\Vcalendar;
37
38 use function ctype_digit;
39 use function floor;
40 use function in_array;
41 use function sprintf;
42 use function str_replace;
43 use function strlen;
44 use function strpos;
45 use function substr;
46 use function trim;
47
48 /**
49 * iCalcreator DateTimeZone support class
50 *
51 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
52 * @since 2.27.8 - 2019-01-12
53 */
54 class DateTimeZoneFactory
55 {
56
57 /**
58 * @var array
59 * @static
60 */
61 public static $UTCARR = [ 'Z', Vcalendar::UTC, Vcalendar::GMT ];
62
63 /**
64 * Return new DateTimeZone object instance
65 *
66 * @param string $tzString
67 * @return DateTimeZone
68 * @throws InvalidArgumentException
69 * @static
70 * @since 2.27.8 - 2019-01-12
71 */
72 public static function factory( $tzString = null )
73 {
74 return self::assertDateTimeZone( $tzString );
75 }
76
77 /**
78 * Assert DateTimeZoneString
79 *
80 * @param string $tzString
81 * @return DateTimeZone
82 * @throws InvalidArgumentException
83 * @static
84 * @since 2.27.14 - 2019-01-31
85 */
86 public static function assertDateTimeZone( $tzString )
87 {
88 static $ERR = 'Invalid DateTimeZone \'%s\'';
89 if( empty( $tzString ) && ( 0 != intval( $tzString ))) {
90 throw new InvalidArgumentException( sprintf( $ERR, $tzString ));
91 }
92 if( self::hasOffset( $tzString )) {
93 $tzString = self::getTimeZoneNameFromOffset( $tzString );
94 }
95 elseif( in_array( $tzString, self::$UTCARR )) {
96 $tzString = Vcalendar::UTC;
97 }
98 try {
99 $tzString = self::standard_to_name( $tzString );
100 $timeZone = new DateTimeZone( $tzString );
101 }
102 catch( Exception $e ) {
103 throw new InvalidArgumentException( sprintf( $ERR, $tzString ), null, $e );
104 }
105 return $timeZone;
106 }
107
108 /**
109 * standard timezone name converter
110 */
111 public static function standard_to_name( $tzString ){
112 $microsoftWindowsTimeZones = [
113 'Dateline Standard Time' => 'Etc/GMT+12',
114 'Aleutian Standard Time' => 'America/Adak',
115 'Hawaiian Standard Time' => 'Etc/GMT+10',
116 'Marquesas Standard Time' => 'Pacific/Marquesas',
117 'Alaskan Standard Time' => 'America/Anchorage',
118 'Pacific Standard Time (Mexico)' => 'America/Tijuana',
119 'Pacific Standard Time' => 'US/Pacific',
120 'US Mountain Standard Time' => 'Etc/GMT+7',
121 'Mountain Standard Time (Mexico)' => 'America/Chihuahua',
122 'Mountain Standard Time' => 'America/Boise',
123 'Central America Standard Time' => 'Etc/GMT+6',
124 'Central Standard Time' => 'America/Chicago',
125 'Easter Island Standard Time' => 'Pacific/Easter',
126 'Central Standard Time (Mexico)' => 'America/Mexico_City',
127 'Canada Central Standard Time' => 'America/Regina',
128 'SA Pacific Standard Time' => 'Etc/GMT+5',
129 'Eastern Standard Time (Mexico)' => 'America/Cancun',
130 'Eastern Standard Time' => 'US/Eastern',
131 'Haiti Standard Time' => 'America/Port-au-Prince',
132 'Cuba Standard Time' => 'America/Havana',
133 'US Eastern Standard Time' => 'America/Indianapolis',
134 'Paraguay Standard Time' => 'America/Asuncion',
135 'Atlantic Standard Time' => 'America/Thule',
136 'Venezuela Standard Time' => 'America/Caracas',
137 'Central Brazilian Standard Time' => 'America/Cuiaba',
138 'SA Western Standard Time' => 'Etc/GMT+4',
139 'Pacific SA Standard Time' => 'America/Santiago',
140 'Turks And Caicos Standard Time' => 'America/Grand_Turk',
141 'Newfoundland Standard Time' => 'America/St_Johns',
142 'Tocantins Standard Time' => 'America/Araguaina',
143 'E. South America Standard Time' => 'America/Sao_Paulo',
144 'SA Eastern Standard Time' => 'Etc/GMT+3',
145 'Argentina Standard Time' => 'America/Buenos_Aires',
146 'Greenland Standard Time' => 'America/Godthab',
147 'Montevideo Standard Time' => 'America/Montevideo',
148 'Magallanes Standard Time' => 'America/Punta_Arenas',
149 'Saint Pierre Standard Time' => 'America/Miquelon',
150 'Bahia Standard Time' => 'America/Bahia',
151 'Azores Standard Time' => 'Atlantic/Azores',
152 'Cape Verde Standard Time' => 'GMT+1',
153 'GMT Standard Time' => 'UTC',
154 'Greenwich Standard Time' => 'Africa/Lome',
155 'W. Europe Standard Time' => 'Europe/Vatican',
156 'Central Europe Standard Time' => 'Europe/Bratislava',
157 'Romance Standard Time' => 'Europe/Paris',
158 'Morocco Standard Time' => 'Africa/Casablanca',
159 'Sao Tome Standard Time' => 'Africa/Sao_Tome',
160 'Central European Standard Time' => 'Europe/Warsaw',
161 'W. Central Africa Standard Time' => 'Etc/GMT-1',
162 'Jordan Standard Time' => 'Asia/Amman',
163 'GTB Standard Time' => 'Europe/Bucharest',
164 'Middle East Standard Time' => 'Asia/Beirut',
165 'Egypt Standard Time' => 'Africa/Cairo',
166 'E. Europe Standard Time' => 'Europe/Chisinau',
167 'Syria Standard Time' => 'Asia/Damascus',
168 'West Bank Standard Time' => 'Asia/Gaza',
169 'South Africa Standard Time' => 'Etc/GMT-2',
170 'FLE Standard Time' => 'Europe/Kiev',
171 'Israel Standard Time' => 'Asia/Jerusalem',
172 'Kaliningrad Standard Time' => 'Europe/Kaliningrad',
173 'Sudan Standard Time' => 'Africa/Khartoum',
174 'Libya Standard Time' => 'Africa/Tripoli',
175 'Namibia Standard Time' => 'Africa/Windhoek',
176 'Arabic Standard Time' => 'Asia/Baghdad',
177 'Turkey Standard Time' => 'Europe/Istanbul',
178 'Arab Standard Time' => 'Asia/Aden',
179 'Belarus Standard Time' => 'Europe/Minsk',
180 'Russian Standard Time' => 'Europe/Simferopol',
181 'E. Africa Standard Time' => 'Etc/GMT-3',
182 'Iran Standard Time' => 'Asia/Tehran',
183 'Arabian Standard Time' => 'Etc/GMT-4',
184 'Astrakhan Standard Time' => 'Europe/Astrakhan',
185 'Azerbaijan Standard Time' => 'Asia/Baku',
186 'Russia Time Zone 3' => 'Europe/Samara',
187 'Mauritius Standard Time' => 'Indian/Mahe',
188 'Saratov Standard Time' => 'Europe/Saratov',
189 'Georgian Standard Time' => 'Asia/Tbilisi',
190 'Caucasus Standard Time' => 'Asia/Yerevan',
191 'Afghanistan Standard Time' => 'Asia/Kabul',
192 'West Asia Standard Time' => 'Etc/GMT-5',
193 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg',
194 'Pakistan Standard Time' => 'Asia/Karachi',
195 'India Standard Time' => 'Asia/Calcutta',
196 'Sri Lanka Standard Time' => 'Asia/Colombo',
197 'Nepal Standard Time' => 'Asia/Katmandu',
198 'Central Asia Standard Time' => 'Etc/GMT-6',
199 'Bangladesh Standard Time' => 'Asia/Thimphu',
200 'Omsk Standard Time' => 'Asia/Omsk',
201 'Myanmar Standard Time' => 'Asia/Rangoon',
202 'SE Asia Standard Time' => 'Etc/GMT-7',
203 'Altai Standard Time' => 'Asia/Barnaul',
204 'W. Mongolia Standard Time' => 'Asia/Hovd',
205 'North Asia Standard Time' => 'Asia/Krasnoyarsk',
206 'N. Central Asia Standard Time' => 'Asia/Novosibirsk',
207 'Tomsk Standard Time' => 'Asia/Tomsk',
208 'China Standard Time' => 'Asia/Macau',
209 'North Asia East Standard Time' => 'Asia/Irkutsk',
210 'Singapore Standard Time' => 'Etc/GMT-8',
211 'W. Australia Standard Time' => 'Australia/Perth',
212 'Taipei Standard Time' => 'Asia/Taipei',
213 'Ulaanbaatar Standard Time' => 'Asia/Ulaanbaatar',
214 'Aus Central W. Standard Time' => 'Australia/Eucla',
215 'Transbaikal Standard Time' => 'Asia/Chita',
216 'Tokyo Standard Time' => 'Etc/GMT-9',
217 'North Korea Standard Time' => 'Asia/Pyongyang',
218 'Korea Standard Time' => 'Asia/Seoul',
219 'Yakutsk Standard Time' => 'Asia/Yakutsk',
220 'Cen. Australia Standard Time' => 'Australia/Adelaide',
221 'AUS Central Standard Time' => 'Australia/Darwin',
222 'E. Australia Standard Time' => 'Australia/Brisbane',
223 'AUS Eastern Standard Time' => 'Australia/Sydney',
224 'West Pacific Standard Time' => 'Etc/GMT-10',
225 'Tasmania Standard Time' => 'Australia/Hobart',
226 'Vladivostok Standard Time' => 'Asia/Vladivostok',
227 'Lord Howe Standard Time' => 'Australia/Lord_Howe',
228 'Bougainville Standard Time' => 'Pacific/Bougainville',
229 'Russia Time Zone 10' => 'Asia/Srednekolymsk',
230 'Magadan Standard Time' => 'Asia/Magadan',
231 'Norfolk Standard Time' => 'Pacific/Norfolk',
232 'Sakhalin Standard Time' => 'Asia/Sakhalin',
233 'Central Pacific Standard Time' => 'Etc/GMT-11',
234 'Russia Time Zone 11' => 'Asia/Kamchatka',
235 'New Zealand Standard Time' => 'Pacific/Auckland',
236 'Fiji Standard Time' => 'Pacific/Fiji',
237 'Chatham Islands Standard Time' => 'Pacific/Chatham',
238 'Tonga Standard Time' => 'Pacific/Tongatapu',
239 'Samoa Standard Time' => 'Pacific/Apia',
240 'Line Islands Standard Time' => 'Etc/GMT-14'
241 ];
242 if( !array_key_exists( $tzString, $microsoftWindowsTimeZones ) ){
243 return $tzString;
244 }
245
246 return $microsoftWindowsTimeZones[$tzString];
247 }
248
249 /**
250 * Return (array) all transitions from timezone
251 *
252 * @param string|DateTimeZone $dateTimeZone
253 * @param int $from
254 * @param int $to
255 * @return array
256 * @throws InvalidArgumentException
257 * @static
258 * @since 2.27.8 - 2019-01-22
259 */
260 public static function getDateTimeZoneTransitions(
261 $dateTimeZone,
262 $from = null,
263 $to = null
264 ) {
265 if( ! $dateTimeZone instanceof DateTimeZone ) {
266 $dateTimeZone = self::factory( $dateTimeZone );
267 }
268 $res = $dateTimeZone->getTransitions( $from, $to );
269 return ( empty( $res )) ? [] : $res;
270 }
271
272 /**
273 * Return (first found) timezone from offset
274 *
275 * @param string $offset
276 * @return string
277 * @throws InvalidArgumentException
278 * @static
279 * @since 2.27.14 - 2019-02-26
280 */
281 public static function getTimeZoneNameFromOffset( $offset )
282 {
283 static $UTCOFFSET = '+00:00';
284 static $ERR = 'Offset \'%s\' (%+d seconds) don\'t match any timezone';
285 if( $UTCOFFSET == $offset ) {
286 return self::$UTCARR[1];
287 }
288 $seconds = self::offsetToSeconds( $offset );
289 $res = timezone_name_from_abbr( Util::$SP0, $seconds );
290 if( false === $res ) {
291 $res = timezone_name_from_abbr( Util::$SP0, $seconds, 0 );
292 }
293 if( false === $res ) {
294 $res = timezone_name_from_abbr( Util::$SP0, $seconds, 1 );
295 }
296 if( false === $res ) {
297 throw new InvalidArgumentException( sprintf( $ERR, $offset, $seconds ));
298 }
299 return $res;
300 }
301
302 /**
303 * Return offset part from dateString
304 *
305 * An offset is one of [+/-]NNNN, [+/-]NN:NN, [+/-]NNNNNN, [+/-]NN:NN:NN
306 * @param string $dateString
307 * @return string
308 * @static
309 0 */
310 public static function getOffset( $dateString )
311 {
312 $dateString = trim( $dateString );
313 $ix = strlen( $dateString ) - 1;
314 $offset = null;
315 while( true ) {
316 $dateX1 = substr( $dateString, $ix, 1 );
317 switch( true ) {
318 case ctype_digit( $dateX1 ) :
319 $offset = $dateX1 . $offset;
320 break;
321 case ( Util::$COLON == $dateX1 ) :
322 $offset = $dateX1 . $offset;
323 break;
324 case DateIntervalFactory::hasPlusMinusPrefix( $dateX1 ) :
325 $offset = $dateX1 . $offset;
326 break 2;
327 default :
328 $offset = null;
329 break 2;
330 } // end switch
331 if( 1 > $ix ) {
332 break;
333 }
334 $ix -= 1;
335 } // end while
336 return $offset;
337 }
338
339 /**
340 * Return bool true if input string contains (trailing) UTC/iCal offset
341 *
342 * An offset is one of [+/-]NNNN, [+/-]NN:NN, [+/-]NNNNNN, [+/-]NN:NN:NN
343 * @param string $string
344 * @return bool
345 * @static
346 * @since 2.27.14 - 2019-02-18
347 */
348 public static function hasOffset( $string )
349 {
350 $string = trim((string) $string );
351 if( empty( $string )) {
352 return false;
353 }
354 if( Vcalendar::Z == substr( $string, -1 )) {
355 return false;
356 }
357 if( false != strpos( $string, Util::$COLON )) {
358 $string = str_replace( Util::$COLON, Util::$SP0, $string );
359 }
360 if( DateIntervalFactory::hasPlusMinusPrefix( substr( $string, -5 )) &&
361 ctype_digit( substr( $string, -4 ))) {
362 return true;
363 }
364 if( DateIntervalFactory::hasPlusMinusPrefix( substr( $string, -7 )) &&
365 ctype_digit( substr( $string, -6 ))) {
366 return true;
367 }
368 return false;
369 }
370
371 /**
372 * Return bool true if UTC timezone
373 *
374 * @param string $timeZoneString
375 * @return bool
376 * @static
377 * @since 2.27.8 - 2019-01-21
378 */
379 public static function isUTCtimeZone( $timeZoneString )
380 {
381 if( empty( $timeZoneString )) {
382 return false;
383 }
384 if( self::hasOffset( $timeZoneString )) {
385 if( false !== strpos( $timeZoneString, Util::$COLON )) {
386 $timeZoneString = str_replace( Util::$COLON, null, $timeZoneString );
387 }
388 return ( empty( intval( $timeZoneString, 10 )));
389 }
390 return ( in_array( strtoupper( $timeZoneString ), self::$UTCARR ));
391 }
392
393 /**
394 * Return seconds based on an offset, [+/-]HHmm[ss], used when correcting UTC to localtime or v.v.
395 *
396 * @param string $offset
397 * @return string
398 * @static
399 * @since 2.26.7 - 2018-11-23
400 */
401 public static function offsetToSeconds( $offset )
402 {
403 $offset = trim( (string) $offset );
404 $seconds = 0;
405 if( false !== strpos( $offset, Util::$COLON )) {
406 $offset = str_replace( Util::$COLON, null, $offset );
407 }
408 $strLen = strlen( $offset );
409 if( ( 5 > $strLen ) || ( 7 < $strLen )) {
410 return $seconds;
411 }
412 if( ! DateIntervalFactory::hasPlusMinusPrefix( $offset )) {
413 return $seconds;
414 }
415 $isMinus = ( Util::$MINUS == substr( $offset, 0, 1 ));
416 if( ! ctype_digit( substr( $offset, 1 ))) {
417 return $seconds;
418 }
419 $seconds += ((int) substr( $offset, 1, 2 )) * 3600;
420 $seconds += ((int) substr( $offset, 3, 2 )) * 60;
421 if( 7 == $strLen ) {
422 $seconds += (int) substr( $offset, 5, 2 );
423 }
424 return ( $isMinus ) ? $seconds * -1 : $seconds;
425 }
426
427 /**
428 * Return iCal offset [-/+]hhmm[ss] (string) from UTC offset seconds
429 *
430 * @param string $offset
431 * @return string
432 * @static
433 * @since 2.26 - 2018-11-10
434 */
435 public static function secondsToOffset( $offset )
436 {
437 static $FMT = '%02d';
438 switch( substr( $offset, 0, 1 )) {
439 case Util::$MINUS :
440 $output = Util::$MINUS;
441 $offset = substr( $offset, 1 );
442 break;
443 case Util::$PLUS :
444 $output = Util::$PLUS;
445 $offset = substr( $offset, 1 );
446 break;
447 default :
448 $output = Util::$PLUS;
449 break;
450 } // end switch
451 $output .= sprintf( $FMT, ((int) floor( $offset / 3600 ))); // hour
452 $seconds = $offset % 3600;
453 $output .= sprintf( $FMT, ((int) floor( $seconds / 60 ))); // min
454 $seconds = $seconds % 60;
455 if( 0 < $seconds ) {
456 $output .= sprintf( $FMT, $seconds ); // sec
457 }
458 return $output;
459 }
460 }
461