List of time zones in <select> element

Hello :wave:

I am using tzdata which allows me to retrieve a list of timezone names:

Tzdata.zone_list()

In most timezone pickers, we can see something like:

(UTC +11:00) Australia/Sydney
(UTC +01:00) Europe/Amsterdam

How can I get the timezone offset from UTC/GMT for each of the time zones?

I can see that there is a periods/1 and periods_for_time/3 function, but they work with a specific moment in time. So not sure how to approach it.

Any recommendations?

I don’t see a straight forward way, but I’m also not convinced its a good idea (including as a consumer). Why? With DST the UTC offset changes. Are you displaying the standard offset or the summer offset? If I select “Australia/Sydney” am I actually selecting the offset of UTC +11:00 or the zone Australia/Sydney.

I appreciate this may not be the interpretation of everyone. But in my opinion, use the zone name only. And to simplify, as a user, I would prefer to use the data from Tzdata.zone_lists_grouped/0 and group the data by region.

2 Likes

It looks like in this case the offset closest to UTC is chosen. E.g. Belgium is shown as +1 (winter time) and not +2 (summer time).

Example of date pickers displaying offsets: Windows, Android, Google Calendar (and probably 90+% of other applications).

Note that on iPhones the offset is not shown but they do not have a picker containing a list of time zones to select; they work with an input field for searching based on user text input.

The pros of having UTC offset values:

  • the UTC offset is used as ordering for the time zones. If instead the order is alphabetical, and the user’s city is not included in a time zone name, I think it will be harder to find the right timezone for the user. It’s one complementary information to help the user select the right option; why not use it?

  • if the user’s city lays between two cities shown, which should he choose? Hopefully he knows his offset which can help him select (he might just know the right time zone name, but if not, he might know the offset at least).

  • most users are used to choose the time zone that way. As mentioned above, this is how Windows/Android/Google Calendar and most applications choose to work; I’m pretty sure they have thought through this, I believe in Google :smiley:

All the above said, I should find the time zone automatically with JS in any case.

The time zone. The label for the field is “Select your time zone” or something in the like, which clarifies that.

There are timezones like Florida, which are all year in DST, effectively never experiencing their actual UTC offset. The whole EU is currently on the way to scrap DST switching leaving member states to decide if they want to stay on DST or non-DST.

That’s interesting. I can’t remember ever choosing my timezone by UTC offset. It’s always been timezone names where I had to do so.

1 Like

If you follow the approach of “offset + timezone name” then as a user I would prefer “Australia/Sydney (currently UTC +11:00)”.

I don’t actually believe most users understand time zones, offset, DST and so on. My personal view is that you would say something like:

The current time for you is __________

And the drop down shows the time in different zones that I can select. And then interpret the zone name from that.

In my view using offsets and zone names is, for the average consumer, making technology their problem.

1 Like

And at best give the user the last choice, as it’s not just about what time it is right now, but e.g. also when does time change (like going on/off DST).

This speaks in part to the whole challenge off “who you are, where you are from, where you are now, what preference you choose…”

An example: I’m a Hertz customer. My profile is clear, my address is Singapore, my nationality is Australian. But whenever I am in Germany I get the German translation for Hertz. They must be using IP address detection - but thats the lowest of the low. They have the tracking cookie for me - why do they do that!!!

For a registered user, follow their preferences. For a user that provides an Accepts-Language header use the -u-tz-zone if provided. Do everything you can to empower the user to define what they want.

But for goodness sake, assuming that a typical consumer knows that UTC means let alone UTC + 11:00 is a really poor and I might say lazy experience. I appreciate this is the common strategy. But even as an informed consumer I find it confusing.

I believe (and recognise this may not be the common view) that there are already two good UX choices:

  1. Use the “You prefer the times you see on this site be the time in _________ (some location)” or
  2. “Please select the current time that best reflects your preference: -________”

PS: This is a rant about the current state of UX in general, not about the original posters question or intent.

2 Likes

I have to disagree with that only for one reason, which I mentioned before. The problem is that for many users, you have to kind of know about time zones anyway => because the time zone names don’t include every city.

Consider a user knows nothing about time zones, and he sees a list showing continents/cities, then he might as well report a bug that his city is not included.

So there is no perfect solution for a list; because of that, my logic is: just display all available information (one of the offsets + timezone) for easing the right pick.

Now for the input fields you suggest, again, what city does he have to enter? If I live in a town, I’ll enter my town, which will lead to no results.

1 Like

Its a very good point and I apologies if I seem argumentative. Its an issue on the web and in apps in general. Its also why I suggested the 2nd approach:

“Please select the current time that best reflects your preference: -________”

Which might be poorly written but it intended to say: based upon this list, which time most closely matches the time you expect to see in this app.

The language is tricky for the reasons i explained in my example. I’m Australian, I live in Singapore, I might be visiting France. Which timezone do I want the time in? Show me a list of the current time in different zones and I’ll tell you which one I want.

Its not perfect either, I know. But I would still prefer something this says:

