2013-10-30 45 views
11

是否有程序或表格为每个国家/地区提供默认时区?获取国家的默认时区(通过CultureInfo)

是的,美国,加拿大,&俄罗斯有多个时区。 (我认为所有其他国家都只有一个国家。)但是,如果一个国家已知,最好从最有可能开始,而不是从格林威治标准时间开始提供一个清单。

最好在C#中,但我会把它带入任何东西并转换为C#。

+2

中国。印度。伊朗。巴西...... –

+0

什么是“默认时区”?这个地区与一个国家的首都? – elgonzo

+1

澳大利亚至少有三个时区,有些州但不是全部都有夏令时,印第安纳州在美国至少使用两个时区。 – 2013-10-30 23:03:23

回答

17

正如问题的评论所指出的那样,您无法为每个国家获得单一时区。有多个时区的国家情况太多了。

可以你可以将标准IANA/Olson time zones的列表筛选到特定国家的可用列表。在C#中要做到这一点

一种方法是用Noda Time

IEnumerable<string> zoneIds = TzdbDateTimeZoneSource.Default.ZoneLocations 
    .Where(x => x.CountryCode == countryCode) 
    .Select(x => x.ZoneId); 

传递一个两位数的ISO-3166国家代码,如"AU"澳大利亚。结果是:再次

var source = TzdbDateTimeZoneSource.Default; 
IEnumerable<string> windowsZoneIds = source.ZoneLocations 
    .Where(x => x.CountryCode == countryCode) 
    .Select(tz => source.WindowsMapping.MapZones 
     .FirstOrDefault(x => x.TzdbIds.Contains(
          source.CanonicalIdMap.First(y => y.Value == tz.ZoneId).Key))) 
    .Where(x => x != null) 
    .Select(x => x.WindowsId) 
    .Distinct() 

,叫做:

"Australia/Lord_Howe", 
"Australia/Hobart", 
"Australia/Currie", 
"Australia/Melbourne", 
"Australia/Sydney", 
"Australia/Broken_Hill", 
"Australia/Brisbane", 
"Australia/Lindeman", 
"Australia/Adelaide", 
"Australia/Darwin", 
"Australia/Perth", 
"Australia/Eucla" 

如果因为某些原因,你想,你可以用TimeZoneInfo对象使用Windows时区标识符,野田佳彦时间也可以映射那些与"AU"澳大利亚返回:

"Tasmania Standard Time", 
"AUS Eastern Standard Time", 
"Cen. Australia Standard Time", 
"E. Australia Standard Time", 
"AUS Central Standard Time", 
"W. Australia Standard Time" 

如果你想知道这个数据有多可靠,全国TZID映射是IANA时区数据的一部分以zone.tab文件为基础。 IANA到Windows的映射数据来自Unicode CLDR supplemental data。它没有比这更接近“官方”。

+0

你可以尝试'FO'国家代码相同吗? ('Faroi Islands')我可以在文件('zone.tab')中找到代码,但是在'C#'中,我没有得到这个代码的结果。 – Alex

+0

尝试编辑我刚才做的。我没有考虑到windows映射中的ID并不总是TZDB规范的ID。 –

2

可能不是正是你所寻找的东西,但试试这个:http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

为了得到一个特定的时间段:

TimeZoneInfo tZone = TimeZoneInfo.FindSystemTimeZoneById("E. Australia Standard Time"); 

要查看可用区域:

ReadOnlyCollection<TimeZoneInfo> zones = TimeZoneInfo.GetSystemTimeZones(); 

foreach (TimeZoneInfo zone in zones) 
{ 
    Console.WriteLine(zone.Id); 
} 
1

为了得到CountryCode - > TimeZoneInfo映射我使用了Matt(第二代码片段)的答案,但它在很多情况下都不起作用。找到更简单,更可靠的解决方案(使用相同的Noda时间):TzdbDateTimeZoneSource.Default.WindowsMapping.MapZones基本上包含所有数据。

代码示例:

Dictionary<string, TimeZoneInfo> GetIsoToTimeZoneMapping() 
{ 
    var source = TzdbDateTimeZoneSource.Default; 

    return source.WindowsMapping.MapZones 
     .GroupBy(z => z.Territory) 
     .ToDictionary(grp => grp.Key, grp => GetTimeZone(source, grp)); 
} 

TimeZoneInfo GetTimeZone(TzdbDateTimeZoneSource source, IEnumerable<MapZone> territoryLocations) 
{ 
    var result = territoryLocations 
     .Select(l => l.WindowsId) 
     .Select(TimeZoneInfo.FindSystemTimeZoneById) 
     //pick timezone with the minimum offset 
     .Aggregate((tz1, tz2) => tz1.BaseUtcOffset < tz2.BaseUtcOffset ? tz1 : tz2); 

    return result; 
}