2012-10-24 8 views
14

私はアプリケーションでNodaTimeを使用しています。ユーザーはドロップダウンリストからタイムゾーンを選択する必要があります。私は次のようなソフト要件を持っています:野田時代のIANA/Olsonタイムゾーンのリストをどのように設定すればよいですか?

1)リストには現実の場所と近い将来現実的な場所で合理的に有効な選択肢のみが含まれています。歴史的な、あいまいな、そして一般的なタイムゾーンは除外されるべきです。

2)リストは、まずUTCオフセットで、次にタイムゾーン名でソートする必要があります。これは、ユーザーにとって意味のある順序でそれらをうまく置きます。

私は以下のコードを書いていますが、それは実際には動作しますが、正確には私の後ろにあるものはありません。フィルタはおそらく調整する必要があります、私はむしろ現在のオフセットではなく、ベース(非dst)オフセットを表すオフセットを持っています。

提案?推薦?

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); 

答えて

26

野田時間1.1 the zone.tab dataを持っているので、あなたが今、次の操作を行うことができます。

/// <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); 
} 

代替アプローチ

代わりのダウンですべてのドロップを提供し、あなたはmap-based timezone pickerを使用することができます。

enter image description here

3

tz.GetZoneInterval(now).StandardOffsetの標準オフセットの取得は簡単です。これにより、現在の標準オフセットが得られます(時間の経過とともにゾーンが変化する可能性があります)。

フィルタリングが適切かもしれません - 私は確かに言いたいと思います。確かにの理想的なではありません。なぜならIDは本当に表示用に設計されていないからです。理想的には、Unicode CLDRの「例」の場所を使用しますが、その時点ではCLDRの統合はありません。

+0

歴史的なタイムゾーンをフィルタリングするためにいくつかのきれいな方法はありますか? TZデータベースには、タイムゾーンが有効な開始日と終了日があります。野田はこれをどのような方法でも公開していますか? –

+0

@MattJohnson:いいえ - TZDBのどのビットがそれを公開していますか?私はフォーマットを完全に理解したことはないと告白する必要がありますが、もしそれが追加できれば、そうするかもしれません。 (FromとToは通常タイムゾーン内の特定のルールのためにあり、最終ルールには常に「最大」のToがあると思っていました) –

+0

私はこのページを見つけましたhttp://69.36.11.139/tzdb/tz-how- to.htmlは物事をかなりうまく説明します。ルールエントリには、私が必要とするデータがあるようです。 –

関連する問題