16

アプリケーションでNodaTimeを使用していますが、ユーザーがドロップダウンリストからタイムゾーンを選択する必要があります。次のソフト要件があります。

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

2 に答える 2

26

Noda Time 1.1にはzone.tabデータがあるため、次のことができるようになりました。

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

代替アプローチ

ドロップダウンを提供する代わりに、マップベースのタイムゾーンピッカーを使用できます。

ここに画像の説明を入力してください

于 2013-06-13T23:29:50.463 に答える
3

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

フィルタリングはあなたに適しているかもしれません-私は確かに言いたくありません。IDが実際に表示用に設計されていないという点で、これは確かに理想的ではありません。Unicode CLDRの「例」の場所を使用するのが理想的ですが、現時点ではその前面にCLDR統合はありません。

于 2012-10-25T14:44:59.163 に答える