settimezone default_time_zone php

php - default_time_zone - La mejor manera de poblar un cuadro<SELECT> con TimeZones



set timezone php (11)

Necesito mostrar un selector de zona horaria como control de usuario, que siempre parece más fácil de lo que realmente es. Internamente, almaceno todo con un identificador DateTimeZone, ya que parece ser la forma más inteligente de tener el nivel de precisión que necesito, ya que este proyecto tiende puentes en el mundo real ya que está vinculado a los medios terrestres.

Lo que no quiero hacer es presentar un cuadro de selección con más de 300 zonas horarias, ni tampoco quiero crear desfases de zona horaria falsos con algo como ''UTC-8'' (que no solo pierde la información DST, sino las fechas reales que DST cae).

Al final, necesitaré una selección con opciones que contengan los identificadores TZD adecuados, algo como esto (los # entre corchetes no son necesarios, solo para una posible ilustración del usuario final):

<select> <option value="America/Los_Angeles">Los Angeles [UTC-7 | DST]</option> ... </select>

¿Alguien tiene alguna sugerencia para construir esta lista? Todas las soluciones que he buscado en Google han sido problemáticas de una forma u otra.

He agregado una recompensa en caso de que pueda atraer a alguien para compartir una respuesta más agradable con nosotros. :)


Al final del día, no creo que haya una buena solución para precapturar la lista demasiado grande de zonas horarias ... Y los problemas involucrados me han hecho decidir comenzar con una clase de un tamaño decente. Lo estoy publicando aquí ya que hubo algunas personas que estaban interesadas en él. Espero que mi solución también ayude a alguien más.

Que hace:

  • Te permite crear una lista de zonas horarias de toda la lista dentro de PHP

  • Le permite crear una buena lista a partir de sus propias definiciones precocinadas, calculando los desplazamientos UTC actuales.

  • Le permite crear una lista por país.

  • De-duplica zonas horarias con la misma abreviatura. Tenga en cuenta que no he investigado mucho para ver si hay duplicados en la lista de los que no debería deshacerme. Es lo suficientemente inteligente como para saber que a pesar de que dos zonas horarias pueden informar la misma abreviatura (por ejemplo, MST para Arizona), indicará si la zona horaria admite o no el horario de verano en cualquier momento del año.

  • Genera HTML bastante configurable (sin ir a la ruta de la plantilla) o JSON para Ajax o JavaScript en línea.

  • Calcula el desplazamiento actual de la zona horaria para cualquier zona horaria dada. Tenga en cuenta que esto no es estático ... cambiará a lo largo del año.

  • Proporciona grandes cantidades de azúcar para el uso en el mundo real.

Lo que no hace:

  • Separar países o continentes a través de un OptGroup. Como ya estoy haciendo una ordenación por desplazamiento UTC, parecía que iba a causar más confusión de la que aliviaría.

Cosas que podría agregar un día:

  • Construya el HTML de la plantilla en lugar de hacerlo en línea de esta manera.

  • Selectores adicionales, como tomar una serie de países en lugar de uno solo.

  • Agrupando, pero como mencioné anteriormente, no estoy haciendo eso.

  • El código está bastante mojado. Hay algunas discrepancias de estilo de codificación menores.

  • Posibilidad de especificar una lista ''preferida'' de nombres amistosos. Por ejemplo, aunque ''Dawson'' es un candidato perfectamente viable para aparecer como ''la'' ciudad para PDT, ya que es parte del grupo principal de PST y observa el horario de verano ... una ciudad de poco más de 1000 residentes no debería vencer a Los Ángeles, San Francisco, Seattle o Vancouver simplemente porque aparece primero léxicamente.

  • Salida sin procesar, de modo que nadie esté vinculado a los métodos simples ''para Seleccionar'' y ''a Json''.

En general, debería adaptarse a mis necesidades tal como están. Maneja adecuadamente todas las zonas horarias con las que estoy familiarizado, y todas las que necesito para mi proyecto actual. Desafortunadamente, mi ámbito de conocimiento se centra principalmente en los EE. UU. Y Europa occidental.

¿Es perfecto? Probablemente no. Feliz de escuchar sobre cualquier problema / error / mejora que pueda tener este código, ya que es probable que termine en mi biblioteca permanente. Si alguien piensa que soy alto ... házmelo saber también. Ese era el objetivo de esta pregunta era encontrar la mejor manera de representar un selector de zona horaria con precisión que, de hecho, sea algo útil para los usuarios finales.

TimezoneList.php:

