diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/sabre/vobject/lib/TimeZoneUtil.php	Sat Jan 13 09:06:10 2018 -0500
@@ -0,0 +1,265 @@
+<?php
+
+namespace Sabre\VObject;
+
+/**
+ * Time zone name translation
+ *
+ * This file translates well-known time zone names into "Olson database" time zone names.
+ *
+ * @copyright Copyright (C) 2011-2015 fruux GmbH (https://fruux.com/).
+ * @author Frank Edelhaeuser (fedel@users.sourceforge.net)
+ * @author Evert Pot (http://evertpot.com/)
+ * @license http://sabre.io/license/ Modified BSD License
+ */
+class TimeZoneUtil {
+
+    public static $map = null;
+
+    /**
+     * List of microsoft exchange timezone ids.
+     *
+     * Source: http://msdn.microsoft.com/en-us/library/aa563018(loband).aspx
+     */
+    public static $microsoftExchangeMap = array(
+        0  => 'UTC',
+        31 => 'Africa/Casablanca',
+
+        // Insanely, id #2 is used for both Europe/Lisbon, and Europe/Sarajevo.
+        // I'm not even kidding.. We handle this special case in the
+        // getTimeZone method.
+        2  => 'Europe/Lisbon',
+        1  => 'Europe/London',
+        4  => 'Europe/Berlin',
+        6  => 'Europe/Prague',
+        3  => 'Europe/Paris',
+        69 => 'Africa/Luanda', // This was a best guess
+        7  => 'Europe/Athens',
+        5  => 'Europe/Bucharest',
+        49 => 'Africa/Cairo',
+        50 => 'Africa/Harare',
+        59 => 'Europe/Helsinki',
+        27 => 'Asia/Jerusalem',
+        26 => 'Asia/Baghdad',
+        74 => 'Asia/Kuwait',
+        51 => 'Europe/Moscow',
+        56 => 'Africa/Nairobi',
+        25 => 'Asia/Tehran',
+        24 => 'Asia/Muscat', // Best guess
+        54 => 'Asia/Baku',
+        48 => 'Asia/Kabul',
+        58 => 'Asia/Yekaterinburg',
+        47 => 'Asia/Karachi',
+        23 => 'Asia/Calcutta',
+        62 => 'Asia/Kathmandu',
+        46 => 'Asia/Almaty',
+        71 => 'Asia/Dhaka',
+        66 => 'Asia/Colombo',
+        61 => 'Asia/Rangoon',
+        22 => 'Asia/Bangkok',
+        64 => 'Asia/Krasnoyarsk',
+        45 => 'Asia/Shanghai',
+        63 => 'Asia/Irkutsk',
+        21 => 'Asia/Singapore',
+        73 => 'Australia/Perth',
+        75 => 'Asia/Taipei',
+        20 => 'Asia/Tokyo',
+        72 => 'Asia/Seoul',
+        70 => 'Asia/Yakutsk',
+        19 => 'Australia/Adelaide',
+        44 => 'Australia/Darwin',
+        18 => 'Australia/Brisbane',
+        76 => 'Australia/Sydney',
+        43 => 'Pacific/Guam',
+        42 => 'Australia/Hobart',
+        68 => 'Asia/Vladivostok',
+        41 => 'Asia/Magadan',
+        17 => 'Pacific/Auckland',
+        40 => 'Pacific/Fiji',
+        67 => 'Pacific/Tongatapu',
+        29 => 'Atlantic/Azores',
+        53 => 'Atlantic/Cape_Verde',
+        30 => 'America/Noronha',
+         8 => 'America/Sao_Paulo', // Best guess
+        32 => 'America/Argentina/Buenos_Aires',
+        60 => 'America/Godthab',
+        28 => 'America/St_Johns',
+         9 => 'America/Halifax',
+        33 => 'America/Caracas',
+        65 => 'America/Santiago',
+        35 => 'America/Bogota',
+        10 => 'America/New_York',
+        34 => 'America/Indiana/Indianapolis',
+        55 => 'America/Guatemala',
+        11 => 'America/Chicago',
+        37 => 'America/Mexico_City',
+        36 => 'America/Edmonton',
+        38 => 'America/Phoenix',
+        12 => 'America/Denver', // Best guess
+        13 => 'America/Los_Angeles', // Best guess
+        14 => 'America/Anchorage',
+        15 => 'Pacific/Honolulu',
+        16 => 'Pacific/Midway',
+        39 => 'Pacific/Kwajalein',
+    );
+
+    /**
+     * This method will try to find out the correct timezone for an iCalendar
+     * date-time value.
+     *
+     * You must pass the contents of the TZID parameter, as well as the full
+     * calendar.
+     *
+     * If the lookup fails, this method will return the default PHP timezone
+     * (as configured using date_default_timezone_set, or the date.timezone ini
+     * setting).
+     *
+     * Alternatively, if $failIfUncertain is set to true, it will throw an
+     * exception if we cannot accurately determine the timezone.
+     *
+     * @param string $tzid
+     * @param Sabre\VObject\Component $vcalendar
+     * @return DateTimeZone
+     */
+    static public function getTimeZone($tzid, Component $vcalendar = null, $failIfUncertain = false) {
+
+        // First we will just see if the tzid is a support timezone identifier.
+        //
+        // The only exception is if the timezone starts with (. This is to
+        // handle cases where certain microsoft products generate timezone
+        // identifiers that for instance look like:
+        //
+        // (GMT+01.00) Sarajevo/Warsaw/Zagreb
+        //
+        // Since PHP 5.5.10, the first bit will be used as the timezone and
+        // this method will return just GMT+01:00. This is wrong, because it
+        // doesn't take DST into account.
+        if ($tzid[0]!=='(') {
+
+            // PHP has a bug that logs PHP warnings even it shouldn't:
+            // https://bugs.php.net/bug.php?id=67881
+            //
+            // That's why we're checking if we'll be able to successfull instantiate
+            // \DateTimeZone() before doing so. Otherwise we could simply instantiate
+            // and catch the exception.
+            $tzIdentifiers = \DateTimeZone::listIdentifiers();
+
+            try {
+                if (
+                    (in_array($tzid, $tzIdentifiers)) ||
+                    (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) ||
+                    (in_array($tzid, self::getIdentifiersBC()))
+                ) {
+                    return new \DateTimeZone($tzid);
+                }
+            } catch(\Exception $e) {
+            }
+
+        }
+
+        self::loadTzMaps();
+
+        // Next, we check if the tzid is somewhere in our tzid map.
+        if (isset(self::$map[$tzid])) {
+            return new \DateTimeZone(self::$map[$tzid]);
+        }
+
+        // Maybe the author was hyper-lazy and just included an offset. We
+        // support it, but we aren't happy about it.
+        if (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) {
+
+            // Note that the path in the source will never be taken from PHP 5.5.10
+            // onwards. PHP 5.5.10 supports the "GMT+0100" style of format, so it
+            // already gets returned early in this function. Once we drop support
+            // for versions under PHP 5.5.10, this bit can be taken out of the
+            // source.
+            // @codeCoverageIgnoreStart
+            return new \DateTimeZone('Etc/GMT' . $matches[1] . ltrim(substr($matches[2],0,2),'0'));
+            // @codeCoverageIgnoreEnd
+        }
+
+        if ($vcalendar) {
+
+            // If that didn't work, we will scan VTIMEZONE objects
+            foreach($vcalendar->select('VTIMEZONE') as $vtimezone) {
+
+                if ((string)$vtimezone->TZID === $tzid) {
+
+                    // Some clients add 'X-LIC-LOCATION' with the olson name.
+                    if (isset($vtimezone->{'X-LIC-LOCATION'})) {
+
+                        $lic = (string)$vtimezone->{'X-LIC-LOCATION'};
+
+                        // Libical generators may specify strings like
+                        // "SystemV/EST5EDT". For those we must remove the
+                        // SystemV part.
+                        if (substr($lic,0,8)==='SystemV/') {
+                            $lic = substr($lic,8);
+                        }
+
+                        return self::getTimeZone($lic, null, $failIfUncertain);
+
+                    }
+                    // Microsoft may add a magic number, which we also have an
+                    // answer for.
+                    if (isset($vtimezone->{'X-MICROSOFT-CDO-TZID'})) {
+                        $cdoId = (int)$vtimezone->{'X-MICROSOFT-CDO-TZID'}->getValue();
+
+                        // 2 can mean both Europe/Lisbon and Europe/Sarajevo.
+                        if ($cdoId===2 && strpos((string)$vtimezone->TZID, 'Sarajevo')!==false) {
+                            return new \DateTimeZone('Europe/Sarajevo');
+                        }
+
+                        if (isset(self::$microsoftExchangeMap[$cdoId])) {
+                            return new \DateTimeZone(self::$microsoftExchangeMap[$cdoId]);
+                        }
+                    }
+
+                }
+
+            }
+
+        }
+
+        if ($failIfUncertain) {
+            throw new \InvalidArgumentException('We were unable to determine the correct PHP timezone for tzid: ' . $tzid);
+        }
+
+        // If we got all the way here, we default to UTC.
+        return new \DateTimeZone(date_default_timezone_get());
+
+    }
+
+    /**
+     * This method will load in all the tz mapping information, if it's not yet
+     * done.
+     */
+    static public function loadTzMaps() {
+
+        if (!is_null(self::$map)) return;
+
+        self::$map = array_merge(
+            include __DIR__ .  '/timezonedata/windowszones.php',
+            include __DIR__ .  '/timezonedata/lotuszones.php',
+            include __DIR__ .  '/timezonedata/exchangezones.php',
+            include __DIR__ .  '/timezonedata/php-workaround.php'
+        );
+
+    }
+
+    /**
+     * This method returns an array of timezone identifiers, that are supported
+     * by DateTimeZone(), but not returned by DateTimeZone::listIdentifiers()
+     *
+     * We're not using DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC) because:
+     * - It's not supported by some PHP versions as well as HHVM.
+     * - It also returns identifiers, that are invalid values for new DateTimeZone() on some PHP versions.
+     * (See timezonedata/php-bc.php and timezonedata php-workaround.php)
+     *
+     * @return array
+     */
+    static public function getIdentifiersBC() {
+        return include __DIR__ .  '/timezonedata/php-bc.php';
+    }
+
+}