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. : )
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>
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With