wp_timezone_choice

The timeline below displays how wordpress function wp_timezone_choice has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.5

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities', true);
        load_textdomain('continents-cities', $mofile, $locale_loaded);
        $mo_loaded = true;
    }
    $tz_identifiers = timezone_identifiers_list();
    $zonen = array();
    foreach ($tz_identifiers as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents, true)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    // If this is a deprecated, but valid, timezone string, display it at the top of the list as-is.
    if (in_array($selected_zone, $tz_identifiers, true) === false && in_array($selected_zone, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC), true)) {
        $structure[] = '<option selected="selected" value="' . esc_attr($selected_zone) . '">' . esc_html($selected_zone) . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = implode('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return implode("\n", $structure);
}

WordPress Version: 1.1

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile, $locale_loaded);
        $mo_loaded = true;
    }
    $tz_identifiers = timezone_identifiers_list();
    $zonen = array();
    foreach ($tz_identifiers as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents, true)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    // If this is a deprecated, but valid, timezone string, display it at the top of the list as-is.
    if (in_array($selected_zone, $tz_identifiers, true) === false && in_array($selected_zone, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC), true)) {
        $structure[] = '<option selected="selected" value="' . esc_attr($selected_zone) . '">' . esc_html($selected_zone) . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = implode('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return implode("\n", $structure);
}

WordPress Version: 6.1

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $tz_identifiers = timezone_identifiers_list();
    $zonen = array();
    foreach ($tz_identifiers as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents, true)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    // If this is a deprecated, but valid, timezone string, display it at the top of the list as-is.
    if (in_array($selected_zone, $tz_identifiers, true) === false && in_array($selected_zone, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC), true)) {
        $structure[] = '<option selected="selected" value="' . esc_attr($selected_zone) . '">' . esc_html($selected_zone) . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = implode('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return implode("\n", $structure);
}

WordPress Version: 5.6

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents, true)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = implode('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return implode("\n", $structure);
}

WordPress Version: 5.5

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents, true)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 5.4

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @staticvar bool $mo_loaded
 * @staticvar string $locale_loaded
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later.
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later.
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen).
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group.
            // Continent optgroup.
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value.
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value.
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value.
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup.
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC.
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets.
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 5.1

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @staticvar bool $mo_loaded
 * @staticvar string $locale_loaded
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        // phpcs:disable WordPress.WP.I18n.LowLevelTranslationFunction,WordPress.WP.I18n.NonSingularStringLiteralText
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
        // phpcs:enable
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen)
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group
            // Continent optgroup
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . '</option>';
        // Close continent optgroup
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . '</option>';
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 4.7

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 * @since 4.7.0 Added the `$locale` parameter.
 *
 * @staticvar bool $mo_loaded
 * @staticvar string $locale_loaded
 *
 * @param string $selected_zone Selected timezone.
 * @param string $locale        Optional. Locale to load the timezones in. Default current site locale.
 * @return string
 */
