2012-10-24 1 views
14

Ich verwende NodaTime in einer Anwendung, und ich brauche den Benutzer ihre Zeitzone aus einer Dropdown-Liste auswählen. Ich habe die folgenden weichen Anforderungen:Wie sollte ich eine Liste der IANA/Olson-Zeitzonen von Noda Time ausfüllen?

1) Die Liste enthält nur Auswahlmöglichkeiten, die für die Gegenwart und nahe Zukunft für reale Orte vernünftig gültig sind. Historische, obskure und allgemeine Zeitzonen sollten herausgefiltert werden.

2) Die Liste sollte zuerst nach UTC-Offset und dann nach Zeitzonenname sortiert werden. Dies bringt sie hoffentlich in eine Reihenfolge, die für den Benutzer von Bedeutung ist.

Ich habe den folgenden Code geschrieben, der tatsächlich funktioniert, aber nicht genau das, was ich habe. Der Filter muss wahrscheinlich angepasst werden, und ich möchte lieber, dass der Offset den Basis-Offset (nicht-dst) und nicht den aktuellen Offset darstellt.

Vorschläge? Empfehlungen?

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) 
    Console.WriteLine(item.DisplayValue); 

Antwort

26

Noda Time 1.1 hat the zone.tab data, so können Sie jetzt wie folgt vorgehen:

/// <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) || 
       location.CountryCode.Equals(countryCode, 
              StringComparison.OrdinalIgnoreCase) 
     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); 
} 

alternativer Ansatz

Statt ein Drop-Down auf alle bereitstellen, können Sie eine map-based timezone picker verwenden.

enter image description here

3

Der Standard-Offset ist einfach - tz.GetZoneInterval(now).StandardOffset. Das gibt Ihnen den "aktuellen" Standard-Offset (es ist möglich, dass sich eine Zone im Laufe der Zeit ändert).

Die Filterung kann für Sie geeignet sein - ich möchte nicht sicher sagen. Es ist sicherlich nicht ideal in dem die IDs sind nicht wirklich für die Anzeige konzipiert. Im Idealfall würden Sie die Unicode CLDR "example" -Plätze verwenden, aber wir haben momentan keine CLDR-Integration an dieser Front.

+0

Gibt es eine saubere Art und Weise historische Zeitzonen, um herauszufiltern? Die TZ-Datenbank hat From- und To-Daten, für die Zeitzonen gültig sind. Stellt Noda das in irgendeiner Weise bloß? –

+0

@MattJohnson: Nein - welches Stück von TZDB macht das frei? Ich muss gestehen, dass ich das Format noch nie richtig verstanden habe, aber wenn es etwas ist, das wir hinzufügen können, tun wir das vielleicht (aber wahrscheinlich nicht für 1.0). (From und To sind normalerweise für bestimmte Regeln innerhalb einer Zeitzone, und ich dachte, dass die letzte Regel immer ein To von "max" hatte.) –

+0

Ich bin über diese Seite gestolpert http://69.36.11.139/tzdb/tz-how- to.html was die Dinge ziemlich gut erklärt. Die Regeleinträge scheinen die Daten zu haben, die ich benötigen würde. –

Verwandte Themen