Получить часовой пояс по умолчанию для страны (через CultureInfo)

Есть ли программа или таблица, которая указывает часовой пояс по умолчанию для каждой страны?

Да, в США, Канаде и России несколько часовых поясов. (Я думаю, что в каждой другой стране есть только одна.) Но лучше начать с наиболее вероятного, если страна известна, а не просто предоставить список, начиная с GMT.

Предпочтительно на C#, но я возьму что угодно и конвертирую в C#.


person David Thielen    schedule 30.10.2013    source источник
comment
Китай. Индия. Иран. Бразилия....   -  person Andrew Barber    schedule 31.10.2013
comment
Что такое часовой пояс по умолчанию??? Зона со столицей страны?   -  person    schedule 31.10.2013
comment
И Австралия, по крайней мере, с тремя часовыми поясами, и некоторые штаты, но не все, имеют летнее время, и Индиана в США, где используется как минимум два часовых пояса.   -  person    schedule 31.10.2013
comment
Вопросы, в которых нас просят порекомендовать или найти инструмент, библиотеку или любимый сторонний ресурс, не относятся к теме Stack Overflow, поскольку они, как правило, привлекают самоуверенные ответы и спам. Вместо этого опишите проблему и то, что уже было сделано для ее решения.   -  person    schedule 31.10.2013
comment
@ Эндрю, забавный факт: в Китае действительно только один часовой пояс. Безумие, если подумать о размерах этой страны. Но в Монголии их два, это должно сбалансировать ;)   -  person    schedule 31.10.2013
comment
@AndrewBarber - Китай, Индия и Иран имеют один часовой пояс.   -  person David Thielen    schedule 31.10.2013
comment
@elgonzo - Думаю, в столице было бы лучше. Но подойдет любой разумный в стране.   -  person David Thielen    schedule 31.10.2013
comment
@MikeW Я не спрашиваю мнение о лучшей библиотеке, которая решает эту проблему. Я просто спрашиваю, существует ли вообще такое решение.   -  person David Thielen    schedule 31.10.2013
comment
@DavidThielen Они действительно? Не имел представления. Хотя я знаю, что в Бразилии их несколько. (3, я думаю...)   -  person Andrew Barber    schedule 31.10.2013
comment
@AndrewBarber Вот почему я думаю, что это было бы неплохо. Для большинства стран есть один. А в остальном большая часть населения находится только в одной из нескольких зон.   -  person David Thielen    schedule 31.10.2013
comment
Кроме того, я знаю, что во Франции, Австралии, Дании и Великобритании их тоже несколько. На самом деле, я думаю, что у Франции больше всех.   -  person Andrew Barber    schedule 31.10.2013
comment
@ Дэвид, может быть, это поможет вам: stackoverflow. com/questions/7977736/ . Если нет, возможно, вы можете украсть..., эм... скопировать таблицу из Википедии (en.wikipedia .org/wiki/List_of_time_zones_by_country) и создайте текстовый/excel/csv/json/любой файл с данными.   -  person    schedule 31.10.2013
comment
Похожий вопрос. Не дублировать, потому что вы представили концепцию часового пояса по умолчанию, но ответ может помочь.   -  person M.Babcock    schedule 31.10.2013
comment
Вот информация из Википедии Кроме того, я даже не знаю, какой будет часовой пояс по умолчанию. Я не думаю, что вы правы в том, что люди сосредоточены в одном часовом поясе.   -  person Andrew Barber    schedule 31.10.2013
comment
@Andrew: Поскольку Гренландия в основном является автономной страной (хотя они по-прежнему являются членами так называемого Королевства Дания), в Дании есть только один часовой пояс (UTC+01:00).   -  person    schedule 31.10.2013
comment
@elgonzo Хорошо, тогда у Гренландии 4;)   -  person Andrew Barber    schedule 31.10.2013
comment
@Эндрю: в Гренландии 4? Я думал, что их 3. Но да, в Гренландии действительно 4 часовых пояса... Думаю, китайцы завидуют Гренландии...   -  person    schedule 31.10.2013
comment
@AndrewBarber для США и России нет, для большинства людей это не один часовой пояс, хотя на Восточном побережье может быть почти половина часового пояса для США. Но для остальных, я думаю, да. Восточное побережье для Австралии, Онтарио для Канады и т. д. PS Мне нравится бразильское время для пары островов.   -  person David Thielen    schedule 31.10.2013
comment
Это определенно сделало для веселой дискуссии   -  person David Thielen    schedule 31.10.2013
comment
Франция? СОЕДИНЕННОЕ КОРОЛЕВСТВО? Индонезия? Мексика? Испания? Португалия? И посмотрите на разрыв во времени, который у вас будет примерно между половиной каждого из США; Восточная и Тихоокеанская.   -  person Andrew Barber    schedule 31.10.2013
comment
В Антарктиде есть все часовые пояса. Ура! Подождите... это не страна...   -  person    schedule 31.10.2013
comment
@AndrewBarber Во Франции есть одна зона для самой Франции. В Великобритании есть один для Британских островов. Испания и Португалия снова один часовой пояс для основной страны. В Индонезии и Мексике вам придется выбрать значение по умолчанию, но по умолчанию для Мексики это сделать несложно. В Индонезии у вас действительно есть большое население в двух из них. Но опять же, если начать с того, что для половины есть правильное значение, а для другой половины оно отсутствует в раскрывающемся списке.   -  person David Thielen    schedule 31.10.2013
comment
Говоря про себя: нет, в Антарктиде не все часовые пояса. Но пингвинам все равно...   -  person    schedule 31.10.2013
comment
@MikeW: тогда само летнее время не распространяется на все штаты, что еще больше усложняет ситуацию ...   -  person Qantas 94 Heavy    schedule 31.10.2013
comment
@Qantas94Heavy Вот что я хотел сказать, но получилось не совсем правильно   -  person    schedule 31.10.2013
comment
@DavidThielen Я согласен, что это была интересная беседа на эту тему! :)   -  person Andrew Barber    schedule 31.10.2013


Ответы (6)


Как указано в комментариях к вопросу, вы не сможете получить единый часовой пояс для каждой страны. Слишком много стран с несколькими часовыми поясами.

Что вы можете сделать, так это отфильтровать список стандартных часовых поясов IANA/Olson вплоть до доступных в конкретной стране.

Один из способов сделать это на C# — использовать Noda Time:

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

Передайте двузначный код страны 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"

И если по какой-то причине вам нужны идентификаторы часовых поясов Windows, которые вы можете использовать с объектом TimeZoneInfo, 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()

Опять же, вызов с "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 берутся из дополнительных данных CLDR Unicode. . Это не становится ближе к «официальному», чем это.

person Matt Johnson-Pint    schedule 31.10.2013
comment
Не могли бы вы попробовать то же самое для кода страны FO? (Faroi Islands) Я могу найти код в файле (zone.tab), но в C# я не получаю результатов для этого кода.. - person Alex; 02.07.2016
comment
Попробуйте редактирование, которое я только что сделал. Я не учел, что идентификаторы в сопоставлении окон не всегда являются каноническими TZDB. - person Matt Johnson-Pint; 02.07.2016
comment
Для часового пояса Windows работает не во всех случаях, например HR. - person Umair; 28.04.2019
comment
Это создает избыточные часовые пояса. Например, в Соединенных Штатах всего 3-4 часовых пояса, но это возвращает 29 часовых поясов, многие из которых совпадают с часовыми поясами! - person A X; 29.12.2019

Возможно, это не совсем то, что вы ищете, но попробуйте следующее: 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);
}
person JuStDaN    schedule 31.10.2013

Чтобы получить сопоставление CountryCode -> TimeZoneInfo, я использовал ответ от Мэтта (2-й фрагмент кода), но во многих случаях это не сработало. Найдено более простое и надежное решение (с использованием того же времени 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;
}
person Konstantin Babiy    schedule 20.10.2017

Последние версии Windows содержат файл %WINDIR%\Globalization\Time Zone\timezoneMapping.xml, который сопоставляет Олсона с часовым поясом Windows, вы можете запросить его как обычный XML. Я не знаю, но, возможно, у C# уже есть класс, который с ним работает.

person Vladimir Zelenov    schedule 03.05.2018
comment
Хороший способ реализовать это можно найти здесь codeofmatt.com/2014/04/07/working-with-time-zone-names-in-net - person Walter Vehoeven; 30.09.2018

Я использовал часовые пояса по умолчанию для каждой страны, которые Microsoft использует для Windows при первом входе пользователя в систему. Они перечислены по адресу https://docs.microsoft.com/en-us/windows-hardware/manufacture./desktop/default-time-zones.

Я также создал скрипт, который анализирует эту таблицу в файл JSON по адресу https://github.com/rahulgi/default-timezones.

person Rahul Gupta-Iwasaki    schedule 18.07.2019

В некоторых странах часовой пояс больше, например в России.

В моем решении я использую 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);

Рассчитать расстояние до географических координат

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;
    }
}
person live2    schedule 03.12.2019