C# 获取一个国家的默认时区(通过 CultureInfo)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19695439/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 15:38:24  来源:igfitidea点击:

Get the default timezone for a country (via CultureInfo)

c#timezonecountry

提问by David Thielen

Is there a program or a table that provides the default timezone for every country?

是否有提供每个国家/地区默认时区的程序或表格?

Yes, the US, Canada, & Russia have multiple timezones. (I think every other country has just one.) But it's better to start on the most likely if a country is known rather than just provide a list starting at GMT.

是的,美国、加拿大和俄罗斯有多个时区。(我认为每个其他国家/地区都只有一个。)但最好从最有可能的国家/地区开始,而不是仅提供从格林威治标准时间开始的列表。

Preferably in C# but I'll take it in anything and convert to C#.

最好在 C# 中,但我会接受任何内容并转换为 C#。

采纳答案by Matt Johnson-Pint

As identified in the comments of the question, you aren't going to be able to get a single time zone for each country. There are just too many cases of countries that have multiple time zones.

正如问题的评论中所指出的,您将无法为每个国家/地区获得一个时区。有多个时区的国家的案例太多了。

What you cando is filter the list of standard IANA/Olson time zonesdown to those available within a specific country.

可以做的是将标准IANA/Olson 时区列表过滤到特定国家/地区可用的时区列表。

One way to do this in C# is with Noda Time:

在 C# 中执行此操作的一种方法是使用Noda Time

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

Pass a two-digit ISO-3166 country code, such as "AU"for Australia. The results are:

传递两位数的 ISO-3166 国家/地区代码,例如"AU"澳大利亚。结果是:

"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"

And if for some reason you'd like Windows time zone identifiers that you can use with the TimeZoneInfoobject, Noda Time can map those too:

如果出于某种原因,您想要可以与TimeZoneInfo对象一起使用的 Windows 时区标识符,Noda Time 也可以映射这些:

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

Again, called with "AU"for Australia returns:

再次,呼吁"AU"澳大利亚返回:

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

If you're wondering about how reliable this data is, the country to tzid mapping is part of the IANA time zone database itself, in the zone.tabfile. The IANA to Windows mapping data comes from the Unicode CLDR supplemental data. It doesn't get any closer to "official" than that.

如果您想知道这些数据的可靠性,那么 tzid 映射的国家/地区是 IANA 时区数据库本身的一部分,位于zone.tab文件中。IANA 到 Windows 的映射数据来自Unicode CLDR 补充数据。没有比这更接近“官方”的了。

回答by JuStDaN

May not be exactly what you are looking for, but try this: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

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

To get a specific time zone:

要获取特定时区:

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

To see the available zones:

要查看可用区域:

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

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

回答by Konstantin Babiy

In order to get CountryCode -> TimeZoneInfo mapping i used answer from Matt (2nd code snippet), but it didn't work for many cases. Found simpler and more reliable solution (using same Noda Time): TzdbDateTimeZoneSource.Default.WindowsMapping.MapZones basically has all the data.

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

Code sample:

代码示例:

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

回答by Vladimir Zelenov

Latest Windows versions contain file %WINDIR%\Globalization\Time Zone\timezoneMapping.xmlwhich maps Olson to Windows time zone, you can query it as regular XML. I don't know but maybe C#already has a class which works with it.

最新的 Windows 版本包含%WINDIR%\Globalization\Time Zone\timezoneMapping.xml将 Olson 映射到 Windows 时区的文件,您可以将其作为常规XML. 我不知道,但也许C#已经有一个可以使用它的类。

回答by Rahul Gupta-Iwasaki

I've used the per-country default timezones that Microsoft uses for Windows when a user first logs in. They list them at https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones.

当用户首次登录时,我使用了 Microsoft 用于 Windows 的每个国家/地区的默认时区。他们在https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-列出了它们时区

I also created a script which parses that table out into a JSON file at https://github.com/rahulgi/default-timezones.

我还创建了一个脚本,该脚本将该表解析为https://github.com/rahulgi/default-timezones 上的 JSON 文件。

回答by live2

Some countries have more as one timezone for example russia.

一些国家将多个时区作为一个时区,例如俄罗斯。

In my solution i use NodaTimeif you have a longitude information available i select the best timezone for this country.

在我的解决方案中,如果您有可用的经度信息,我会使用NodaTime,我会选择该国家/地区的最佳时区。

var countryName = "Russia";
var longitude = 40.332206;

var zones = TzdbDateTimeZoneSource.Default.ZoneLocations.Where(x => x.CountryName == countryName).AsQueryable();
if (!double.IsNaN(longitude))
{
    zones = zones.OrderBy(o => this.Distance(o.Latitude, longitude, o.Latitude, o.Longitude, DistanceUnit.Kilometer));
}
var bestZone = zones.FirstOrDefault();
var dateTimeZone = TzdbDateTimeZoneSource.Default.ForId(bestZone.ZoneId);

var newTime = DateTime.UtcNow.AddSeconds(dateTimeZone.MaxOffset.Seconds);

Calculate distance of geo coordinates

计算地理坐标的距离

public enum DistanceUnit { StatuteMile, Kilometer, NauticalMile };

private double Distance(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit)
{
    double rlat1 = Math.PI * lat1 / 180;
    double rlat2 = Math.PI * lat2 / 180;
    double theta = lon1 - lon2;
    double rtheta = Math.PI * theta / 180;
    double dist =
        Math.Sin(rlat1) * Math.Sin(rlat2) + Math.Cos(rlat1) *
        Math.Cos(rlat2) * Math.Cos(rtheta);
    dist = Math.Acos(dist);
    dist = dist * 180 / Math.PI;
    dist = dist * 60 * 1.1515;

    switch (unit)
    {
        case DistanceUnit.Kilometer:
            return dist * 1.609344;
        case DistanceUnit.NauticalMile:
            return dist * 0.8684;
        default:
        case DistanceUnit.StatuteMile: //Miles
            return dist;
    }
}