2013-10-30 30 views
11

Esiste un programma o una tabella che fornisce il fuso orario predefinito per ogni paese?Ottieni il fuso orario predefinito per un Paese (tramite CultureInfo)

Sì, Stati Uniti, Canada, & La Russia ha più fusi orari. (Penso che ogni altro paese ne abbia solo uno.) Ma è meglio partire dal più probabile se si conosce un paese piuttosto che fornire una lista a partire da GMT.

Preferibilmente in C# ma lo prenderò in qualsiasi cosa e convertirò in C#.

+2

Cina. India. Ho corso. Brasile .... –

+0

Che cos'è un "fuso orario predefinito" ??? La zona con la capitale di un paese? – elgonzo

+1

E l'Australia con almeno tre fusi orari e alcuni stati, ma non tutti, hanno ora legale e Indiana negli Stati Uniti che utilizza almeno due fusi orari. –

risposta

17

Come indicato nei commenti della domanda, non sarai in grado di ottenere un singolo fuso orario per ogni paese. Ci sono troppi casi di paesi che hanno più fusi orari.

Che cosa si può fare è filtrare l'elenco di standard di IANA/Olson time zones giù a quelli disponibili all'interno di un determinato paese.

Un modo per fare questo in C# è con Noda Time:

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

passare una a due cifre ISO-3166 codice del paese, come ad esempio "AU" per l'Australia. I risultati sono:

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

E se per qualche motivo vuoi identificatori fuso orario di Windows che è possibile utilizzare con l'oggetto TimeZoneInfo, Noda tempo può mappare quelli troppo:

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

Anche in questo caso, chiamato con "AU" per l'Australia restituisce:

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

Se vi state chiedendo su come affidabile questi dati è, il paese a tzid mappatura è parte dei dati del fuso orario IANA base stessa, nel file zone.tab. I dati di mappatura da IANA a Windows provengono da Unicode CLDR supplemental data. Non si avvicina a "ufficiale" di quello.

+0

Puoi provare lo stesso per il codice del paese 'FO'? ('Faroi Islands') Riesco a trovare il codice nel file (' zone.tab') ma in 'C#' Non ottengo risultati per questo codice .. – Alex

+0

Prova la modifica che ho appena creato. Non avevo preso in considerazione che gli ID nella mappatura di Windows non sono sempre quelli canonici di TZDB. –

2

potrebbe non essere esattamente quello che stai cercando, ma provate questo: http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

Per ottenere un fuso orario specifico:

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

Per vedere le zone disponibili:

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

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

Per ottenere CountryCode -> TimeZoneInfo mapping ho usato la risposta di Matt (2 ° snippet di codice), ma non ha funzionato in molti casi. Trovato soluzione più semplice e più affidabile (usando la stessa Noda Time): TzdbDateTimeZoneSource.Default.WindowsMapping.MapZones ha fondamentalmente tutti i dati.

Esempio di codice:

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