FindFromTimezoneIdentifier.php 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. <?php
  2. declare(strict_types=1);
  3. namespace Sabre\VObject\TimezoneGuesser;
  4. use DateTimeZone;
  5. use Exception;
  6. /**
  7. * Some clients add 'X-LIC-LOCATION' with the olson name.
  8. */
  9. class FindFromTimezoneIdentifier implements TimezoneFinder
  10. {
  11. public function find(string $tzid, bool $failIfUncertain = false): ?DateTimeZone
  12. {
  13. // First we will just see if the tzid is a support timezone identifier.
  14. //
  15. // The only exception is if the timezone starts with (. This is to
  16. // handle cases where certain microsoft products generate timezone
  17. // identifiers that for instance look like:
  18. //
  19. // (GMT+01.00) Sarajevo/Warsaw/Zagreb
  20. //
  21. // Since PHP 5.5.10, the first bit will be used as the timezone and
  22. // this method will return just GMT+01:00. This is wrong, because it
  23. // doesn't take DST into account
  24. if (!isset($tzid[0])) {
  25. return null;
  26. }
  27. if ('(' === $tzid[0]) {
  28. return null;
  29. }
  30. // PHP has a bug that logs PHP warnings even it shouldn't:
  31. // https://bugs.php.net/bug.php?id=67881
  32. //
  33. // That's why we're checking if we'll be able to successfully instantiate
  34. // \DateTimeZone() before doing so. Otherwise we could simply instantiate
  35. // and catch the exception.
  36. $tzIdentifiers = DateTimeZone::listIdentifiers();
  37. try {
  38. if (
  39. (in_array($tzid, $tzIdentifiers)) ||
  40. (preg_match('/^GMT(\+|-)([0-9]{4})$/', $tzid, $matches)) ||
  41. (in_array($tzid, $this->getIdentifiersBC()))
  42. ) {
  43. return new DateTimeZone($tzid);
  44. }
  45. } catch (Exception $e) {
  46. }
  47. return null;
  48. }
  49. /**
  50. * This method returns an array of timezone identifiers, that are supported
  51. * by DateTimeZone(), but not returned by DateTimeZone::listIdentifiers().
  52. *
  53. * We're not using DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC) because:
  54. * - It's not supported by some PHP versions as well as HHVM.
  55. * - It also returns identifiers, that are invalid values for new DateTimeZone() on some PHP versions.
  56. * (See timezonedata/php-bc.php and timezonedata php-workaround.php)
  57. *
  58. * @return array
  59. */
  60. private function getIdentifiersBC()
  61. {
  62. return include __DIR__.'/../timezonedata/php-bc.php';
  63. }
  64. }