function wp_timezone_choice($selected_zone, $locale = null)
{
    static $mo_loaded = false, $locale_loaded = null;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities.
    if (!$mo_loaded || $locale !== $locale_loaded) {
        $locale_loaded = $locale ? $locale : get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale_loaded . '.mo';
        unload_textdomain('continents-cities');
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen)
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group
            // Continent optgroup
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>";
        // Close continent optgroup
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . "</option>";
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 4.3

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 *
 * @staticvar bool $mo_loaded
 *
 * @param string $selected_zone Selected timezone.
 * @return string
 */
function wp_timezone_choice($selected_zone)
{
    static $mo_loaded = false;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities
    if (!$mo_loaded) {
        $locale = get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen)
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group
            // Continent optgroup
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>";
        // Close continent optgroup
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . "</option>";
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 4.0

/**
 * Gives a nicely-formatted list of timezone strings.
 *
 * @since 2.9.0
 *
 * @param string $selected_zone Selected timezone.
 * @return string
 */
function wp_timezone_choice($selected_zone)
{
    static $mo_loaded = false;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities
    if (!$mo_loaded) {
        $locale = get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen)
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group
            // Continent optgroup
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>";
        // Close continent optgroup
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . "</option>";
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}

WordPress Version: 3.7

/**
 * Gives a nicely formatted list of timezone strings.
 *
 * @since 2.9.0
 *
 * @param string $selected_zone Selected Zone
 * @return string
 */
function wp_timezone_choice($selected_zone)
{
    static $mo_loaded = false;
    $continents = array('Africa', 'America', 'Antarctica', 'Arctic', 'Asia', 'Atlantic', 'Australia', 'Europe', 'Indian', 'Pacific');
    // Load translations for continents and cities
    if (!$mo_loaded) {
        $locale = get_locale();
        $mofile = WP_LANG_DIR . '/continents-cities-' . $locale . '.mo';
        load_textdomain('continents-cities', $mofile);
        $mo_loaded = true;
    }
    $zonen = array();
    foreach (timezone_identifiers_list() as $zone) {
        $zone = explode('/', $zone);
        if (!in_array($zone[0], $continents)) {
            continue;
        }
        // This determines what gets set and translated - we don't translate Etc/* strings here, they are done later
        $exists = array(0 => isset($zone[0]) && $zone[0], 1 => isset($zone[1]) && $zone[1], 2 => isset($zone[2]) && $zone[2]);
        $exists[3] = $exists[0] && 'Etc' !== $zone[0];
        $exists[4] = $exists[1] && $exists[3];
        $exists[5] = $exists[2] && $exists[3];
        $zonen[] = array('continent' => $exists[0] ? $zone[0] : '', 'city' => $exists[1] ? $zone[1] : '', 'subcity' => $exists[2] ? $zone[2] : '', 't_continent' => $exists[3] ? translate(str_replace('_', ' ', $zone[0]), 'continents-cities') : '', 't_city' => $exists[4] ? translate(str_replace('_', ' ', $zone[1]), 'continents-cities') : '', 't_subcity' => $exists[5] ? translate(str_replace('_', ' ', $zone[2]), 'continents-cities') : '');
    }
    usort($zonen, '_wp_timezone_choice_usort_callback');
    $structure = array();
    if (empty($selected_zone)) {
        $structure[] = '<option selected="selected" value="">' . __('Select a city') . '</option>';
    }
    foreach ($zonen as $key => $zone) {
        // Build value in an array to join later
        $value = array($zone['continent']);
        if (empty($zone['city'])) {
            // It's at the continent level (generally won't happen)
            $display = $zone['t_continent'];
        } else {
            // It's inside a continent group
            // Continent optgroup
            if (!isset($zonen[$key - 1]) || $zonen[$key - 1]['continent'] !== $zone['continent']) {
                $label = $zone['t_continent'];
                $structure[] = '<optgroup label="' . esc_attr($label) . '">';
            }
            // Add the city to the value
            $value[] = $zone['city'];
            $display = $zone['t_city'];
            if (!empty($zone['subcity'])) {
                // Add the subcity to the value
                $value[] = $zone['subcity'];
                $display .= ' - ' . $zone['t_subcity'];
            }
        }
        // Build the value
        $value = join('/', $value);
        $selected = '';
        if ($value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($value) . '">' . esc_html($display) . "</option>";
        // Close continent optgroup
        if (!empty($zone['city']) && (!isset($zonen[$key + 1]) || isset($zonen[$key + 1]) && $zonen[$key + 1]['continent'] !== $zone['continent'])) {
            $structure[] = '</optgroup>';
        }
    }
    // Do UTC
    $structure[] = '<optgroup label="' . esc_attr__('UTC') . '">';
    $selected = '';
    if ('UTC' === $selected_zone) {
        $selected = 'selected="selected" ';
    }
    $structure[] = '<option ' . $selected . 'value="' . esc_attr('UTC') . '">' . __('UTC') . '</option>';
    $structure[] = '</optgroup>';
    // Do manual UTC offsets
    $structure[] = '<optgroup label="' . esc_attr__('Manual Offsets') . '">';
    $offset_range = array(-12, -11.5, -11, -10.5, -10, -9.5, -9, -8.5, -8, -7.5, -7, -6.5, -6, -5.5, -5, -4.5, -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5, 5.5, 5.75, 6, 6.5, 7, 7.5, 8, 8.5, 8.75, 9, 9.5, 10, 10.5, 11, 11.5, 12, 12.75, 13, 13.75, 14);
    foreach ($offset_range as $offset) {
        if (0 <= $offset) {
            $offset_name = '+' . $offset;
        } else {
            $offset_name = (string) $offset;
        }
        $offset_value = $offset_name;
        $offset_name = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $offset_name);
        $offset_name = 'UTC' . $offset_name;
        $offset_value = 'UTC' . $offset_value;
        $selected = '';
        if ($offset_value === $selected_zone) {
            $selected = 'selected="selected" ';
        }
        $structure[] = '<option ' . $selected . 'value="' . esc_attr($offset_value) . '">' . esc_html($offset_name) . "</option>";
    }
    $structure[] = '</optgroup>';
    return join("\n", $structure);
}