Я постараюсь объяснить, в чем здесь проблема.
Согласно списку поддерживаемых часовых поясов из руководства по PHP, я вижу все действительные идентификаторы TZ в PHP.
Мой первый вопрос - как получить этот список из кода, но это не то, что мне действительно нужно.
Моя конечная цель - написать функцию isValidTimezoneId()
, которая возвращает TRUE , если часовой пояс действителен, в противном случае он должен возвращать FALSE .
function isValidTimezoneId($timezoneId) {
# ...function body...
return ?; # TRUE or FALSE
}
Итак, когда я передаю идентификатор TZ, используя $timezoneId
(строку) в функции, мне нужен логический результат.
Ну что у меня пока ...
1) Решение с использованием оператора @
Первое решение, которое у меня есть, выглядит примерно так:
function isValidTimezoneId($timezoneId) {
$savedZone = date_default_timezone_get(); # save current zone
$res = $savedZone == $timezoneId; # it's TRUE if param matches current zone
if (!$res) { # 0r...
@date_default_timezone_set($timezoneId); # try to set new timezone
$res = date_default_timezone_get() == $timezoneId; # it's true if new timezone set matches param string.
}
date_default_timezone_set($savedZone); # restore back old timezone
return $res; # set result
}
Это прекрасно работает, но я хочу другое решение (чтобы не пытаться установить неправильный часовой пояс)
Затем я пытался получить список допустимых идентификаторов часовых поясов и сравнить его с параметром, используя функцию in_array () . Поэтому я попытался использовать timezone_identifiers_list () , но это было не так хорошо, потому что в массиве, возвращаемом этой функцией, отсутствовало много часовых поясов (псевдоним DateTimeZone :: listIdentifiers () ). На первый взгляд это было именно то, что я искал.
function isValidTimezoneId($timezoneId) {
$zoneList = timezone_identifiers_list(); # list of (all) valid timezones
return in_array($timezoneId, $zoneList); # set result
}
Этот код выглядит красиво и просто, но я обнаружил, что массив $zoneList
содержит ~ 400 элементов. По моим расчетам он должен вернуть 550+ элементов. Более 150 элементов отсутствуют ... Так что этого недостаточно для решения моей проблемы.
Это последний шаг на пути к поиску идеального решения. Используя массив, возвращенный этим методом, я могу извлечь все идентификаторы часовых поясов, поддерживаемые PHP.
function createTZlist() {
$tza = DateTimeZone::listAbbreviations();
$tzlist = array();
foreach ($tza as $zone)
foreach ($zone as $item)
if (is_string($item['timezone_id']) && $item['timezone_id'] != '')
$tzlist[] = $item['timezone_id'];
$tzlist = array_unique($tzlist);
asort($tzlist);
return array_values($tzlist);
}
Эта функция возвращает 563 элемента (в Example #2
у меня всего 407 ).
Я пытался найти различия между этими двумя массивами:
$a1 = timezone_identifiers_list();
$a2 = createTZlist();
print_r(array_values(array_diff($a2, $a1)));
Результат:
Array
(
[0] => Africa/Asmera
[1] => Africa/Timbuktu
[2] => America/Argentina/ComodRivadavia
[3] => America/Atka
[4] => America/Buenos_Aires
[5] => America/Catamarca
[6] => America/Coral_Harbour
[7] => America/Cordoba
[8] => America/Ensenada
[9] => America/Fort_Wayne
[10] => America/Indianapolis
[11] => America/Jujuy
[12] => America/Knox_IN
[13] => America/Louisville
[14] => America/Mendoza
[15] => America/Porto_Acre
[16] => America/Rosario
[17] => America/Virgin
[18] => Asia/Ashkhabad
[19] => Asia/Calcutta
[20] => Asia/Chungking
[21] => Asia/Dacca
[22] => Asia/Istanbul
[23] => Asia/Katmandu
[24] => Asia/Macao
[25] => Asia/Saigon
[26] => Asia/Tel_Aviv
[27] => Asia/Thimbu
[28] => Asia/Ujung_Pandang
[29] => Asia/Ulan_Bator
[30] => Atlantic/Faeroe
[31] => Atlantic/Jan_Mayen
[32] => Australia/ACT
[33] => Australia/Canberra
[34] => Australia/LHI
[35] => Australia/NSW
[36] => Australia/North
[37] => Australia/Queensland
[38] => Australia/South
[39] => Australia/Tasmania
[40] => Australia/Victoria
[41] => Australia/West
[42] => Australia/Yancowinna
[43] => Brazil/Acre
[44] => Brazil/DeNoronha
[45] => Brazil/East
[46] => Brazil/West
[47] => CET
[48] => CST6CDT
[49] => Canada/Atlantic
[50] => Canada/Central
[51] => Canada/East-Saskatchewan
[52] => Canada/Eastern
[53] => Canada/Mountain
[54] => Canada/Newfoundland
[55] => Canada/Pacific
[56] => Canada/Saskatchewan
[57] => Canada/Yukon
[58] => Chile/Continental
[59] => Chile/EasterIsland
[60] => Cuba
[61] => EET
[62] => EST
[63] => EST5EDT
[64] => Egypt
[65] => Eire
[66] => Etc/GMT
[67] => Etc/GMT+0
[68] => Etc/GMT+1
[69] => Etc/GMT+10
[70] => Etc/GMT+11
[71] => Etc/GMT+12
[72] => Etc/GMT+2
[73] => Etc/GMT+3
[74] => Etc/GMT+4
[75] => Etc/GMT+5
[76] => Etc/GMT+6
[77] => Etc/GMT+7
[78] => Etc/GMT+8
[79] => Etc/GMT+9
[80] => Etc/GMT-0
[81] => Etc/GMT-1
[82] => Etc/GMT-10
[83] => Etc/GMT-11
[84] => Etc/GMT-12
[85] => Etc/GMT-13
[86] => Etc/GMT-14
[87] => Etc/GMT-2
[88] => Etc/GMT-3
[89] => Etc/GMT-4
[90] => Etc/GMT-5
[91] => Etc/GMT-6
[92] => Etc/GMT-7
[93] => Etc/GMT-8
[94] => Etc/GMT-9
[95] => Etc/GMT0
[96] => Etc/Greenwich
[97] => Etc/UCT
[98] => Etc/UTC
[99] => Etc/Universal
[100] => Etc/Zulu
[101] => Europe/Belfast
[102] => Europe/Nicosia
[103] => Europe/Tiraspol
[104] => Factory
[105] => GB
[106] => GB-Eire
[107] => GMT
[108] => GMT+0
[109] => GMT-0
[110] => GMT0
[111] => Greenwich
[112] => HST
[113] => Hongkong
[114] => Iceland
[115] => Iran
[116] => Israel
[117] => Jamaica
[118] => Japan
[119] => Kwajalein
[120] => Libya
[121] => MET
[122] => MST
[123] => MST7MDT
[124] => Mexico/BajaNorte
[125] => Mexico/BajaSur
[126] => Mexico/General
[127] => NZ
[128] => NZ-CHAT
[129] => Navajo
[130] => PRC
[131] => PST8PDT
[132] => Pacific/Ponape
[133] => Pacific/Samoa
[134] => Pacific/Truk
[135] => Pacific/Yap
[136] => Poland
[137] => Portugal
[138] => ROC
[139] => ROK
[140] => Singapore
[141] => Turkey
[142] => UCT
[143] => US/Alaska
[144] => US/Aleutian
[145] => US/Arizona
[146] => US/Central
[147] => US/East-Indiana
[148] => US/Eastern
[149] => US/Hawaii
[150] => US/Indiana-Starke
[151] => US/Michigan
[152] => US/Mountain
[153] => US/Pacific
[154] => US/Pacific-New
[155] => US/Samoa
[156] => Universal
[157] => W-SU
[158] => WET
[159] => Zulu
)
Этот список содержит все действительные идентификаторы TZ, которым Example #2
не удалось сопоставить.
Есть еще четыре идентификатора TZ (часть $a1
):
print_r(array_values(array_diff($a1, $a2)));
выход
Array
(
[0] => America/Bahia_Banderas
[1] => Antarctica/Macquarie
[2] => Pacific/Chuuk
[3] => Pacific/Pohnpei
)
Так что теперь у меня есть почти идеальное решение ...
function isValidTimezoneId($timezoneId) {
$zoneList = createTZlist(); # list of all valid timezones (last 4 are not included)
return in_array($timezoneId, $zoneList); # set result
}
Это мое решение, и я могу его использовать. Конечно, я использую эту функцию как часть класса, поэтому мне не нужно генерировать $zoneList
при каждом вызове методов.
Что мне здесь действительно нужно?
Мне интересно, есть ли какое-нибудь более простое (более быстрое) решение для получения списка всех допустимых идентификаторов часовых поясов в виде массива (я хочу избежать извлечения этого списка из DateTimeZone::listAbbreviations()
, если это возможно)? Или, если вы знаете, как проверить , является ли параметр часового пояса действительным , сообщите мне (повторяю, оператор @
не может быть частью решения).
Постскриптум Если вам нужно больше деталей и примеров, дайте мне знать. Я полагаю, что нет.
Я использую PHP 5.3.5
(думаю, это не важно).
Обновление
Любая часть кода, которая генерирует исключение для недопустимой строки часового пояса (скрыта с помощью @
или перехвачена с помощью блока try..catch
), не является решением, которое я ищу.
Еще одно обновление
Я назначил маленькую награду за этот вопрос!
Теперь я ищу самый простой способ извлечения списка всех идентификаторов часовых поясов в массиве PHP.