Get the default timezone for a country (via CultureInfo)

前端 未结 6 1600
广开言路
广开言路 2020-11-30 05:20

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 c

相关标签:
6条回答
  • 2020-11-30 05:39

    May not be exactly what you are looking for, but try this: 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);
    }
    
    0 讨论(0)
  • 2020-11-30 05:40

    Some countries have more as one timezone for example russia.

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

    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;
        }
    }
    
    0 讨论(0)
  • 2020-11-30 05:48

    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.

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

    0 讨论(0)
  • 2020-11-30 05:49

    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.

    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;
    }
    
    0 讨论(0)
  • 2020-11-30 05:50

    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 can do is filter the list of standard IANA/Olson time zones down to those available within a specific country.

    One way to do this in C# is with 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:

    "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 TimeZoneInfo object, Noda Time can map those too:

    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:

    "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.tab file. The IANA to Windows mapping data comes from the Unicode CLDR supplemental data. It doesn't get any closer to "official" than that.

    0 讨论(0)
  • 2020-11-30 05:54

    Latest Windows versions contain file %WINDIR%\Globalization\Time Zone\timezoneMapping.xml which 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.

    0 讨论(0)
提交回复
热议问题