web-dev-qa-db-ja.com

国のデフォルトのタイムゾーンを取得する(CultureInfoを使用)

すべての国のデフォルトのタイムゾーンを提供するプログラムまたはテーブルはありますか?

はい、米国、カナダ、ロシアには複数のタイムゾーンがあります。 (他の国は1つだけだと思います。)しかし、GMTで始まるリストを提供するだけでなく、国が知られている場合は、最も可能性の高いものから開始することをお勧めします。

できればC#を使用しますが、何でも使用してC#に変換します。

15
David Thielen

質問のコメントに記載されているように、国ごとに1つのタイムゾーンを取得することはできません。複数のタイムゾーンを持つ国のケースは多すぎます。

あなたができることできることは、標準的な IANA/Olsonタイムゾーン のリストを特定の国で利用可能なものまでフィルタリングします。

C#でこれを行う1つの方法は Noda Time を使用することです。

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

2桁の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"

そして、何らかの理由でTimeZoneInfoオブジェクトで使用できるWindowsタイムゾーン識別子が必要な場合は、野田時間もそれらをマッピングできます。

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へのマッピングデータは nicode CLDR補足データ から取得されます。それより「公式」に近づくことはありません。

21

正確にあなたが探しているものではないかもしれませんが、これを試してください: 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);
}
3
JuStDaN

CountryCode-> TimeZoneInfoマッピングを取得するために、Matt(2番目のコードスニペット)からの回答を使用しましたが、多くの場合は機能しませんでした。よりシンプルで信頼性の高いソリューションが見つかりました(同じ野田時間を使用):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;
}
1

私は、ユーザーが最初にログインするときにMicrosoftがWindowsに使用する国別のデフォルトのタイムゾーンを使用しました。 https://docs.Microsoft.com/en-us/windows -hardware/manufacture/desktop/default-time-zones

https://github.com/rahulgi/default-timezones にあるJSONファイルにそのテーブルを解析するスクリプトも作成しました。

0

Windowsの最新バージョンには、OlsonをWindowsタイムゾーンにマップするファイル%WINDIR%\Globalization\Time Zone\timezoneMapping.xmlが含まれており、通常のXMLとしてクエリできます。わかりませんが、おそらくC#には、それを扱うクラスがすでにあります。

0

一部の国では、たとえばロシアなど、複数のタイムゾーンを持っています。

私のソリューションでは 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;
    }
}
0
live2