Presenting a list of Timezones to the user


 

I first got into timezones when I working on an calendar app which displayed various times of day which are pertinent to Jewish daily life. The app would display calculated times which of course would differ based on the timezone of the given location. As I investigated into timezones, I found them to be fairly complicated. Not all timezones are even on the hour…some are at 30 minute offsets, some at 45 minutes, and historically there have been even stranger offsets than that.

To make matters worse, there’s the whole issue of Daylight Saving Time. Apparently some places have it some don’t. Some countries have a set date for DST, some pick a new one each year depending on circumstances. And of course, DST does not mean only adding one hour. 

My research led me to what is “colloquially” known as the “Olson” database. The Olson database is a de facto standard in the world of keeping time. The most recognizable part of the way timezones are identified is the {Continent}/{Location} signature. For example, the timezone that I am in is called “America/New_York”. The Olson database tracks all historical information about timezones back at least until 1970. By timezone information, this also means transitions for DST and the GMT offset for both standard time and DST.

The best part of all of this, is that PHP 5 and up has built in support for understanding Olson timezones. This means that you all you need is the timezone id (the tzid), and you can have PHP worry about all the timezone and DST calculations.

Recently, I was working on another app which required members to select a timezone. The app is written on top of Expression Engine which contains a full blown membership system. The membership system includes a timezone setting. Let’s take a quick look at the what this look like:

Selecting a timezone in Expression Engine

Selecting a timezone in Expression Engine

Notice the checkbox that says “Daylight Saving Time”? This means that the user has to remember, every year, to select that checkbox when DST happens. Not very fun. Expression Engine is written in PHP 4, and the authors intend to keep that, stubbornly, for as long as possible.

I’m not here to wrant on Expression Engine (that’s for another time), but either way, this would not suit my purposes. I can’t rely on users remembering to “spring forward” when they have to.

The alternative is to provide a list based on the Olson database. The problem is that, as of this post, their are 560 tzid’s in the database, and they are not “friendly” nor recognizable to anybody but geeks. 

I started looking around on the Interwebs trying to see what other people came up with. There was a question on Stackoverflow.com which hit the nail on the head, but anybody answering the question missed the point completely.

Eventually I realized that I must present a list similar to Expression Engine’s list, but which has the values as Olson tzid’s. The first step was to clean up the list a little. Much of the information is redundant, and only there for historical purposes. For instance, until 2006, much of Indiana did not observe DST. After 2006, however, the story changed. This explains why there are so many Olson tzid’s with Indiana in them. However, for all practical purposes, they’re the same.

The question is, what defines them as the same? I determined the best way would be to look at the DST transition date (if applicable), and the resulting offsets and compare them. Fortunately, PHP has a function that does this…timezone_transitions_get().

My idea was to pull in all the timezones and their transistions into excel and sort them by offset, and transition dates to identify which tzids are similar. After that, to figure out a friendly name to call them.

Doing more research I found somebody made a spreadsheet which tried to map Windows timezone names to Olson tzid’s. I used this a base reference for the names I chose, although I found not all the data in that spreadsheet was accurate (one day I will submit my changes to the author). Some timezones I had to come up with my own names like “America/Havana” which has different rules for any place in its timezone. I decided to call this (GMT-05:00) Cuba for lack of anything else.

In the end, I came up with a list of about 80 or so timezones, and I’m somewhat proud of my results:

Here is the list:

<option value="Pacific/Midway">(GMT-11:00) Midway Island, Samoa</option>
<option value="America/Adak">(GMT-10:00) Hawaii-Aleutian</option>
<option value="Etc/GMT+10">(GMT-10:00) Hawaii</option>
<option value="Pacific/Marquesas">(GMT-09:30) Marquesas Islands</option>
<option value="Pacific/Gambier">(GMT-09:00) Gambier Islands</option>
<option value="America/Anchorage">(GMT-09:00) Alaska</option>
<option value="America/Ensenada">(GMT-08:00) Tijuana, Baja California</option>
<option value="Etc/GMT+8">(GMT-08:00) Pitcairn Islands</option>
<option value="America/Los_Angeles">(GMT-08:00) Pacific Time (US & Canada)</option>
<option value="America/Denver">(GMT-07:00) Mountain Time (US & Canada)</option>
<option value="America/Chihuahua">(GMT-07:00) Chihuahua, La Paz, Mazatlan</option>
<option value="America/Dawson_Creek">(GMT-07:00) Arizona</option>
<option value="America/Belize">(GMT-06:00) Saskatchewan, Central America</option>
<option value="America/Cancun">(GMT-06:00) Guadalajara, Mexico City, Monterrey</option>
<option value="Chile/EasterIsland">(GMT-06:00) Easter Island</option>
<option value="America/Chicago">(GMT-06:00) Central Time (US & Canada)</option>
<option value="America/New_York">(GMT-05:00) Eastern Time (US & Canada)</option>
<option value="America/Havana">(GMT-05:00) Cuba</option>
<option value="America/Bogota">(GMT-05:00) Bogota, Lima, Quito, Rio Branco</option>
<option value="America/Caracas">(GMT-04:30) Caracas</option>
<option value="America/Santiago">(GMT-04:00) Santiago</option>
<option value="America/La_Paz">(GMT-04:00) La Paz</option>
<option value="Atlantic/Stanley">(GMT-04:00) Faukland Islands</option>
<option value="America/Campo_Grande">(GMT-04:00) Brazil</option>
<option value="America/Goose_Bay">(GMT-04:00) Atlantic Time (Goose Bay)</option>
<option value="America/Glace_Bay">(GMT-04:00) Atlantic Time (Canada)</option>
<option value="America/St_Johns">(GMT-03:30) Newfoundland</option>
<option value="America/Araguaina">(GMT-03:00) UTC-3</option>
<option value="America/Montevideo">(GMT-03:00) Montevideo</option>
<option value="America/Miquelon">(GMT-03:00) Miquelon, St. Pierre</option>
<option value="America/Godthab">(GMT-03:00) Greenland</option>
<option value="America/Argentina/Buenos_Aires">(GMT-03:00) Buenos Aires</option>
<option value="America/Sao_Paulo">(GMT-03:00) Brasilia</option>
<option value="America/Noronha">(GMT-02:00) Mid-Atlantic</option>
<option value="Atlantic/Cape_Verde">(GMT-01:00) Cape Verde Is.</option>
<option value="Atlantic/Azores">(GMT-01:00) Azores</option>
<option value="Europe/Belfast">(GMT) Greenwich Mean Time : Belfast</option>
<option value="Europe/Dublin">(GMT) Greenwich Mean Time : Dublin</option>
<option value="Europe/Lisbon">(GMT) Greenwich Mean Time : Lisbon</option>
<option value="Europe/London">(GMT) Greenwich Mean Time : London</option>
<option value="Africa/Abidjan">(GMT) Monrovia, Reykjavik</option>
<option value="Europe/Amsterdam">(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna</option>
<option value="Europe/Belgrade">(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague</option>
<option value="Europe/Brussels">(GMT+01:00) Brussels, Copenhagen, Madrid, Paris</option>
<option value="Africa/Algiers">(GMT+01:00) West Central Africa</option>
<option value="Africa/Windhoek">(GMT+01:00) Windhoek</option>
<option value="Asia/Beirut">(GMT+02:00) Beirut</option>
<option value="Africa/Cairo">(GMT+02:00) Cairo</option>
<option value="Asia/Gaza">(GMT+02:00) Gaza</option>
<option value="Africa/Blantyre">(GMT+02:00) Harare, Pretoria</option>
<option value="Asia/Jerusalem">(GMT+02:00) Jerusalem</option>
<option value="Europe/Minsk">(GMT+02:00) Minsk</option>
<option value="Asia/Damascus">(GMT+02:00) Syria</option>
<option value="Europe/Moscow">(GMT+03:00) Moscow, St. Petersburg, Volgograd</option>
<option value="Africa/Addis_Ababa">(GMT+03:00) Nairobi</option>
<option value="Asia/Tehran">(GMT+03:30) Tehran</option>
<option value="Asia/Dubai">(GMT+04:00) Abu Dhabi, Muscat</option>
<option value="Asia/Yerevan">(GMT+04:00) Yerevan</option>
<option value="Asia/Kabul">(GMT+04:30) Kabul</option>
<option value="Asia/Yekaterinburg">(GMT+05:00) Ekaterinburg</option>
<option value="Asia/Tashkent">(GMT+05:00) Tashkent</option>
<option value="Asia/Kolkata">(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi</option>
<option value="Asia/Katmandu">(GMT+05:45) Kathmandu</option>
<option value="Asia/Dhaka">(GMT+06:00) Astana, Dhaka</option>
<option value="Asia/Novosibirsk">(GMT+06:00) Novosibirsk</option>
<option value="Asia/Rangoon">(GMT+06:30) Yangon (Rangoon)</option>
<option value="Asia/Bangkok">(GMT+07:00) Bangkok, Hanoi, Jakarta</option>
<option value="Asia/Krasnoyarsk">(GMT+07:00) Krasnoyarsk</option>
<option value="Asia/Hong_Kong">(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi</option>
<option value="Asia/Irkutsk">(GMT+08:00) Irkutsk, Ulaan Bataar</option>
<option value="Australia/Perth">(GMT+08:00) Perth</option>
<option value="Australia/Eucla">(GMT+08:45) Eucla</option>
<option value="Asia/Tokyo">(GMT+09:00) Osaka, Sapporo, Tokyo</option>
<option value="Asia/Seoul">(GMT+09:00) Seoul</option>
<option value="Asia/Yakutsk">(GMT+09:00) Yakutsk</option>
<option value="Australia/Adelaide">(GMT+09:30) Adelaide</option>
<option value="Australia/Darwin">(GMT+09:30) Darwin</option>
<option value="Australia/Brisbane">(GMT+10:00) Brisbane</option>
<option value="Australia/Hobart">(GMT+10:00) Hobart</option>
<option value="Asia/Vladivostok">(GMT+10:00) Vladivostok</option>
<option value="Australia/Lord_Howe">(GMT+10:30) Lord Howe Island</option>
<option value="Etc/GMT-11">(GMT+11:00) Solomon Is., New Caledonia</option>
<option value="Asia/Magadan">(GMT+11:00) Magadan</option>
<option value="Pacific/Norfolk">(GMT+11:30) Norfolk Island</option>
<option value="Asia/Anadyr">(GMT+12:00) Anadyr, Kamchatka</option>
<option value="Pacific/Auckland">(GMT+12:00) Auckland, Wellington</option>
<option value="Etc/GMT-12">(GMT+12:00) Fiji, Kamchatka, Marshall Is.</option>
<option value="Pacific/Chatham">(GMT+12:45) Chatham Islands</option>
<option value="Pacific/Tongatapu">(GMT+13:00) Nuku'alofa</option>
<option value="Pacific/Kiritimati">(GMT+14:00) Kiritimati</option>

If anybody can offer any improvements to this or a different suggestion altogether, that would be great.

, , ,

  1. #1 by ysth at March 13th, 2009

    Nice work. One clarification: Olson timezones have historical changes back through much earlier than 1970, but they don’t create distinct timezones when the only differences were earlier than 1970.

  2. #2 by David M at May 25th, 2009

    This is a bad way to do it because you’re mapping “static” timezones (e.g. (GMT)) to geographical locations (e.g. Europe/London) which have “dyanamic” times. PHP will use the time of the location which will change throughout the year when daylight savings comes into effect. Europe/London will be GMT for 6 months but for the other 6 months it will will be BST, which is GMT+1.

    For your list to be correct you have to use the actual “static” identifiers i.e. GMT, GMT+1, etc, as the option values.

    It is also extra work for the user who will need to switch DST on/off at the appropriate time. If you do it the way I did at http://blog.boxedice.com/2009/03/21/handling-timezone-conversion-with-php-datetime/ then that will be handled automatically.

    • #3 by Avi at May 25th, 2009

      I think you misunderstood my post. I’m mapping the “friendly name” which people recognize, to the Olson name which PHP can handle. So somebody on the east coast of the US will see (GMT-05:00) Eastern Time (US & Canada) and recognize that as their timezone. Meanwhile they get the “dynamic” identifier America/New_York stored in the database. Of course now their DST will be handled automatically for them.

      • #4 by David M at May 25th, 2009

        I understand that if the user wants GMT -5 and they select that from your drop menu as “(GMT-05:00) Eastern Time (US & Canada)”, that will map to “America/New_York”. However, New York is not always GMT -5. For example, it is currently GMT -4. This means your mapping is incorrect.

        • #5 by Avi at May 25th, 2009

          In my experience people do not think in DST terms. People on the East Coast of the united states do not think of their time in the summer as GMT -4…the think of it as GMT -5 plus one extra hour.
          Either way, the important part of my list here is the friendly names…not the GMT offsets. The GMT offsets just provide a convenient way to list the timezones in an order that makes sense.
          The important part is that the user can identify their timezone in a way that makes sense to them, and I can store it in a way that makes sense to me.

  3. #6 by User_Friendly at July 9th, 2009

    Very Good work! I was looking throughout the net for TZ lists and Your beats all I’ve found! Thanks a lot!

  4. #7 by Robert Gunther at July 15th, 2009

    I like your list, will be using it on our website to allow users to set their timezone.

  5. #8 by DC at September 19th, 2009

    Excellent. I’ve gone crazy looking for a similar human-friendly list. This is the only one so far.

  6. #9 by Charles Himmer at October 7th, 2009

    Thanks for posting this. I was looking all over for this and figured somebody had done this.

  7. #10 by John at November 29th, 2009

    Fantastic! Been searching for weeks for something like this. After a bunch of different options, I’ll see if I just use this one. If only you could automatically detect the user’s setting in Javascript. Presently, I only find selection boxes which have values like “+01:00, 1″ which can be automatically set by JS…

    Thanks
    John

  8. #11 by chris at February 4th, 2010

    This is great, but since it is statically generated, it must be manually updated in the future as boundaries may change. What would be more interesting is a script that can generate the output you created.

  9. #12 by Aris at March 6th, 2010

    Thanks! I too was looking for a shortened “human-friendly” list that’s similar to the drop-down in Google Calendar and this is the closest one.

(will not be published)
  1. No trackbacks yet.