aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/vobject/lib/TimezoneGuesser/FindFromTimezoneMap.php
blob: b52ba6a19c58c0e40a9493e23ddb6b259c8c8e42 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php

declare(strict_types=1);

namespace Sabre\VObject\TimezoneGuesser;

use DateTimeZone;

/**
 * Some clients add 'X-LIC-LOCATION' with the olson name.
 */
class FindFromTimezoneMap implements TimezoneFinder
{
    private $map = [];

    private $patterns = [
        '/^\((UTC|GMT)(\+|\-)[\d]{2}\:[\d]{2}\) (.*)/',
        '/^\((UTC|GMT)(\+|\-)[\d]{2}\.[\d]{2}\) (.*)/',
    ];

    public function find(string $tzid, bool $failIfUncertain = false): ?DateTimeZone
    {
        // Next, we check if the tzid is somewhere in our tzid map.
        if ($this->hasTzInMap($tzid)) {
            return new DateTimeZone($this->getTzFromMap($tzid));
        }

        // Some Microsoft products prefix the offset first, so let's strip that off
        // and see if it is our tzid map.  We don't want to check for this first just
        // in case there are overrides in our tzid map.
        foreach ($this->patterns as $pattern) {
            if (!preg_match($pattern, $tzid, $matches)) {
                continue;
            }
            $tzidAlternate = $matches[3];
            if ($this->hasTzInMap($tzidAlternate)) {
                return new DateTimeZone($this->getTzFromMap($tzidAlternate));
            }
        }

        return null;
    }

    /**
     * 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
     */
    private function getTzMaps()
    {
        if ([] === $this->map) {
            $this->map = array_merge(
                include __DIR__.'/../timezonedata/windowszones.php',
                include __DIR__.'/../timezonedata/lotuszones.php',
                include __DIR__.'/../timezonedata/exchangezones.php',
                include __DIR__.'/../timezonedata/php-workaround.php'
            );
        }

        return $this->map;
    }

    private function getTzFromMap(string $tzid): string
    {
        return $this->getTzMaps()[$tzid];
    }

    private function hasTzInMap(string $tzid): bool
    {
        return isset($this->getTzMaps()[$tzid]);
    }
}