Generar lista de zonas horarias de forma dinámica en PHP

Se genera la lista de zonas horarias de forma dinámica, y por lo tanto se actualiza automáticamente cuando se podrían cambiar las zonas horarias (en PHP).

  • Nombre de zona horaria son algo así:  "America/Lima" y ahora se convierte en America, Lima
  • Las zonas horarias se clasifican en offset y nombre
function timezone_list() {
    static $timezones = null;
 
    if ($timezones === null) {
        $timezones = [];
        $offsets = [];
        $now = new DateTime();
 
        foreach (DateTimeZone::listIdentifiers() as $timezone) {
            $now->setTimezone(new DateTimeZone($timezone));
            $offsets[] = $offset = $now->getOffset();
            $timezones[$timezone] = '(' . format_GMT_offset($offset) . ') ' . format_timezone_name($timezone);
        }
 
        array_multisort($offsets, $timezones);
    }
 
    return $timezones;
}
 
function format_GMT_offset($offset) {
    $hours = intval($offset / 3600);
    $minutes = abs(intval($offset % 3600 / 60));
    return 'GMT' . ($offset ? sprintf('%+03d:%02d', $hours, $minutes) : '');
}
 
function format_timezone_name($name) {
    $name = str_replace('/', ', ', $name);
    $name = str_replace('_', ' ', $name);
    $name = str_replace('St ', 'St. ', $name);
    return $name;
}
 
// Uso
$timezone = timezone_list();
echo '<pre>';
    print_r($timezone);
echo '</pre>';

Aquí es un ejemplo de la salida:

Array
(
    [Pacific/Midway]    => (GMT-11:00) Pacific, Midway
    [Pacific/Niue]      => (GMT-11:00) Pacific, Niue
    [Pacific/Pago_Pago] => (GMT-11:00) Pacific, Pago Pago
    [America/Adak]      => (GMT-10:00) America, Adak
    [Pacific/Honolulu]  => (GMT-10:00) Pacific, Honolulu
    [Pacific/Johnston]  => (GMT-10:00) Pacific, Johnston
    [Pacific/Rarotonga] => (GMT-10:00) Pacific, Rarotonga
    [Pacific/Tahiti]    => (GMT-10:00) Pacific, Tahiti
    [Pacific/Marquesas] => (GMT-09:30) Pacific, Marquesas
    [America/Anchorage] => (GMT-09:00) America, Anchorage
    [America/Juneau]    => (GMT-08:00) America, Juneau
    [America/Metlakatla] => (GMT-08:00) America, Metlakatla
    [America/Nome]      => (GMT-08:00) America, Nome
    [America/Sitka]     => (GMT-08:00) America, Sitka
    [America/Yakutat]   => (GMT-08:00) America, Yakutat
    [Pacific/Pitcairn]  => (GMT-08:00) Pacific, Pitcairn
    [America/Creston]   => (GMT-07:00) America, Creston
    [America/Dawson]    => (GMT-07:00) America, Dawson
    ...
)

 

Para ir a la página oficial: http://php.net/manual/es/timezones.php