aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/vobject/lib/TimeZoneUtil.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sabre/vobject/lib/TimeZoneUtil.php')
-rw-r--r--vendor/sabre/vobject/lib/TimeZoneUtil.php261
1 files changed, 134 insertions, 127 deletions
diff --git a/vendor/sabre/vobject/lib/TimeZoneUtil.php b/vendor/sabre/vobject/lib/TimeZoneUtil.php
index 2c407fee6..6422c0930 100644
--- a/vendor/sabre/vobject/lib/TimeZoneUtil.php
+++ b/vendor/sabre/vobject/lib/TimeZoneUtil.php
@@ -2,6 +2,16 @@
namespace Sabre\VObject;
+use DateTimeZone;
+use InvalidArgumentException;
+use Sabre\VObject\TimezoneGuesser\FindFromOffset;
+use Sabre\VObject\TimezoneGuesser\FindFromTimezoneIdentifier;
+use Sabre\VObject\TimezoneGuesser\FindFromTimezoneMap;
+use Sabre\VObject\TimezoneGuesser\GuessFromLicEntry;
+use Sabre\VObject\TimezoneGuesser\GuessFromMsTzId;
+use Sabre\VObject\TimezoneGuesser\TimezoneFinder;
+use Sabre\VObject\TimezoneGuesser\TimezoneGuesser;
+
/**
* Time zone name translation.
*
@@ -14,17 +24,136 @@ namespace Sabre\VObject;
*/
class TimeZoneUtil
{
+ /** @var self */
+ private static $instance = null;
+
+ /** @var TimezoneGuesser[] */
+ private $timezoneGuessers = [];
+
+ /** @var TimezoneFinder[] */
+ private $timezoneFinders = [];
+
+ private function __construct()
+ {
+ $this->addGuesser('lic', new GuessFromLicEntry());
+ $this->addGuesser('msTzId', new GuessFromMsTzId());
+ $this->addFinder('tzid', new FindFromTimezoneIdentifier());
+ $this->addFinder('tzmap', new FindFromTimezoneMap());
+ $this->addFinder('offset', new FindFromOffset());
+ }
+
+ private static function getInstance(): self
+ {
+ if (null === self::$instance) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ private function addGuesser(string $key, TimezoneGuesser $guesser): void
+ {
+ $this->timezoneGuessers[$key] = $guesser;
+ }
+
+ private function addFinder(string $key, TimezoneFinder $finder): void
+ {
+ $this->timezoneFinders[$key] = $finder;
+ }
+
+ /**
+ * 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.
+ */
+ private function findTimeZone(string $tzid, Component $vcalendar = null, bool $failIfUncertain = false): DateTimeZone
+ {
+ foreach ($this->timezoneFinders as $timezoneFinder) {
+ $timezone = $timezoneFinder->find($tzid, $failIfUncertain);
+ if (!$timezone instanceof DateTimeZone) {
+ continue;
+ }
+
+ return $timezone;
+ }
+
+ if ($vcalendar) {
+ // If that didn't work, we will scan VTIMEZONE objects
+ foreach ($vcalendar->select('VTIMEZONE') as $vtimezone) {
+ if ((string) $vtimezone->TZID === $tzid) {
+ foreach ($this->timezoneGuessers as $timezoneGuesser) {
+ $timezone = $timezoneGuesser->guess($vtimezone, $failIfUncertain);
+ if (!$timezone instanceof DateTimeZone) {
+ continue;
+ }
+
+ return $timezone;
+ }
+ }
+ }
+ }
+
+ 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 whatever has been set as the PHP default timezone.
+ return new DateTimeZone(date_default_timezone_get());
+ }
+
+ public static function addTimezoneGuesser(string $key, TimezoneGuesser $guesser): void
+ {
+ self::getInstance()->addGuesser($key, $guesser);
+ }
+
+ public static function addTimezoneFinder(string $key, TimezoneFinder $finder): void
+ {
+ self::getInstance()->addFinder($key, $finder);
+ }
+
+ /**
+ * @param string $tzid
+ * @param false $failIfUncertain
+ *
+ * @return DateTimeZone
+ */
+ public static function getTimeZone($tzid, Component $vcalendar = null, $failIfUncertain = false)
+ {
+ return self::getInstance()->findTimeZone($tzid, $vcalendar, $failIfUncertain);
+ }
+
+ public static function clean(): void
+ {
+ self::$instance = null;
+ }
+
+ // Keeping things for backwards compatibility
+ /**
+ * @var array|null
+ *
+ * @deprecated
+ */
public static $map = null;
/**
* List of microsoft exchange timezone ids.
*
* Source: http://msdn.microsoft.com/en-us/library/aa563018(loband).aspx
+ *
+ * @deprecated
*/
public static $microsoftExchangeMap = [
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.
@@ -104,134 +233,10 @@ class TimeZoneUtil
];
/**
- * 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
- */
- public static 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 successfully 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]);
- }
-
- // 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.
- if (preg_match('/^\((UTC|GMT)(\+|\-)[\d]{2}\:[\d]{2}\) (.*)/', $tzid, $matches)) {
- $tzidAlternate = $matches[3];
- if (isset(self::$map[$tzidAlternate])) {
- return new \DateTimeZone(self::$map[$tzidAlternate]);
- }
- }
-
- // 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 ('SystemV/' === substr($lic, 0, 8)) {
- $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 (2 === $cdoId && false !== strpos((string) $vtimezone->TZID, 'Sarajevo')) {
- 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.
+ *
+ * @deprecated
*/
public static function loadTzMaps()
{
@@ -257,6 +262,8 @@ class TimeZoneUtil
* (See timezonedata/php-bc.php and timezonedata php-workaround.php)
*
* @return array
+ *
+ * @deprecated
*/
public static function getIdentifiersBC()
{