我应该如何从 Noda Time 填充 IANA/Olson 时区列表? [英] How should I populate a list of IANA / Olson time zones from Noda Time?

查看:27
本文介绍了我应该如何从 Noda Time 填充 IANA/Olson 时区列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在应用程序中使用 NodaTime,我需要用户从下拉列表中选择他们的时区.我有以下软性要求:

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) 该列表仅包含对当前和不久的将来真实地点合理有效的选择.应过滤掉历史、模糊和通用时区.

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) 列表应首先按 UTC 偏移量排序,然后按时区名称排序.这有望使它们按对用户有意义的顺序排列.

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.

我编写了以下代码,它确实有效,但并不完全符合我的要求.过滤器可能需要调整,我宁愿让偏移量代表基本(非 dst)偏移量,而不是当前偏移量.

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.

建议?推荐?

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

推荐答案

Noda Time 1.1 有 zone.tab 数据,因此您现在可以执行以下操作:

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

替代方法

您可以使用基于地图的时区选择器,而不是根本不提供下拉菜单.

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

这篇关于我应该如何从 Noda Time 填充 IANA/Olson 时区列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