Please select the time in the zone you prefer. Please select the time zone i which the time your prefer is the same as the time in: 
<time zone list>

But again, I have no perfect answer. I’m just saying that UTC +11:00 Australia/Sydney" is to me more ambiguous that "Standard timezone UTC +11:00orAustralia/Sydney`. And as I’m sure you know there are zone names that are synonymous that cover a larger range of cities that might also help.

I probably sound argumentative and thats not my intent. I’m just saying that as a consumer, who moves around a lot of timezones, and lives in a country thats not my nationality, this issue is a complete pain in the a**s every day and I think as an industry we can do better.

No need. We are argumenting not arguing :smiley: and I can’t thank you enough for all the support you bring on this forum. I knew when writing that initial post that it will lead to a question more related to UX than Elixir. Note in any case that it is quite a subjective topic, and thus it might still be interesting to see a function returning the different offsets for a specific time zone.

If I understood it’s a list with the current time in different time zones. I see only one problem, is that time moves. So if the user takes a 30 minutes break from the screen and comes back to the form, these values need to have been updated. This can be done using JS I guess, but not sure what happens when I update the <option> elements every minute while the user has clicked on the select element. I guess I can have an event listener for onfocus/onblur events to disable the time updates when the user opens the select. Oh, but while he was on a 30 minutes break, somewhere in the world there was a DST switch, oops :stuck_out_tongue:

Time zones are a weird topic.

To get the values you want from Tzdata I would go this way.

iex(17)> d = DateTime.utc_now()                    
~U[2020-01-26 09:06:46.250947Z]                    
iex(18)> iso_days = Calendar.ISO.naive_datetime_to_iso_days(d.year, d.month, d.day, d.hour, d.minute, d.second, d.microsecond)
{737815, {32806250947, 86400000000}}
iex(19)> Tzdata.TimeZoneDatabase.time_zone_period_from_utc_iso_days(iso_days, "Europe/Berlin")        {:ok,
 %{
   from_wall: ~N[2019-10-27 02:00:00],
   std_offset: 0,
   until_wall: ~N[2020-03-29 02:00:00],
   utc_offset: 3600,
   zone_abbr: "CET"
 }}

This gives you the utc_offset and std_offset (DST) for the current point in time. Both values could be change over time. For utc_offset it is not so usually but it can happen. @LostKobrakai mentioned this in his comment about the situation in the EU.

For me it is also weird to select a time zone by utc offset, because that will group many countries with different rules for the DST. In some edge cases it can be difficult to say if you in a zone with UTC -11 or UTC +13.

For a better user experience in your time zone selector you could provide more cities. Data for that approach can be found at http://www.geonames.org/export/
With this data you can build something like this https://www.timeanddate.com/worldclock/converter.html

And if you chose to go the “add more names” route you could use TzWorld.timezone_at/1 to return the timezone name of that city. See tz_world. It uses the cool timezone boundary builder data.

Here’s one approach to letting users select a locale like “America/New_York”:

  def locale_list do
    now = DateTime.utc_now()

    Tzdata.zone_list()
    |> Enum.map(fn zone ->
      tzinfo = Timex.Timezone.get(zone, now)
      offset = Timex.TimezoneInfo.format_offset(tzinfo) # added in v3.78
      label = "#{tzinfo.full_name} - #{tzinfo.abbreviation} (#{offset})"

      {tzinfo.full_name, label}
    end)
    |> Enum.uniq()
  end

This outputs a list of values like:

[
  {"Africa/Abidjan", "Africa/Abidjan - GMT (+00:00:00)"},
  ...
]

If you wanted to sort these by offset, you could use the value of Timex.Timezone.total_offset(tzinfo), but I think alphabetical makes more sense, since the locales are grouped by region.

In the template, I think an <input> with a <datalist> is better than a <select>, as it lets users type and use autocomplete, which in my testing will match any substring, like “africa” or “abidjan” or “gmt” or “05:30” (although exactly how that works is up to the browser). This means that if somebody knows their offset and wants to type it, it can narrow to the locales that match.

<input list="locales" name="user-locale" id="user-locale" value={@user.tz_locale}>
<datalist id="locales">
  <%= for {fullname, label} <- @locales do %>
    <option value={ fullname } >
      <%= label %>
    </option>
  <% end %>
</datalist>

It’s still not as nice as being able to type the name of whatever town you live in, big or small, but the answers above could help you do that.

Oh yeah, and Intl.DateTimeFormat().resolvedOptions().timeZone in JS can get the user’s locale from the browser - "DateTimeFormat" | Can I use... Support tables for HTML5, CSS3, etc

So you can add a button to autofill:

<button phx-hook="AutofillLocale">Autofill</button>

…and set up a hook to do it:

Hooks.AutofillLocale = {
  mounted() {
    this.el.addEventListener("click", e => {
      let locale = Intl.DateTimeFormat().resolvedOptions().timeZone
      document.getElementById("user-locale").value = locale
    })
  }
}

Here’s a quick demo:

locale_picker

2 Likes