<?php class TimezoneList { public $timezones = array(); private $_initialized = false; private $_dt_now; private $_utc; function __construct($grouped = false) { $this->_utc = new DateTimeZone(''UTC''); $this->_dt_now = new DateTime(''now'', $this->_utc); } // Public Static Alternate Constructors public static function byCountry($countryKey) { $retVal = new TimezoneList(); $retVal->_setList($countryKey); return $retVal; } public static function fromTimezones(Array $tzArr) { $retVal = new TimezoneList(); foreach ($tzArr as $tzItem) { $retVal->timezones[] = $tzItem; } $retVal->_initialized = true; return $retVal; } public static function fromIdentifierList($timezoneList, $friendlyNames = NULL) { $retVal = new TimezoneList(); if ($friendlyNames) { if (count($timezoneList) != count($friendlyNames)) throw new Exception(''Array count mismatch in TimezoneBuilder::fromList''); } // I''d normally use a foreach pattern, but since friendlyNames is optional, this seemed the way to go. for ($ii = 0; $ii < count($timezoneList); $ii++) { $pTimezoneEx = new TimezoneExtended($timezoneList[$ii]); if ($friendlyNames) { $pTimezoneEx->friendlyName = $friendlyNames[$ii]; } $retVal->timezones[] = $pTimezoneEx; } $retVal->_initialized = true; return $retVal; } // Private Statics // Private utility function [ Thanks to Zubair1 ] private static function _formatOffset($offset) { $hours = $offset / 3600; $remainder = $offset % 3600; $sign = $hours > 0 ? ''+'' : ''-''; $hour = (int)abs($hours); $minutes = (int)abs($remainder / 60); $sign = (($hour == 0) && ($minutes == 0)) ? '' '' : $sign; return $sign.str_pad($hour, 2, ''0'', STR_PAD_LEFT).'':''.str_pad($minutes,2, ''0''); } // Publics public function getUniqueTimezoneList($countryKey = null) { $this->_initialize(); $outArr = array(); $usedTzs = array(); foreach ($this->timezones as $timezoneEx) { if (!(in_array($timezoneEx->currentKey, $usedTzs))) { $usedTzs[] = $timezoneEx->currentKey; $outArr[] = $timezoneEx; } } usort($outArr,array(''self'',''_orderByOffset'')); return self::fromTimezones($outArr); } // In final code, I''ll use a PHP include with output buffering as a template. public function toSelect($displayOffset = true, $displayCurrent = true, $selected = array(), Array $options = array()) { $pOpts = array(); $pItems = array(); foreach ($options as $key=>$option) { $pOpts[] = '' ''.$key.''="''.$option.''"''; } if (!is_array($selected)) $selected = array($selected); $outVal = ''<select''.implode('''', $pOpts).''>''."/n"; foreach ($this->timezones as $timezoneEx) { $offset = ''''; $selectionAttr = ''''; if (in_array($timezoneEx->tzkey, $selected)) { $selectionAttr = '' selected="selected"''; } if ($displayOffset) { $offset = '' [''.$timezoneEx->currentAbbr.'' ''.self::_formatOffset($timezoneEx->currentOffset); if ($displayCurrent && (!($timezoneEx->observesDst))) $offset .= '' ( Does not observe DST ) ''; $offset .= '']''; } $pItems[] = "/t".''<option value="''.$timezoneEx->tzkey.''"''.$selectionAttr.''>''.$timezoneEx->friendlyName.$offset.''</option>''; } $outVal .= implode("/n", $pItems)."/n".''</select>''; return $outVal; } public function toJson() { $outArr = array(); foreach ($this->timezones as $timezoneEx) { $outArr[] = $timezoneEx->toShallowArray(); } return json_encode($outArr); } // Privates private function _initialize() { if ($this->_initialized) return; $this->_setList(); } private function _orderByOffset($a, $b) { if( $a->currentOffset == $b->currentOffset ){ return 0 ; } return ($a->currentOffset < $b->currentOffset) ? -1 : 1; } private function _setList($countryKey = NULL) { $this->timezones = array(); $listType = ($countryKey) ? DateTimeZone::PER_COUNTRY : DateTimeZone::ALL; $tzIds = DateTimeZone::listIdentifiers($listType, $countryKey); foreach ($tzIds as $tzIdentifier) { $this->timezones[] = new TimezoneExtended($tzIdentifier); } $this->_initialized = true; } } class TimezoneExtended { const START_YEAR = ''January 1st''; const MID_YEAR = ''July 1st''; private static $_dt_startYear = NULL; // Static so that we don''t have to rebuild it each time we go through. private static $_dt_midYear = NULL; private static $_dtz_utc = NULL; private static $_dt_now = NULL; private $_baseObj; public $tzkey; public $friendlyName; public $currentKey; // Current Key contains the friendly Timezone Key + whether this timezone observes DST. // This is unique across the US & Canada. Unsure if it will be unique across other Timezones. public $currentAbbr; public $currentOffset; public $currentlyDst; public $observesDst = false; // Defaults to off function __construct($tzKey) { if (empty(self::$_dtz_utc)) self::$_dtz_utc = new DateTimeZone(''UTC''); if (empty(self::$_dtz_now)) self::$_dt_now = new DateTime(''now'', self::$_dtz_utc); if (empty(self::$_dt_startYear)) self::$_dt_startYear = new DateTime(self::START_YEAR, self::$_dtz_utc); if (empty(self::$_dt_midYear)) self::$_dt_midYear = new DateTime(self::MID_YEAR, self::$_dtz_utc); $this->tzkey = $tzKey; $this->_baseObj = new DateTimeZone($tzKey); if ($this->_baseObj == NULL) throw new Exception(''Invalid Timezone Key''); foreach ($this->_baseObj->getTransitions(self::$_dt_startYear->getTimestamp()) as $transition) { if ($transition[''isdst'']) $this->observesDst = true; } foreach ($this->_baseObj->getTransitions(self::$_dt_midYear->getTimestamp()) as $transition) { if ($transition[''isdst'']) $this->observesDst = true; } $this->friendlyName =str_replace(''_'','' '',array_pop(explode(''/'',$tzKey))); $pTransition = $this->_baseObj->getTransitions(self::$_dt_now->getTimestamp()); $this->currentAbbr = $pTransition[0][''abbr'']; // With a Timestamp, we should only get one transition. $this->currentlyDst = $pTransition[0][''isdst'']; $this->currentKey = $this->currentAbbr.''_''.$this->observesDst; $this->currentOffset = $this->_baseObj->getOffset(self::$_dt_now); } public function toShallowArray() { $outArr = array( ''tzkey''=>$this->tzkey, ''friendlyName''=>$this->friendlyName, ''currentOffset''=>$this->currentOffset/3600, ''observesDst''=>$this->observesDst, ''currentlyDst''=>$this->currentlyDst, ''currentAbbr''=>$this->currentAbbr ); return $outArr; } }

Uf. Aquí hay ejemplos de uso (timezones.php):

<?php include_once ''TimezoneList.php''; /* Example 1: Get Select Box by Country Code */ $tzl = TimezoneList::byCountry(''US''); $tzl = $tzl->getUniqueTimezoneList(); echo $tzl->toSelect(true,true,''America/Los_Angeles''); echo "/n".''<br />''."/n"; /* Example 2: Get a list by country code, output as JSON for AJAX (or similar uses) */ $_REQUEST[''country_code''] = ''US''; // Hack for quick usage. $tzl_ajax = TimezoneList::byCountry($_REQUEST[''country_code'']); $tzl_ajax = $tzl_ajax->getUniqueTimezoneList(); echo ''<script type="text/javascript">''."/n"; echo ''var foo = ''.$tzl_ajax->toJson().'';''; echo "/n".''</script>''; echo "/n".''<br />''."/n"; /* Example 3: Get Select Box from a list of TZDs + friendly names */ $tzl2 = TimezoneList::fromIdentifierList( array(''America/Los_Angeles'',''America/Boise'',''America/Phoenix'',''America/Chicago'',''America/New_York''), array(''Pacific'',''Mountain'',''Mountain (Arizona)'',''Central'',''Eastern'') ); // Example shows setting extra properties on the <SELECT>. echo $tzl2->toSelect(true,false,''America/Los_Angeles'', array(''style''=>''font-size:15px; border:1px solid #ccc; padding:4px'', ''id''=>''timezone_list'', ''class''=>''standard-list'', ''name''=>''timezone'') ); echo "/n".''<br />''."/n"; /* Example 4: Get a raw list of timezones */ $tzl3 = new TimezoneList(true); $tzl3 = $tzl3->getUniqueTimezoneList(); echo $tzl3->toSelect(true,false,''America/Los_Angeles'');

Y aquí está el código de salida de los ejemplos en timezones.php:

<select> <option value="Pacific/Honolulu">Honolulu [HST -10:00 ( Does not observe DST ) ]</option> <option value="America/Adak">Adak [HADT -09:00]</option> <option value="America/Anchorage">Anchorage [AKDT -08:00]</option> <option value="America/Phoenix">Phoenix [MST -07:00 ( Does not observe DST ) ]</option> <option value="America/Los_Angeles" selected="selected">Los Angeles [PDT -07:00]</option> <option value="America/Boise">Boise [MDT -06:00]</option> <option value="America/Chicago">Chicago [CDT -05:00]</option> <option value="America/Detroit">Detroit [EDT -04:00]</option> </select> <br /> <script type="text/javascript"> var foo = [{"tzkey":"Pacific//Honolulu","friendlyName":"Honolulu","currentOffset":-10,"observesDst":false,"currentlyDst":false,"currentAbbr":"HST"},{"tzkey":"America//Adak","friendlyName":"Adak","currentOffset":-9,"observesDst":true,"currentlyDst":true,"currentAbbr":"HADT"},{"tzkey":"America//Anchorage","friendlyName":"Anchorage","currentOffset":-8,"observesDst":true,"currentlyDst":true,"currentAbbr":"AKDT"},{"tzkey":"America//Phoenix","friendlyName":"Phoenix","currentOffset":-7,"observesDst":false,"currentlyDst":false,"currentAbbr":"MST"},{"tzkey":"America//Los_Angeles","friendlyName":"Los Angeles","currentOffset":-7,"observesDst":true,"currentlyDst":true,"currentAbbr":"PDT"},{"tzkey":"America//Boise","friendlyName":"Boise","currentOffset":-6,"observesDst":true,"currentlyDst":true,"currentAbbr":"MDT"},{"tzkey":"America//Chicago","friendlyName":"Chicago","currentOffset":-5,"observesDst":true,"currentlyDst":true,"currentAbbr":"CDT"},{"tzkey":"America//Detroit","friendlyName":"Detroit","currentOffset":-4,"observesDst":true,"currentlyDst":true,"currentAbbr":"EDT"}]; </script> <br /> <select style="font-size:15px; border:1px solid #ccc; padding:4px" id="timezone_list" class="standard-list" name="timezone"> <option value="America/Los_Angeles" selected="selected">Pacific [PDT -07:00]</option> <option value="America/Boise">Mountain [MDT -06:00]</option> <option value="America/Phoenix">Mountain (Arizona) [MST -07:00]</option> <option value="America/Chicago">Central [CDT -05:00]</option> <option value="America/New_York">Eastern [EDT -04:00]</option> </select> <br /> <select> <option value="Pacific/Midway">Midway [SST -11:00]</option> <option value="Pacific/Niue">Niue [NUT -11:00]</option> <option value="Pacific/Apia">Apia [WST -11:00]</option> <option value="Pacific/Tahiti">Tahiti [TAHT -10:00]</option> <option value="Pacific/Honolulu">Honolulu [HST -10:00]</option> <option value="Pacific/Rarotonga">Rarotonga [CKT -10:00]</option> <option value="Pacific/Fakaofo">Fakaofo [TKT -10:00]</option> <option value="Pacific/Marquesas">Marquesas [MART -09:30]</option> <option value="America/Adak">Adak [HADT -09:00]</option> <option value="Pacific/Gambier">Gambier [GAMT -09:00]</option> <option value="America/Anchorage">Anchorage [AKDT -08:00]</option> <option value="Pacific/Pitcairn">Pitcairn [PST -08:00]</option> <option value="America/Dawson_Creek">Dawson Creek [MST -07:00]</option> <option value="America/Dawson">Dawson [PDT -07:00]</option> <option value="America/Belize">Belize [CST -06:00]</option> <option value="America/Boise">Boise [MDT -06:00]</option> <option value="Pacific/Easter">Easter [EAST -06:00]</option> <option value="Pacific/Galapagos">Galapagos [GALT -06:00]</option> <option value="America/Resolute">Resolute [CDT -05:00]</option> <option value="America/Cancun">Cancun [CDT -05:00]</option> <option value="America/Guayaquil">Guayaquil [ECT -05:00]</option> <option value="America/Lima">Lima [PET -05:00]</option> <option value="America/Bogota">Bogota [COT -05:00]</option> <option value="America/Atikokan">Atikokan [EST -05:00]</option> <option value="America/Caracas">Caracas [VET -04:30]</option> <option value="America/Guyana">Guyana [GYT -04:00]</option> <option value="America/Campo_Grande">Campo Grande [AMT -04:00]</option> <option value="America/La_Paz">La Paz [BOT -04:00]</option> <option value="America/Anguilla">Anguilla [AST -04:00]</option> <option value="Atlantic/Stanley">Stanley [FKT -04:00]</option> <option value="America/Detroit">Detroit [EDT -04:00]</option> <option value="America/Boa_Vista">Boa Vista [AMT -04:00]</option> <option value="America/Santiago">Santiago [CLT -04:00]</option> <option value="America/Asuncion">Asuncion [PYT -04:00]</option> <option value="Antarctica/Rothera">Rothera [ROTT -03:00]</option> <option value="America/Paramaribo">Paramaribo [SRT -03:00]</option> <option value="America/Sao_Paulo">Sao Paulo [BRT -03:00]</option> <option value="America/Argentina/Buenos_Aires">Buenos Aires [ART -03:00]</option> <option value="America/Cayenne">Cayenne [GFT -03:00]</option> <option value="America/Glace_Bay">Glace Bay [ADT -03:00]</option> <option value="America/Argentina/San_Luis">San Luis [WARST -03:00]</option> <option value="America/Araguaina">Araguaina [BRT -03:00]</option> <option value="America/Montevideo">Montevideo [UYT -03:00]</option> <option value="America/St_Johns">St Johns [NDT -02:30]</option> <option value="America/Miquelon">Miquelon [PMDT -02:00]</option> <option value="America/Noronha">Noronha [FNT -02:00]</option> <option value="America/Godthab">Godthab [WGST -02:00]</option> <option value="Atlantic/Cape_Verde">Cape Verde [CVT -01:00]</option> <option value="Atlantic/Azores">Azores [AZOST 00:00]</option> <option value="America/Scoresbysund">Scoresbysund [EGST 00:00]</option> <option value="UTC">UTC [UTC 00:00]</option> <option value="Africa/Abidjan">Abidjan [GMT 00:00]</option> <option value="Africa/Casablanca">Casablanca [WET 00:00]</option> <option value="Africa/Bangui">Bangui [WAT +01:00]</option> <option value="Europe/Guernsey">Guernsey [BST +01:00]</option> <option value="Europe/Dublin">Dublin [IST +01:00]</option> <option value="Africa/Algiers">Algiers [CET +01:00]</option> <option value="Atlantic/Canary">Canary [WEST +01:00]</option> <option value="Africa/Windhoek">Windhoek [WAT +01:00]</option> <option value="Africa/Johannesburg">Johannesburg [SAST +02:00]</option> <option value="Africa/Blantyre">Blantyre [CAT +02:00]</option> <option value="Africa/Tripoli">Tripoli [EET +02:00]</option> <option value="Africa/Ceuta">Ceuta [CEST +02:00]</option> <option value="Asia/Jerusalem">Jerusalem [IDT +03:00]</option> <option value="Africa/Addis_Ababa">Addis Ababa [EAT +03:00]</option> <option value="Africa/Cairo">Cairo [EEST +03:00]</option> <option value="Antarctica/Syowa">Syowa [SYOT +03:00]</option> <option value="Europe/Volgograd">Volgograd [VOLST +04:00]</option> <option value="Europe/Samara">Samara [SAMST +04:00]</option> <option value="Asia/Tbilisi">Tbilisi [GET +04:00]</option> <option value="Europe/Moscow">Moscow [MSD +04:00]</option> <option value="Asia/Dubai">Dubai [GST +04:00]</option> <option value="Indian/Mauritius">Mauritius [MUT +04:00]</option> <option value="Indian/Reunion">Reunion [RET +04:00]</option> <option value="Indian/Mahe">Mahe [SCT +04:00]</option> <option value="Asia/Tehran">Tehran [IRDT +04:30]</option> <option value="Asia/Kabul">Kabul [AFT +04:30]</option> <option value="Asia/Aqtau">Aqtau [AQTT +05:00]</option> <option value="Asia/Ashgabat">Ashgabat [TMT +05:00]</option> <option value="Asia/Oral">Oral [ORAT +05:00]</option> <option value="Asia/Yerevan">Yerevan [AMST +05:00]</option> <option value="Asia/Baku">Baku [AZST +05:00]</option> <option value="Indian/Kerguelen">Kerguelen [TFT +05:00]</option> <option value="Indian/Maldives">Maldives [MVT +05:00]</option> <option value="Asia/Karachi">Karachi [PKT +05:00]</option> <option value="Asia/Dushanbe">Dushanbe [TJT +05:00]</option> <option value="Asia/Samarkand">Samarkand [UZT +05:00]</option> <option value="Antarctica/Mawson">Mawson [MAWT +05:00]</option> <option value="Asia/Colombo">Colombo [IST +05:30]</option> <option value="Asia/Kathmandu">Kathmandu [NPT +05:45]</option> <option value="Indian/Chagos">Chagos [IOT +06:00]</option> <option value="Asia/Bishkek">Bishkek [KGT +06:00]</option> <option value="Asia/Almaty">Almaty [ALMT +06:00]</option> <option value="Antarctica/Vostok">Vostok [VOST +06:00]</option> <option value="Asia/Yekaterinburg">Yekaterinburg [YEKST +06:00]</option> <option value="Asia/Dhaka">Dhaka [BDT +06:00]</option> <option value="Asia/Thimphu">Thimphu [BTT +06:00]</option> <option value="Asia/Qyzylorda">Qyzylorda [QYZT +06:00]</option> <option value="Indian/Cocos">Cocos [CCT +06:30]</option> <option value="Asia/Rangoon">Rangoon [MMT +06:30]</option> <option value="Asia/Jakarta">Jakarta [WIT +07:00]</option> <option value="Asia/Hovd">Hovd [HOVT +07:00]</option> <option value="Antarctica/Davis">Davis [DAVT +07:00]</option> <option value="Asia/Bangkok">Bangkok [ICT +07:00]</option> <option value="Indian/Christmas">Christmas [CXT +07:00]</option> <option value="Asia/Omsk">Omsk [OMSST +07:00]</option> <option value="Asia/Novokuznetsk">Novokuznetsk [NOVST +07:00]</option> <option value="Asia/Choibalsan">Choibalsan [CHOT +08:00]</option> <option value="Asia/Ulaanbaatar">Ulaanbaatar [ULAT +08:00]</option> <option value="Asia/Brunei">Brunei [BNT +08:00]</option> <option value="Antarctica/Casey">Casey [WST +08:00]</option> <option value="Asia/Singapore">Singapore [SGT +08:00]</option> <option value="Asia/Manila">Manila [PHT +08:00]</option> <option value="Asia/Hong_Kong">Hong Kong [HKT +08:00]</option> <option value="Asia/Krasnoyarsk">Krasnoyarsk [KRAST +08:00]</option> <option value="Asia/Makassar">Makassar [CIT +08:00]</option> <option value="Asia/Kuala_Lumpur">Kuala Lumpur [MYT +08:00]</option> <option value="Australia/Eucla">Eucla [CWST +08:45]</option> <option value="Pacific/Palau">Palau [PWT +09:00]</option> <option value="Asia/Tokyo">Tokyo [JST +09:00]</option> <option value="Asia/Dili">Dili [TLT +09:00]</option> <option value="Asia/Jayapura">Jayapura [EIT +09:00]</option> <option value="Asia/Pyongyang">Pyongyang [KST +09:00]</option> <option value="Asia/Irkutsk">Irkutsk [IRKST +09:00]</option> <option value="Australia/Adelaide">Adelaide [CST +09:30]</option> <option value="Asia/Yakutsk">Yakutsk [YAKST +10:00]</option> <option value="Australia/Currie">Currie [EST +10:00]</option> <option value="Pacific/Port_Moresby">Port Moresby [PGT +10:00]</option> <option value="Pacific/Guam">Guam [ChST +10:00]</option> <option value="Pacific/Truk">Truk [TRUT +10:00]</option> <option value="Antarctica/DumontDUrville">DumontDUrville [DDUT +10:00]</option> <option value="Australia/Lord_Howe">Lord Howe [LHST +10:30]</option> <option value="Pacific/Ponape">Ponape [PONT +11:00]</option> <option value="Pacific/Kosrae">Kosrae [KOST +11:00]</option> <option value="Antarctica/Macquarie">Macquarie [MIST +11:00]</option> <option value="Pacific/Noumea">Noumea [NCT +11:00]</option> <option value="Pacific/Efate">Efate [VUT +11:00]</option> <option value="Pacific/Guadalcanal">Guadalcanal [SBT +11:00]</option> <option value="Asia/Sakhalin">Sakhalin [SAKST +11:00]</option> <option value="Asia/Vladivostok">Vladivostok [VLAST +11:00]</option> <option value="Pacific/Norfolk">Norfolk [NFT +11:30]</option> <option value="Asia/Kamchatka">Kamchatka [PETST +12:00]</option> <option value="Pacific/Tarawa">Tarawa [GILT +12:00]</option> <option value="Asia/Magadan">Magadan [MAGST +12:00]</option> <option value="Pacific/Wallis">Wallis [WFT +12:00]</option> <option value="Pacific/Kwajalein">Kwajalein [MHT +12:00]</option> <option value="Pacific/Funafuti">Funafuti [TVT +12:00]</option> <option value="Pacific/Nauru">Nauru [NRT +12:00]</option> <option value="Asia/Anadyr">Anadyr [ANAST +12:00]</option> <option value="Antarctica/McMurdo">McMurdo [NZST +12:00]</option> <option value="Pacific/Wake">Wake [WAKT +12:00]</option> <option value="Pacific/Fiji">Fiji [FJT +12:00]</option> <option value="Pacific/Chatham">Chatham [CHAST +12:45]</option> <option value="Pacific/Enderbury">Enderbury [PHOT +13:00]</option> <option value="Pacific/Tongatapu">Tongatapu [TOT +13:00]</option> <option value="Pacific/Kiritimati">Kiritimati [LINT +14:00]</option> </select>



Mi solución:

Para evitar una gran lista de zonas horarias, haga que el usuario seleccione primero el país, luego use esa información para completar una lista de zonas horarias.

Archivo populate.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>Select test</title> <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.2.min.js"></script> <script type="text/javascript" charset="utf-8"> $(function(){ $("select#country").change(function(){ $.getJSON("json.php",{country: $(this).val()}, function(j){ var options = ''''; for (var i = 0; i < j.length; i++) { options += ''<option value="'' + j[i].optionValue + ''">'' + j[i].optionDisplay + ''</option>''; } $("#city").html(options); $(''#city option:first'').attr(''selected'', ''selected''); }) }) }) </script> </head> <body> <form action="#"> <label for="country">Country:</label> <select name="country" id="country"> <option value="Portugal">Portugal</option> <option value="United States">United States</option> <option value="Japan">Japan</option> </select> <label for="city">Timezone:</label> <select name="city" id="city"> <option value="Atlantic/Azores">Atlantic/Azores</option> <option value="Atlantic/Madeira">Atlantic/Madeira</option> <option value="Europe/Lisbon">Europe/Lisbon</option> </select> <input type="submit" name="action" value="Set TZ" /> </form>

archivo json.php

$country = $_GET[''country'']; $citylist = ""; $country_list = file_get_contents("country_iso.txt"); //grab this file @ http://pastebin.com/e8gxcVHm preg_match_all(''/(.*?):''.$country.''/im'', $country_list, $country_iso, PREG_PATTERN_ORDER); $country_iso = $country_iso[1][0]; if(isset($country_iso)) { $tz = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country_iso); //php 5.3 needed to use DateTimeZone::PER_COUNTRY ! foreach($tz as $city) $citylist .= "{/"optionValue/": /"$city/", /"optionDisplay/": /"$city/"}, "; } $citylist = preg_replace(''/, $/im'', '''', $citylist); $citylist = "[".$citylist."]"; echo $citylist;

Espero que te ayude :)


