- <?php
- /**
- * Abstract class for helping with timezones; specifically converting strings to DateTime objects.
- *
- * @copyright 2014 Perforce Software. All rights reserved.
- * @license Please see LICENSE.txt in top-level folder of this distribution.
- * @version <release>/<patch>
- */
-
- namespace P4\Time;
-
- class Time
- {
- // translation map derived from http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml
- // using the script collateral/scripts/timezonemap.php
- // we filter for php supported zones and prefer territory 001 where possible.
- protected static $tzWindowsToPhp = array(
- 'afghanistan standard time' => 'Asia/Kabul',
- 'alaskan standard time' => 'America/Anchorage',
- 'arabian standard time' => 'Asia/Dubai',
- 'arabic standard time' => 'Asia/Baghdad',
- 'arab standard time' => 'Asia/Riyadh',
- 'atlantic standard time' => 'America/Halifax',
- 'aus central standard time' => 'Australia/Darwin',
- 'aus eastern standard time' => 'Australia/Sydney',
- 'azerbaijan standard time' => 'Asia/Baku',
- 'azores standard time' => 'Atlantic/Azores',
- 'bahia standard time' => 'America/Bahia',
- 'bangladesh standard time' => 'Asia/Dhaka',
- 'canada central standard time' => 'America/Regina',
- 'cape verde standard time' => 'Atlantic/Cape_Verde',
- 'caucasus standard time' => 'Asia/Yerevan',
- 'cen. australia standard time' => 'Australia/Adelaide',
- 'central america standard time' => 'America/Guatemala',
- 'central asia standard time' => 'Asia/Almaty',
- 'central brazilian standard time' => 'America/Cuiaba',
- 'central european standard time' => 'Europe/Warsaw',
- 'central europe standard time' => 'Europe/Budapest',
- 'central pacific standard time' => 'Pacific/Guadalcanal',
- 'central standard time' => 'America/Chicago',
- 'central standard time (mexico)' => 'America/Mexico_City',
- 'china standard time' => 'Asia/Shanghai',
- 'e. africa standard time' => 'Africa/Nairobi',
- 'e. australia standard time' => 'Australia/Brisbane',
- 'e. south america standard time' => 'America/Sao_Paulo',
- 'eastern standard time' => 'America/New_York',
- 'egypt standard time' => 'Africa/Cairo',
- 'ekaterinburg standard time' => 'Asia/Yekaterinburg',
- 'fiji standard time' => 'Pacific/Fiji',
- 'fle standard time' => 'Europe/Kiev',
- 'georgian standard time' => 'Asia/Tbilisi',
- 'gmt standard time' => 'Europe/London',
- 'greenland standard time' => 'America/Godthab',
- 'greenwich standard time' => 'Atlantic/Reykjavik',
- 'gtb standard time' => 'Europe/Bucharest',
- 'hawaiian standard time' => 'Pacific/Honolulu',
- 'iran standard time' => 'Asia/Tehran',
- 'israel standard time' => 'Asia/Jerusalem',
- 'jordan standard time' => 'Asia/Amman',
- 'kaliningrad standard time' => 'Europe/Kaliningrad',
- 'korea standard time' => 'Asia/Seoul',
- 'libya standard time' => 'Africa/Tripoli',
- 'magadan standard time' => 'Asia/Magadan',
- 'mauritius standard time' => 'Indian/Mauritius',
- 'middle east standard time' => 'Asia/Beirut',
- 'montevideo standard time' => 'America/Montevideo',
- 'morocco standard time' => 'Africa/Casablanca',
- 'mountain standard time' => 'America/Denver',
- 'mountain standard time (mexico)' => 'America/Chihuahua',
- 'myanmar standard time' => 'Asia/Rangoon',
- 'n. central asia standard time' => 'Asia/Novosibirsk',
- 'namibia standard time' => 'Africa/Windhoek',
- 'newfoundland standard time' => 'America/St_Johns',
- 'new zealand standard time' => 'Pacific/Auckland',
- 'north asia east standard time' => 'Asia/Irkutsk',
- 'north asia standard time' => 'Asia/Krasnoyarsk',
- 'pacific sa standard time' => 'America/Santiago',
- 'pacific standard time' => 'America/Los_Angeles',
- 'pacific standard time (mexico)' => 'America/Santa_Isabel',
- 'pakistan standard time' => 'Asia/Karachi',
- 'paraguay standard time' => 'America/Asuncion',
- 'romance standard time' => 'Europe/Paris',
- 'russian standard time' => 'Europe/Moscow',
- 'sa eastern standard time' => 'America/Cayenne',
- 'samoa standard time' => 'Pacific/Apia',
- 'sa pacific standard time' => 'America/Bogota',
- 'sa western standard time' => 'America/La_Paz',
- 'se asia standard time' => 'Asia/Bangkok',
- 'singapore standard time' => 'Asia/Singapore',
- 'south africa standard time' => 'Africa/Johannesburg',
- 'sri lanka standard time' => 'Asia/Colombo',
- 'syria standard time' => 'Asia/Damascus',
- 'taipei standard time' => 'Asia/Taipei',
- 'tasmania standard time' => 'Australia/Hobart',
- 'tokyo standard time' => 'Asia/Tokyo',
- 'tonga standard time' => 'Pacific/Tongatapu',
- 'turkey standard time' => 'Europe/Istanbul',
- 'ulaanbaatar standard time' => 'Asia/Ulaanbaatar',
- 'us mountain standard time' => 'America/Phoenix',
- 'utc+12' => 'Pacific/Tarawa',
- 'utc-02' => 'America/Noronha',
- 'utc-11' => 'Pacific/Pago_Pago',
- 'venezuela standard time' => 'America/Caracas',
- 'vladivostok standard time' => 'Asia/Vladivostok',
- 'w. australia standard time' => 'Australia/Perth',
- 'w. central africa standard time' => 'Africa/Lagos',
- 'w. europe standard time' => 'Europe/Berlin',
- 'west asia standard time' => 'Asia/Tashkent',
- 'west pacific standard time' => 'Pacific/Port_Moresby',
- 'yakutsk standard time' => 'Asia/Yakutsk',
- );
-
- /**
- * This method attempts to turn the passed timezone name/id into a DateTimeZone object.
- * The passed zone can be a windows timezone name, timezone abbreviation or
- * supported long-form PHP timezone.
- *
- * If we are not able to get the passed zone into a value DateTimeZone will recognize,
- * an exception will be thrown.
- *
- * @param string $name the name or abbreviated timezone to turn into a date time zone
- * @param string|int|null $offset optional - the offset in minutes e.g. "-0800" or -800
- * @return \DateTimeZone an object representing the specified timezone
- * @throws \Exception if the passed timezone isn't parsable
- */
- public static function toDateTimeZone($name, $offset = null)
- {
- // if we got a windows timezone name, map it over to the PHP compatible value
- if (isset(static::$tzWindowsToPhp[strtolower($name)])) {
- $name = static::$tzWindowsToPhp[strtolower($name)];
- }
-
- // the 'daylight' version of windows time still map to the same olson value; check that too
- if (isset(static::$tzWindowsToPhp[str_replace('daylight', 'standard', strtolower($name))])) {
- $name = static::$tzWindowsToPhp[str_replace('daylight', 'standard', strtolower($name))];
- }
-
- // if we have a known abbreviation, resolve it into a full timezone name
- if (array_key_exists(strtolower($name), array_change_key_case(timezone_abbreviations_list(), CASE_LOWER))) {
- // if we have an offset it is expected to be in the format -430 or "+0800"
- // convert this value from hours and minutes to seconds
- $gmtOffset = null;
- if ($offset) {
- $gmtOffset = ($offset % 100) * 60;
- $gmtOffset += ((int) ($offset / 100)) * 60 * 60;
- }
-
- $name = timezone_name_from_abbr($name, $gmtOffset);
- }
-
- return new \DateTimeZone($name);
- }
- }