Take the 2-minute tour ×

I am using NodaTime in an application, and I need the user to select their timezone from a dropdown list. I have the following soft requirements:

1) The list only contain choices that are reasonably valid for the present and near future for real places. Historical, obscure, and generic timezones should be filtered out.

2) The list should be sorted first by UTC offset, and then by timezone name. This hopefully puts them in an order that is meaningful for the user.

I've written the following code, which does indeed work, but doesn't have exactly what I'm after. The filter probably needs to be adjusted, and I'd rather have the offset represent the base (non-dst) offset, rather than the current offset.

Suggestions? Recommendations?

var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
var tzdb = DateTimeZoneProviders.Tzdb;
var list = from id in tzdb.Ids
           where id.Contains("/") && !id.StartsWith("etc", StringComparison.OrdinalIgnoreCase)
           let tz = tzdb[id]
           let offset = tz.GetOffsetFromUtc(now)
           orderby offset, id
           select new
               Id = id,
               DisplayValue = string.Format("({0}) {1}", offset.ToString("+HH:mm", null), id)

// ultimately we build a dropdown list, but for demo purposes you can just dump the results
foreach (var item in list)
share|improve this question
add comment

2 Answers

up vote 6 down vote accepted

Noda Time 1.1 has the zone.tab data, so you can now do the following:

/// <summary>
/// Returns a list of valid timezones as a dictionary, where the key is
/// the timezone id, and the value can be used for display.
/// </summary>
/// <param name="countryCode">
/// The two-letter country code to get timezones for.
/// Returns all timezones if null or empty.
/// </param>
public IDictionary<string, string> GetTimeZones(string countryCode)
    var now = SystemClock.Instance.Now;
    var tzdb = DateTimeZoneProviders.Tzdb;

    var list = 
        from location in TzdbDateTimeZoneSource.Default.ZoneLocations
        where string.IsNullOrEmpty(countryCode) ||
        let zoneId = location.ZoneId
        let tz = tzdb[zoneId]
        let offset = tz.GetZoneInterval(now).StandardOffset
        orderby offset, zoneId
        select new
            Id = zoneId,
            DisplayValue = string.Format("({0:+HH:mm}) {1}", offset, zoneId)

    return list.ToDictionary(x => x.Id, x => x.DisplayValue);

Alternative Approach

Instead of providing a drop down at all, you can use a map-based timezone picker.

enter image description here

share|improve this answer
add comment

Getting the standard offset is easy - tz.GetZoneInterval(now).StandardOffset. That will give you the "current" standard offset (it's possible for a zone to change over time).

The filtering may be appropriate for you - I wouldn't like to say for sure. It's certainly not ideal in that the IDs aren't really designed for display. Ideally you'd use the Unicode CLDR "example" places, but we don't have any CLDR integration on that front at the moment.

share|improve this answer
Is there some clean way to filter out historical timezones? The TZ database does have From and To dates that timezones are valid for. Does Noda expose this in any way? –  Matt Johnson Oct 25 '12 at 14:52
@MattJohnson: No - which bit of TZDB exposes that? I must confess I've never fully understood the format, but if it's something we can add, we may do so (though probably not for 1.0). (From and To are usually for particular rules within a time zone, and I thought the final rule always had a To of "max".) –  Jon Skeet Oct 25 '12 at 14:55
I stumbled upon this page which explains things fairly well. The Rule entries seem to have the data I would need. –  Matt Johnson Oct 25 '12 at 14:59
For sake of filtering, I guess I would be interested in removing any timezones that did not have a "max" rule, but had a final To date that had already passed. But I guess I am assuming that there is always at least one Rule per Zone, and I don't know if that is the case or not. –  Matt Johnson Oct 25 '12 at 15:04
@MattJohnson: Could you raise a feature request citing that web page, and giving Honolulu as an example? Currently we assume (in various places, actually) that time zones are perpetual... it sounds like we shouldn't. That could be, um, interesting. –  Jon Skeet Oct 25 '12 at 15:06
show 5 more comments

Your Answer


