Last active
November 22, 2018 09:42
-
-
Save Rican7/72a31d8a47472c68d085 to your computer and use it in GitHub Desktop.
Parsing Unicode CLDR Windows Timezones in PHP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// The location of the Unicode CLDR "windowsZones" mappings here | |
const XML_URL = 'http://unicode.org/cldr/data/common/supplemental/windowsZones.xml'; | |
const XML_ZONE_MAP_XPATH = '/supplementalData/windowsZones/mapTimezones/mapZone'; | |
const ZONE_TERRITORY_ATTRIBUTE = 'territory'; | |
const ZONE_IANA_NAME_ATTRIBUTE = 'type'; | |
const ZONE_WINDOWS_NAME_ATTRIBUTE = 'other'; | |
const MAP_IANA_MULTIPLE_DELIMITER = ' '; | |
// Load the remote XML document | |
$xml = new SimpleXmlElement(XML_URL, 0, true); | |
// Build the Windows->IANA Timezone map | |
$windows_iana_timezone_map = array_reduce( | |
$xml->xpath(XML_ZONE_MAP_XPATH), | |
function (array $map, SimpleXmlElement $element) { | |
$windows_name = (string) $element[ZONE_WINDOWS_NAME_ATTRIBUTE]; | |
$territory = (string) $element[ZONE_TERRITORY_ATTRIBUTE]; | |
$iana_names = explode(MAP_IANA_MULTIPLE_DELIMITER, (string) $element[ZONE_IANA_NAME_ATTRIBUTE]); | |
if (!isset($map[$windows_name])) { | |
$map[$windows_name] = []; | |
} | |
if (!isset($map[$windows_name][$territory])) { | |
$map[$windows_name][$territory] = []; | |
} | |
$map[$windows_name][$territory] = array_merge( | |
$map[$windows_name][$territory], | |
$iana_names | |
); | |
return $map; | |
}, | |
[] | |
); | |
// Build the IANA->Windows Timezone map for faster inverted lookups | |
$iana_windows_timezone_map = []; | |
array_walk( | |
$windows_iana_timezone_map, | |
function (array $territories, $windows_name) use (&$iana_windows_timezone_map) { | |
$iana_names = array_reduce( | |
$territories, | |
function ($all, $row) { | |
return array_merge($all, $row); | |
}, | |
[] | |
); | |
foreach ($iana_names as $iana_name) { | |
$iana_windows_timezone_map[$iana_name] = $windows_name; | |
} | |
} | |
); | |
// OPTIONAL: Sort the keys of the maps naturally for easier viewing and generated file "diffing" | |
ksort($iana_windows_timezone_map, SORT_NATURAL); | |
ksort($windows_iana_timezone_map, SORT_NATURAL); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment