Get the default timezone for a country (via CultureInfo)
Asked Answered
F

6

26

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#.

Flexuous answered 30/10, 2013 at 23:0 Comment(26)
China. India. Iran. Brazil....Multifoliate
What is a "default timezone"??? The zone in with the capital of a country?Biomedicine
And Australia with at least three timezones, and some states, but not all, have daylight saving time, and Indiana in the US which uses at least two time zones.Toilworn
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.Toilworn
@Andrew, fun fact: China has indeed only one timezone. Crazy, if you think about the size of that country. But Mongolia has two, that should balance it ;)Biomedicine
@AndrewBarber - China, India, & Iran all have a single timezone.Flexuous
@elgonzo - I think the capital would be best. But any reasonable one in the country would be fine.Flexuous
@MikeW I'm not asking for an opinion on the best library that solves this. I'm just asking if such a solution exists at all.Flexuous
@DavidThielen Do they really? I had no idea. I do know Brazil has multiple, though. (3, I think...)Multifoliate
@AndrewBarber That's why I think this would be a good thing to have. For most countries there is one. And for the remainder, most of the population is in just one of the several zones.Flexuous
Also, I know France, Australia, Denmark, and the UK also have multiple. In fact, I think France has the most of any.Multifoliate
@David, maybe this helps you: #7978236 . If not, perhaps you can stea..., erm... copy the table from Wikipedia (en.wikipedia.org/wiki/List_of_time_zones_by_country) and make yourself a text/excel/csv/json/whatever file with the data.Biomedicine
Related question. Not duplicate because you've imagined the concept of a "default" timezone, but the answer may help.Ethicize
Here's info from Wikipedia And also, I don't even know what a "Default timezone" would be. I don't think you are correct about people being centered in one timezone.Multifoliate
@Andrew: Since Greenland is basically an autonomous country (they are still member of the so-called "Kingdom of Denmark", though), Denmark has only one timezone (UTC+01:00)Biomedicine
@elgonzo OK, so Greenland has 4, then ;)Multifoliate
@Andrew: Greenland has 4? I thought they have 3. But yes, Greenland has indeed 4 timezones... I think the Chinese are jealous about Greenland...Biomedicine
@AndrewBarber for the U.S. & Russia no it's not one timezone for most people, although the East Coast may have close to half for the U.S. But for the rest I think yes. East Coast for Australia, Ontario for Canada, etc. ps I love the Brazil time that's for "a couple of islands."Flexuous
This definitely made for a fun discussionFlexuous
France? UK? Indonesia? Mexico? Spain? Portugal? And look at the split in time you would have between about half each of the US; Eastern and Pacific.Multifoliate
Antarctica has all timezones. Yay! Wait... that's no country...Biomedicine
@AndrewBarber France has one zone for France itself. UK has one for the British Isles. Spain & Portugal again one timezone for the main country. Indonesia & Mexico you would have to pick a default but Mexico's default is easy. Indonesia you do have a large population in two of them. But again, starting on either has the correct for half and it's one away in the drop-down list for the other half.Flexuous
Speaking to myself: No, Antarctica does not have all timezones. But the penguins don't care anyway...Biomedicine
@MikeW: then daylight savings itself does not apply to all states, which complicates things even more...Metaphysic
@Qantas94Heavy That's what I meant to say, but it didn't quite come out rightToilworn
@DavidThielen I agree this has been an interesting convo about the topic! :)Multifoliate
I
34

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.

Indoor answered 31/10, 2013 at 3:13 Comment(7)
Could you try the same for FO country code? (Faroi Islands) I can find the code in file (zone.tab) but in C# I am getting no results for this code..Lactone
Try the edit I just made. I hadn't taken into account the IDs in the windows mapping are not always the TZDB canonical ones.Indoor
For windows time zone, it does not work for all cases, for example HR.Pulchritude
This produces redundant time zones. For example, the United States only has 3-4 time zones but this returns 29 time zones, many of which are the same time zone!Musket
Hello I found that the code doesn't work for country with code "AX" so here id my take on your solution: IEnumerable<TzdbZoneLocation> ZoneIds = source.ZoneLocations.Where(key => key.CountryCode == countryCode); IReadOnlyDictionary<string, string> WindowsZoneIDs = source.TzdbToWindowsIds; List<string> Timezones = new(); foreach (var timezone in ZoneIds) { if (WindowsZoneIDs.ContainsKey(timezone.ZoneId)) Timezones.Add(WindowsZoneIDs[timezone.ZoneId]); } var TimezonesDistinct = Timezones.Distinct();Banjo
Is there a way to do this by specifying a CountryCode as well as an additional region identifier? For example in the US, if we just use "US", it will return all timezones, but if I do "US" and "NY", it will return America/New_York?Mirtamirth
@RajeshPatel - No, because there are several states in the USA that observe more than one time zone.Indoor
F
4

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);
}
Flieger answered 31/10, 2013 at 3:3 Comment(0)
I
4

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;
}
Ill answered 20/10, 2017 at 14:7 Comment(0)
M
1

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.

Maverick answered 3/5, 2018 at 7:38 Comment(1)
Nice way to implement this can be found here codeofmatt.com/2014/04/07/working-with-time-zone-names-in-netGovernor
C
1

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;
    }
}
Calliopsis answered 3/12, 2019 at 15:14 Comment(0)
M
0

I've used the per-country default timezones that Microsoft uses for Windows when a user first logs in. They list them at https://learn.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.

Malformation answered 18/7, 2019 at 0:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.