Se me ocurrió una solución auto-actualizada dinámica que no requiere ninguna tabla de búsqueda ( seleccione demo ):

function Timezones() { $result = array(); $timezones = array(); // only process geographical timezones foreach (preg_grep(''~^(?:A(?:frica|merica|ntarctica|rctic|tlantic|sia|ustralia)|Europe|Indian|Pacific)/~'', timezone_identifiers_list()) as $timezone) { if (is_object($timezone = new DateTimeZone($timezone)) === true) { $id = array(); // get only the two most distant transitions foreach (array_slice($timezone->getTransitions($_SERVER[''REQUEST_TIME'']), -2) as $transition) { // dark magic $id[] = sprintf(''%b|%+d|%u'', $transition[''isdst''], $transition[''offset''], $transition[''ts'']); } if (count($id) > 1) { sort($id, SORT_NUMERIC); // sort by %b (isdst = 0) first, so that we always get the raw offset } $timezones[implode(''|'', $id)][] = $timezone->getName(); } } if ((is_array($timezones) === true) && (count($timezones) > 0)) { uksort($timezones, function($a, $b) // sort offsets by -, 0, + { foreach (array(''a'', ''b'') as $key) { $$key = explode(''|'', $$key); } return intval($a[1]) - intval($b[1]); }); foreach ($timezones as $key => $value) { $zone = reset($value); // first timezone ID is our internal timezone $result[$zone] = preg_replace(array(''~^.*/([^/]+)$~'', ''~_~''), array(''$1'', '' ''), $value); // "humanize" city names if (array_key_exists(1, $offset = explode(''|'', $key)) === true) // "humanize" the offset { $offset = str_replace('' +00:00'', '''', sprintf(''(UTC %+03d:%02u)'', $offset[1] / 3600, abs($offset[1]) % 3600 / 60)); } if (asort($result[$zone]) === true) // sort city names { $result[$zone] = trim(sprintf(''%s %s'', $offset, implode('', '', $result[$zone]))); } } } return $result; }

Hay muchas zonas horarias que comparten los mismos desplazamientos exactos y temporizaciones DST ( Europe/Dublin , Europe/Lisbon y Europe/London por nombrar algunas), mi algoritmo agrupa estas zonas (utilizando una notación especial en las teclas de matriz dst?|offset|timestamp ) en la primera identificación de zona horaria de ese grupo y concatena las transformaciones humanizadas del último segmento (generalmente a nivel de ciudad) de la ID de la zona horaria:

Array ( [Pacific/Midway] => (UTC -11:00) Midway, Niue, Pago Pago [America/Adak] => (UTC -10:00) Adak [Pacific/Fakaofo] => (UTC -10:00) Fakaofo, Honolulu, Johnston, Rarotonga, Tahiti [Pacific/Marquesas] => (UTC -10:30) Marquesas [America/Anchorage] => (UTC -09:00) Anchorage, Juneau, Nome, Sitka, Yakutat [Pacific/Gambier] => (UTC -09:00) Gambier [America/Dawson] => (UTC -08:00) Dawson, Los Angeles, Tijuana, Vancouver, Whitehorse [America/Santa_Isabel] => (UTC -08:00) Santa Isabel [America/Metlakatla] => (UTC -08:00) Metlakatla, Pitcairn [America/Dawson_Creek] => (UTC -07:00) Dawson Creek, Hermosillo, Phoenix [America/Chihuahua] => (UTC -07:00) Chihuahua, Mazatlan [America/Boise] => (UTC -07:00) Boise, Cambridge Bay, Denver, Edmonton, Inuvik, Ojinaga, Shiprock, Yellowknife [America/Chicago] => (UTC -06:00) Beulah, Center, Chicago, Knox, Matamoros, Menominee, New Salem, Rainy River, Rankin Inlet, Resolute, Tell City, Winnipeg [America/Belize] => (UTC -06:00) Belize, Costa Rica, El Salvador, Galapagos, Guatemala, Managua, Regina, Swift Current, Tegucigalpa [Pacific/Easter] => (UTC -06:00) Easter [America/Bahia_Banderas] => (UTC -06:00) Bahia Banderas, Cancun, Merida, Mexico City, Monterrey [America/Detroit] => (UTC -05:00) Detroit, Grand Turk, Indianapolis, Iqaluit, Louisville, Marengo, Monticello, Montreal, Nassau, New York, Nipigon, Pangnirtung, Petersburg, Thunder Bay, Toronto, Vevay, Vincennes, Winamac [America/Atikokan] => (UTC -05:00) Atikokan, Bogota, Cayman, Guayaquil, Jamaica, Lima, Panama, Port-au-Prince [America/Havana] => (UTC -05:00) Havana [America/Caracas] => (UTC -05:30) Caracas [America/Glace_Bay] => (UTC -04:00) Bermuda, Glace Bay, Goose Bay, Halifax, Moncton, Thule [Atlantic/Stanley] => (UTC -04:00) Stanley [America/Santiago] => (UTC -04:00) Palmer, Santiago [America/Anguilla] => (UTC -04:00) Anguilla, Antigua, Aruba, Barbados, Blanc-Sablon, Boa Vista, Curacao, Dominica, Eirunepe, Grenada, Guadeloupe, Guyana, Kralendijk, La Paz, Lower Princes, Manaus, Marigot, Martinique, Montserrat, Port of Spain, Porto Velho, Puerto Rico, Rio Branco, Santo Domingo, St Barthelemy, St Kitts, St Lucia, St Thomas, St Vincent, Tortola [America/Campo_Grande] => (UTC -04:00) Campo Grande, Cuiaba [America/Asuncion] => (UTC -04:00) Asuncion [America/St_Johns] => (UTC -04:30) St Johns [America/Sao_Paulo] => (UTC -03:00) Sao Paulo [America/Araguaina] => (UTC -03:00) Araguaina, Bahia, Belem, Buenos Aires, Catamarca, Cayenne, Cordoba, Fortaleza, Jujuy, La Rioja, Maceio, Mendoza, Paramaribo, Recife, Rio Gallegos, Rothera, Salta, San Juan, Santarem, Tucuman, Ushuaia [America/Montevideo] => (UTC -03:00) Montevideo [America/Godthab] => (UTC -03:00) Godthab [America/Argentina/San_Luis] => (UTC -03:00) San Luis [America/Miquelon] => (UTC -03:00) Miquelon [America/Noronha] => (UTC -02:00) Noronha, South Georgia [Atlantic/Cape_Verde] => (UTC -01:00) Cape Verde [America/Scoresbysund] => (UTC -01:00) Azores, Scoresbysund [Atlantic/Canary] => (UTC) Canary, Dublin, Faroe, Guernsey, Isle of Man, Jersey, Lisbon, London, Madeira [Africa/Abidjan] => (UTC) Abidjan, Accra, Bamako, Banjul, Bissau, Casablanca, Conakry, Dakar, Danmarkshavn, El Aaiun, Freetown, Lome, Monrovia, Nouakchott, Ouagadougou, Reykjavik, Sao Tome, St Helena [Africa/Algiers] => (UTC +01:00) Algiers, Bangui, Brazzaville, Douala, Kinshasa, Lagos, Libreville, Luanda, Malabo, Ndjamena, Niamey, Porto-Novo, Tunis [Africa/Ceuta] => (UTC +01:00) Amsterdam, Andorra, Belgrade, Berlin, Bratislava, Brussels, Budapest, Ceuta, Copenhagen, Gibraltar, Ljubljana, Longyearbyen, Luxembourg, Madrid, Malta, Monaco, Oslo, Paris, Podgorica, Prague, Rome, San Marino, Sarajevo, Skopje, Stockholm, Tirane, Vaduz, Vatican, Vienna, Warsaw, Zagreb, Zurich [Africa/Windhoek] => (UTC +01:00) Windhoek [Asia/Damascus] => (UTC +02:00) Damascus [Asia/Beirut] => (UTC +02:00) Beirut [Asia/Jerusalem] => (UTC +02:00) Jerusalem [Asia/Nicosia] => (UTC +02:00) Athens, Bucharest, Chisinau, Helsinki, Istanbul, Mariehamn, Nicosia, Riga, Sofia, Tallinn, Vilnius [Africa/Blantyre] => (UTC +02:00) Blantyre, Bujumbura, Cairo, Gaborone, Gaza, Harare, Hebron, Johannesburg, Kigali, Lubumbashi, Lusaka, Maputo, Maseru, Mbabane, Tripoli [Asia/Amman] => (UTC +02:00) Amman [Africa/Addis_Ababa] => (UTC +03:00) Addis Ababa, Aden, Antananarivo, Asmara, Baghdad, Bahrain, Comoro, Dar es Salaam, Djibouti, Juba, Kaliningrad, Kampala, Khartoum, Kiev, Kuwait, Mayotte, Minsk, Mogadishu, Nairobi, Qatar, Riyadh, Simferopol, Syowa, Uzhgorod, Zaporozhye [Asia/Tehran] => (UTC +03:30) Tehran [Asia/Yerevan] => (UTC +04:00) Yerevan [Asia/Dubai] => (UTC +04:00) Dubai, Mahe, Mauritius, Moscow, Muscat, Reunion, Samara, Tbilisi, Volgograd [Asia/Baku] => (UTC +04:00) Baku [Asia/Kabul] => (UTC +04:30) Kabul [Antarctica/Mawson] => (UTC +05:00) Aqtau, Aqtobe, Ashgabat, Dushanbe, Karachi, Kerguelen, Maldives, Mawson, Oral, Samarkand, Tashkent [Asia/Colombo] => (UTC +05:30) Colombo, Kolkata [Asia/Kathmandu] => (UTC +05:45) Kathmandu [Antarctica/Vostok] => (UTC +06:00) Almaty, Bishkek, Chagos, Dhaka, Qyzylorda, Thimphu, Vostok, Yekaterinburg [Asia/Rangoon] => (UTC +06:30) Cocos, Rangoon [Antarctica/Davis] => (UTC +07:00) Bangkok, Christmas, Davis, Ho Chi Minh, Hovd, Jakarta, Novokuznetsk, Novosibirsk, Omsk, Phnom Penh, Pontianak, Vientiane [Antarctica/Casey] => (UTC +08:00) Brunei, Casey, Choibalsan, Chongqing, Harbin, Hong Kong, Kashgar, Krasnoyarsk, Kuala Lumpur, Kuching, Macau, Makassar, Manila, Perth, Shanghai, Singapore, Taipei, Ulaanbaatar, Urumqi [Australia/Eucla] => (UTC +08:45) Eucla [Asia/Dili] => (UTC +09:00) Dili, Irkutsk, Jayapura, Palau, Pyongyang, Seoul, Tokyo [Australia/Adelaide] => (UTC +09:30) Adelaide, Broken Hill [Australia/Darwin] => (UTC +09:30) Darwin [Antarctica/DumontDUrville] => (UTC +10:00) Brisbane, Chuuk, DumontDUrville, Guam, Lindeman, Port Moresby, Saipan, Yakutsk [Australia/Currie] => (UTC +10:00) Currie, Hobart, Melbourne, Sydney [Australia/Lord_Howe] => (UTC +10:30) Lord Howe [Antarctica/Macquarie] => (UTC +11:00) Efate, Guadalcanal, Kosrae, Macquarie, Noumea, Pohnpei, Sakhalin, Vladivostok [Pacific/Norfolk] => (UTC +11:30) Norfolk [Antarctica/McMurdo] => (UTC +12:00) Auckland, McMurdo, South Pole [Asia/Anadyr] => (UTC +12:00) Anadyr, Fiji, Funafuti, Kamchatka, Kwajalein, Magadan, Majuro, Nauru, Tarawa, Wake, Wallis [Pacific/Chatham] => (UTC +12:45) Chatham [Pacific/Enderbury] => (UTC +13:00) Enderbury, Tongatapu [Pacific/Apia] => (UTC +13:00) Apia [Pacific/Kiritimati] => (UTC +14:00) Kiritimati )

Por supuesto, la concatenación de la ciudad todavía es bastante larga, pero la lista de zonas horarias únicas (reales) se ha reducido de 414 (o 415, si consideramos el UTC no geográfico) a 75, que es bastante buena y parece reflejar la lista de las zonas horarias "normalizadas" que usa Windows (también 75).

Hay dos grandes problemas con este enfoque automatizado:

  1. La identificación de zona horaria elegida para un grupo de ciudades es la primera en orden alfabético, esto quiere decir que para (UTC) Canarias, Dublín, Faroe, Guernsey, Isla de Man, Jersey, Lisboa, Londres, Madeira, el valor de la zona horaria será Atlantic/Canary - aunque no debería haber nada de malo en eso, tendría más sentido elegir una identificación de zona horaria asociada a una ciudad más grande (como Europe/London )
  2. la concatenación de ciudades es claramente el mayor problema, hay demasiadas. Una forma de resolver este problema sería mediante el uso de array_slice($cities, 0, $maxCities) antes de implosionar, pero esto no tendría la dimensión de ciudad en cuenta, y por un límite de 4 Canarias, Dublín, Faroe, Guernsey, Isla de Man, Jersey, Lisboa, Londres, Madeira se convertiría en Canarias, Dublín, Faroe, Guernsey en lugar del equivalente lógico de Windows Dublín, Edimburgo, Lisboa, Londres .

Esto no debería ser muy útil, pero pensé que lo compartiría, quizás alguien más pueda mejorarlo.


Si desea hacer cosas con zoneinfo, no tiene otra opción que incluir cientos de entradas, porque así es como funciona zoneinfo. Generalmente tiene al menos una entrada por país, y hay alrededor de 200 países (según Wikipedia ).

Lo que he hecho antes es usar timezone_identifiers_list() y filtrar cualquier entrada que no esté en una de las regiones estándar:

# Output option list, HTML. $opt = ''''; $regions = array(''Africa'', ''America'', ''Antarctica'', ''Arctic'', ''Asia'', ''Atlantic'', ''Australia'', ''Europe'', ''Indian'', ''Pacific''); $tzs = timezone_identifiers_list(); $optgroup = ''''; sort($tzs); foreach ($tzs as $tz) { $z = explode(''/'', $tz, 2); # timezone_identifiers_list() returns a number of # backwards-compatibility entries. This filters them out of the # list presented to the user. if (count($z) != 2 || !in_array($z[0], $regions)) continue; if ($optgroup != $z[0]) { if ($optgroup !== '''') $opt .= ''</optgroup>''; $optgroup = $z[0]; $opt .= ''<optgroup label="'' . htmlentities($z[0]) . ''">''; } $opt .= ''<option value="'' . htmlentities($tz) . ''" label="'' . htmlentities(str_replace(''_'', '' '', $z[1])) . ''">'' . htmlentities(str_replace(''_'', '' '', $tz)) . ''</option>''; } if ($optgroup !== '''') $opt .= ''</optgroup>'';

Esto crea una lista con elementos <optgroup> , por lo que la lista al menos se dividirá lógicamente por región.


Después de pensar (y probar) mucho sobre este problema, he llegado a la conclusión de que no puedes usar listas cortas de zonas horarias por el simple hecho de que las reglas de zona horaria son dinámicas (más de lo que cabría esperar). 4 zonas horarias tendrán sus reglas cambiado este mes) y los grupos / concatenaciones / abreviaturas son estáticos.

Aquí está el código para el enfoque que decidí seguir:

function Timezones($country = null, $continent = null) { $result = array(); if (is_array($timezones = DateTimeZone::listIdentifiers()) === true) { $timestamp = strtotime(''-6 months'', time()); if ((strlen($country) == 2) && (defined(''DateTimeZone::PER_COUNTRY'') === true)) { $timezones = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, $country); } foreach (preg_grep(''~'' . preg_quote($continent, ''~'') . ''/~i'', $timezones) as $id) { $timezone = new DateTimeZone($id); if (is_array($transitions = $timezone->getTransitions()) === true) { while ((isset($result[$id]) !== true) && (is_null($transition = array_shift($transitions)) !== true)) { $result[$id] = (($transition[''isdst''] !== true) && ($transition[''ts''] >= $timestamp)) ? $transition[''offset''] : null; } } } if (array_multisort($result, SORT_NUMERIC, preg_replace(''~^[^/]+/~'', '''', array_keys($result)), SORT_REGULAR, $result) === true) { foreach ($result as $key => $value) { $result[$key] = sprintf(''(GMT %+03d:%02u) %s'', $value / 3600, abs($value) % 3600 / 60, ltrim(strstr($key, ''/''), ''/'')); } } } return str_replace(array('' +00:00'', ''_'', ''/''), array('''', '' '', '' - ''), $result); }

  • admite filtrar por país y continente simultáneamente (como en EE. UU./America o EE. UU./Pacífico)
  • el desplazamiento estándar (sin procesar) se calcula dinámicamente para cada zona horaria
  • las zonas horarias se ordenan por su desplazamiento primero y luego por su ubicación
  • el identificador de zona horaria se convierte en una representación legible por humanos

Demostración en http://www.ideone.com/VYWtw y http://jsfiddle.net/hSxa8/embedded/result/ .


Puedo pensar en algunas opciones.

Primero, llenar toda la lista de selección y usar un plugin jQuery como Chosen para rellenar toda la lista. Probablemente esto sea una mierda, ya que es posible que los usuarios ni siquiera conozcan todas las zonas horarias.

La segunda opción es usar JS para obtener la hora local del navegador en un campo de entrada oculto, y combinar eso con el conocimiento de la IP de los usuarios para tratar de deducir la ubicación de los usuarios de forma transparente. Incluso podría mostrar su ubicación asumida en un mapa y preguntarles si tiene la hora correcta.

La tercera opción es preguntarle al usuario dónde viven. El país y el código postal probablemente deberían ser suficientes para obtener la zona horaria para la mayoría de los usuarios. En casos extremos, puede pedirle al usuario que aclare.

Personalmente, probablemente combinaría la primera y la segunda solución para que una lista de selección muestre las regiones en las que cree que el usuario está más cerca.


Esto se ha respondido durante mucho tiempo, pero no estaba satisfecho con ninguna de las respuestas que obligaban a los usuarios a pasar por todas las entradas TZ que conoce php. En su lugar, creé una lista más concisa que mapea tiempos como el este de America / New_York e incluye entradas especiales para ubicaciones raras como Arizona.

Entrada de Github: https://github.com/ryanzor/timezone-dropdown

Demo de solo selector: http://lifesnow.com/time-zone-dropdown/

<?php /** * * This get''s the timezone offset based on the olson code. * In this code it is used to find the offset between the given olson code and UTC, but can be used to convert other differences * * @param string $remote_tz TZ string * @param string $origin_tz TZ string, defaults to UTC * @return int offset in seconds */ function ln_get_timezone_offset($remote_tz, $origin_tz = ''UTC'') { $origin_dtz = new DateTimeZone($origin_tz); $remote_dtz = new DateTimeZone($remote_tz); $origin_dt = new DateTime("now", $origin_dtz); $remote_dt = new DateTime("now", $remote_dtz); $offset = $remote_dtz->getOffset($remote_dt) - $origin_dtz->getOffset($origin_dt); return $offset; } /** * Converts a timezone difference to be displayed as GMT +/- * * @param string $timezone TZ time * @return string text with GMT */ function ln_get_timezone_offset_text($timezone){ $time = ln_get_timezone_offset($timezone); $minutesOffset = $time/60; $hours = floor(($minutesOffset)/60); $minutes = abs($minutesOffset%60); $minutesFormatted = sprintf(''%02d'', $minutes); $plus = ''''; if($time >= 0){ $plus = ''+''; } $GMToff = ''GMT ''.$plus.$hours.'':''.$minutesFormatted; return $GMToff; } /** * This is for formatting how the timezone option displays. * It can be converted to include current time, not include gmt or anything like that. * * @param string $timezone TZ time * @param string $text format select box option */ function ln_display_timezone_option($timezone, $text){ ?> <option value="<?php echo $timezone; ?>"><?php echo ''(''.ln_get_timezone_offset_text($timezone).'') ''.$text; ?></option> <?php } /** * The concise list of timezones. This generates the html wherever it is called */ function ln_display_timezone_selector(){ ?> <select name="timezoneSelectDropdown"> <?php ln_display_timezone_option(''Pacific/Auckland'', ''International Date Line West''); ln_display_timezone_option(''Pacific/Midway'', ''Midway Island, Samoa''); ln_display_timezone_option(''US/Hawaii'', ''Hawaii''); ln_display_timezone_option(''US/Alaska'', ''Alaska''); ln_display_timezone_option(''US/Pacific'', ''Pacific Time (US & Canada)''); ln_display_timezone_option(''America/Tijuana'', ''Tijuana, Baja California''); ln_display_timezone_option(''America/Phoenix'', ''Arizona''); ln_display_timezone_option(''America/Chihuahua'', ''Chihuahua, La Paz, Mazatlan''); ln_display_timezone_option(''US/Mountain'', ''Mountain Time (US & Canada)''); ln_display_timezone_option(''America/Cancun'', ''Central America''); ln_display_timezone_option(''US/Central'', ''Central Time (US & Canada)''); ln_display_timezone_option(''America/Mexico_City'', ''Guadalajara, Mexico City, Monterrey''); ln_display_timezone_option(''Canada/Saskatchewan'', ''Saskatchewan''); ln_display_timezone_option(''America/Lima'', ''Bogota, Lima, Quito, Rio Branco''); ln_display_timezone_option(''US/Eastern'', ''Eastern Time (US & Canada)''); ln_display_timezone_option(''US/East-Indiana'', ''Indiana (East)''); ln_display_timezone_option(''Canada/Atlantic'', ''Atlantic Time (Canada)''); ln_display_timezone_option(''America/Caracas'', ''Caracas, La Paz''); ln_display_timezone_option(''America/Manaus'', ''Manaus''); ln_display_timezone_option(''America/Santiago'', ''Santiago''); ln_display_timezone_option(''Canada/Newfoundland'', ''Newfoundland''); ln_display_timezone_option(''America/Sao_Paulo'', ''Brasilia''); ln_display_timezone_option(''America/Argentina/Buenos_Aires'', ''Buenos Aires, Georgetown''); ln_display_timezone_option(''America/Godthab'', ''Greenland''); ln_display_timezone_option(''America/Montevideo'', ''Montevideo''); ln_display_timezone_option(''Atlantic/South_Georgia'', ''Mid-Atlantic''); ln_display_timezone_option(''Atlantic/Cape_Verde'', ''Cape Verde Is.''); ln_display_timezone_option(''Atlantic/Azores'', ''Azores''); ln_display_timezone_option(''Africa/Casablanca'', ''Casablanca, Monrovia, Reykjavik''); ln_display_timezone_option(''UTC'', ''Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London''); ln_display_timezone_option(''Europe/Amsterdam'', ''Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna''); ln_display_timezone_option(''Europe/Belgrade'', ''Belgrade, Bratislava, Budapest, Ljubljana, Prague''); ln_display_timezone_option(''Europe/Brussels'', ''Brussels, Copenhagen, Madrid, Paris''); ln_display_timezone_option(''Europe/Sarajevo'', ''Sarajevo, Skopje, Warsaw, Zagreb''); ln_display_timezone_option(''Africa/Windhoek'', ''West Central Africa''); ln_display_timezone_option(''Asia/Amman'', ''Amman''); ln_display_timezone_option(''Europe/Athens'', ''Athens, Bucharest, Istanbul''); ln_display_timezone_option(''Asia/Beirut'', ''Beirut''); ln_display_timezone_option(''Africa/Cairo'', ''Cairo''); ln_display_timezone_option(''Africa/Harare'', ''Harare, Pretoria''); ln_display_timezone_option(''Europe/Helsinki'', ''Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius''); ln_display_timezone_option(''Asia/Jerusalem'', ''Jerusalem''); ln_display_timezone_option(''Europe/Minsk'', ''Minsk''); ln_display_timezone_option(''Africa/Windhoek'', ''Windhoek''); ln_display_timezone_option(''Asia/Kuwait'', ''Kuwait, Riyadh, Baghdad''); ln_display_timezone_option(''Europe/Moscow'', ''Moscow, St. Petersburg, Volgograd''); ln_display_timezone_option(''Africa/Nairobi'', ''Nairobi''); ln_display_timezone_option(''Asia/Tbilisi'', ''Tbilisi''); ln_display_timezone_option(''Asia/Tehran'', ''Tehran''); ln_display_timezone_option(''Asia/Muscat'', ''Abu Dhabi, Muscat''); ln_display_timezone_option(''Asia/Baku'', ''Baku''); ln_display_timezone_option(''Asia/Yerevan'', ''Yerevan''); ln_display_timezone_option(''Asia/Kabul'', ''Kabul''); ln_display_timezone_option(''Asia/Yekaterinburg'', ''Yekaterinburg''); ln_display_timezone_option(''Asia/Karachi'', ''Islamabad, Karachi, Tashkent''); ln_display_timezone_option(''Asia/Kolkata'', ''Sri Jayawardenepura''); ln_display_timezone_option(''Asia/Kolkata'', ''Chennai, Kolkata, Mumbai, New Delhi''); ln_display_timezone_option(''Asia/Kathmandu'', ''Kathmandu''); ln_display_timezone_option(''Asia/Almaty'', ''Almaty, Novosibirsk''); ln_display_timezone_option(''Asia/Dhaka'', ''Astana, Dhaka''); ln_display_timezone_option(''Asia/Rangoon'', ''Yangon (Rangoon)''); ln_display_timezone_option(''Asia/Bangkok'', ''Bangkok, Hanoi, Jakarta''); ln_display_timezone_option(''Asia/Krasnoyarsk'', ''Krasnoyarsk''); ln_display_timezone_option(''Asia/Shanghai'', ''Beijing, Chongqing, Hong Kong, Urumqi''); ln_display_timezone_option(''Asia/Singapore'', ''Kuala Lumpur, Singapore''); ln_display_timezone_option(''Asia/Irkutsk'', ''Irkutsk, Ulaan Bataar''); ln_display_timezone_option(''Australia/Perth'', ''Perth''); ln_display_timezone_option(''Asia/Taipei'', ''Taipei''); ln_display_timezone_option(''Asia/Tokyo'', ''Osaka, Sapporo, Tokyo''); ln_display_timezone_option(''Asia/Seoul'', ''Seoul''); ln_display_timezone_option(''Asia/Yakutsk'', ''Yakutsk''); ln_display_timezone_option(''Australia/Adelaide'', ''Adelaide''); ln_display_timezone_option(''Australia/Darwin'', ''Darwin''); ln_display_timezone_option(''Australia/Brisbane'', ''Brisbane''); ln_display_timezone_option(''Australia/Sydney'', ''Canberra, Melbourne, Sydney''); ln_display_timezone_option(''Australia/Hobart'', ''Hobart''); ln_display_timezone_option(''Pacific/Guam'', ''Guam, Port Moresby''); ln_display_timezone_option(''Asia/Vladivostok'', ''Vladivostok''); ln_display_timezone_option(''Asia/Magadan'', ''Magadan, Solomon Is., New Caledonia''); ln_display_timezone_option(''Pacific/Auckland'', ''Auckland, Wellington''); ln_display_timezone_option(''Pacific/Fiji'', ''Fiji, Kamchatka, Marshall Is.''); ln_display_timezone_option(''Pacific/Tongatapu'', ''Nuku/'alofa''); ?> </select> <?php } ?>


Hay una lista / referencia en la respuesta a esta pregunta . Se trata de solo 88 zonas horarias únicas que conformarán su lista de selección.



function formatOffset($offset) { $hours = $offset / 3600; $remainder = $offset % 3600; $sign = $hours > 0 ? ''+'' : ''-''; $hour = (int) abs($hours); $minutes = (int) abs($remainder / 60); if ($hour == 0 AND $minutes == 0) { $sign = '' ''; } return $sign . str_pad($hour, 2, ''0'', STR_PAD_LEFT) .'':''. str_pad($minutes,2, ''0''); } $utc = new DateTimeZone(''UTC''); $dt = new DateTime(''now'', $utc); echo ''<select name="userTimeZone">''; foreach(DateTimeZone::listIdentifiers() as $tz) { $current_tz = new DateTimeZone($tz); $offset = $current_tz->getOffset($dt); $transition = $current_tz->getTransitions($dt->getTimestamp(), $dt->getTimestamp()); $abbr = $transition[0][''abbr'']; echo ''<option value="'' .$tz. ''">'' .$tz. '' ['' .$abbr. '' ''. formatOffset($offset). '']</option>''; } echo ''</select>'';

Lo anterior dará salida a todas las zonas horarias en el menú de selección con el siguiente formato:

<select name="userTimeZone"> <option value="America/Los_Angeles">America/Los_Angeles [PDT -7]</option> </select>