我在应用程序中使用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);
答案 0 :(得分:26)
Noda Time 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。
,而不是提供下拉菜单
答案 1 :(得分:3)
获得标准偏移很容易 - tz.GetZoneInterval(now).StandardOffset
。这将给你&#34;当前&#34;标准偏移(区域可能随时间变化)。
过滤可能适合您 - 我不想肯定地说。它当然不是理想,因为ID并非真正用于显示。理想情况下,您使用Unicode CLDR&#34;示例&#34;这些地方,但我们目前还没有任何CLDR集成。