Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to populate a <SELECT> box with TimeZones

Tags:

php

I need to display a timezone selector as a user control, which always seems easier than it really is. Internally, I store everything with a DateTimeZone Identifier, as that seems to be the smartest way to have the level of accuracy I need, as this project bridges real-world times as it is tied to terrestrial media.

What I don't want to do is present a select box with 300+ time zones, nor do I want to create faked timezone offsets with something like 'UTC-8' (which loses not only DST info, but the actual dates that the DST falls on).

In the end, I'll need a select with options containing the proper TZD Identifiers, something like this (the bracketed #s aren't necessary, just for potential end-user illustration):

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

Does anyone have any pointers for building this list? All of the solutions I've googled have been problematic in one way or another.


I've added a bounty in case that might entice somebody to share a nicer answer with us. : )

like image 637
John Green Avatar asked Aug 03 '11 04:08

John Green


2 Answers

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>'; 

The above will output all of the timezones in select menu with the following format:

<select name="userTimeZone"> <option value="America/Los_Angeles">America/Los_Angeles [PDT -7]</option> </select> 
like image 135
Zubair1 Avatar answered Oct 14 '22 15:10

Zubair1


My solution:

To avoid a huge timezone list, have the user select the country first, then use that information to populate a list of timezones.

File 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> 

file 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;  

I hope it helps you :)

like image 26
Pedro Lobito Avatar answered Oct 14 '22 15:10

Pedro Lobito