How to Change the Timezones List in Drupal

Recently I did some work related to change the user timezone listing on user registration and edit forms of Drupal. The work included altering the registration form as well as the user edit form. Here is the code that I used for that.

/**
* Implements hook_form_FORM_ID_alter().
*/

function CUSTOM_MODULE_form_user_profile_form_alter(&$form, $form_state) {
  if (isset($form['timezone']['timezone'])) {
    $form['timezone']['timezone']['#options'] = _get_timezone_list();
  }
}

/**
* Implements hook_form_FORM_ID_alter().
*/

function CUSTOM_MODULE_form_user_register_form_alter(&$form, $form_state) {
  CUSTOM_MODULE_form_user_profile_form_alter($form, $form_state);
}

Now we add the callback with format times and time differences.

function _get_timezone_list(){
    $list = DateTimeZone::listAbbreviations();
    $idents = DateTimeZone::listIdentifiers();
    $data = $offset = $added = array();
    foreach ($list as $abbr => $info) {
        foreach ($info as $zone) {
            if ( ! empty($zone['timezone_id'])
                AND
                ! in_array($zone['timezone_id'], $added)
                AND 
                  in_array($zone['timezone_id'], $idents)) {
                $z = new DateTimeZone($zone['timezone_id']);
                $c = new DateTime(null, $z);
                $zone['time'] = $c->format('H:i a');
                $data[] = $zone;
                $offset[] = $z->getOffset($c);
                $added[] = $zone['timezone_id'];
            }
        }
    }
    array_multisort($offset, SORT_ASC, $data);
    $options = array();
    foreach ($data as $key => $row) {
        $options[$row['timezone_id']] = $row['time'] . ' - '
                                        . _format_offset($row['offset']) 
                                        . ' ' . $row['timezone_id'];
    }
    return $options;
    // now you can use $options;
}

function _format_offset($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 'GMT' . $sign . str_pad($hour, 2, '0', STR_PAD_LEFT) 
                .':'. str_pad($minutes,2, '0');
}