2009-08-13 7 views
17

Ich habe ein Szenario, in dem ich einen Zeitzonenoffset (in Minuten) habe und die Zeitzone dafür bestimmen muss. Ich weiß, dass alle Daten nicht verfügbar sind (es kann z. B. mehrere Zeitzonen mit einem Offset von -240 Minuten geben), aber eine "beste Schätzung" ist akzeptabel.Wie kann ich eine Zeitzone anhand des UTC-Offsets ermitteln?

Mein erster Pass sah wie folgt aus:

foreach (var info in TimeZoneInfo.GetSystemTimeZones()) 
{ 
    if (info.BaseUtcOffset.TotalMinutes == timezoneOffset) 
    { 
     // do something here if this is a valid timezone 
    } 
} 

Diese sorta funktioniert, aber ich brauche für die Sommerzeit zu berücksichtigen, die mich etwas weg zu werfen ist. Ich habe diese schreckliche Hack:

foreach (var info in TimeZoneInfo.GetSystemTimeZones()) 
{ 
    var extra = info.IsDaylightSavingTime(DateTime.Now) ? 60 : 0; 
    if (info.BaseUtcOffset.TotalMinutes + extra == timezoneOffset) 
    { 
     // do something here if this is a valid timezone 
    } 
} 

Diese „gut genug“ in das funktioniert kann ich den Benutzer die richtige Zeit für sie zeige, wenn die Sommerzeit nicht wirksam ist, und ist etwa 70% richtig während DST. Trotzdem ... das ist ein schrecklicher Code für meine Augäpfel.

Gibt es einen besseren Weg, dies zu tun? Mehr Eleganz wäre gut und mehr Genauigkeit wäre noch besser.

aktualisiert

Technisch Ich habe Zugang zu allen Informationen Javascript in Bezug auf den Zeitpunkt bekommen. Ich habe eine Seite, auf der ich ein verstecktes Feld namens "Offset" platziert habe. Ich habe eine JQuery-Funktion, die das Offset-Feld mit der DateTime(). GetTimezoneOffset() füllt. Ich sehe zwar nichts auf dem DateTime-Objekt, das hilft, aber vielleicht werden dadurch andere Ideen eröffnet.

+0

@Sailing Judo: Ich habe meiner Antwort einen Code hinzugefügt, mit dem Javascript einen universellen Zeitstempel in einen lokalen umwandeln kann. – Kip

Antwort

16

Kurze Antwort: Sie können nicht.

Sommerzeit machen es unmöglich. Zum Beispiel gibt es keine Möglichkeit, allein aus dem UTC-Offset den Unterschied zwischen Arizona und Kalifornien im Sommer oder Arizona und New Mexico im Winter zu bestimmen (da Arizona DST nicht beobachtet).

Es gibt auch die Frage, zu welcher Zeit verschiedene Länder DST beobachten. Zum Beispiel, in den USA beginnt die Sommerzeit früher und endet später als in Europa.

Eine genaue Schätzung ist möglich (d. H. +/- eine Stunde), aber wenn Sie sie verwenden, um die Zeit für Benutzer anzuzeigen, wird bei einigen von ihnen zwangsläufig die falsche Zeit angezeigt.


aktualisieren: Aus den Kommentaren, es sieht aus wie Ihr primäres Ziel ist es in dem Benutzer lokaler Zeitzone einen Zeitstempel angezeigt werden soll. Wenn Sie das möchten, sollten Sie die Zeit als UTC-Zeitstempel senden und sie dann im Browser des Benutzers mit Javascript neu schreiben. Für den Fall, dass sie Javascript nicht aktiviert haben, sehen sie immer noch einen verwendbaren UTC-Zeitstempel. Hier ist eine Funktion, die ich in this question, die ich in this Greasemonkey script verwendet habe, kam. Vielleicht möchten Sie es an Ihre Bedürfnisse anpassen.

//@param timestamp An ISO-8601 timestamp in the form YYYY-MM-DDTHH:MM:SS±HH:MM 
//Note: Some other valid ISO-8601 timestamps are not accepted by this function 
function parseISO8601(timestamp) 
{ 
    var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$"); 
    var matches = regex.exec(timestamp); 
    if(matches != null) 
    { 
    var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10); 
    if(matches[7] == "-") 
     offset = -offset; 

    return new Date(
     Date.UTC(
     parseInt(matches[1], 10), 
     parseInt(matches[2], 10) - 1, 
     parseInt(matches[3], 10), 
     parseInt(matches[4], 10), 
     parseInt(matches[5], 10), 
     parseInt(matches[6], 10) 
    ) - offset*60*1000 
    ); 
    } 
    return null; 
} 

Hier ist eine Funktion, die ich in meinem Blog verwende, um einen geparsten Zeitstempel in der lokalen Zeitzone des Benutzers anzuzeigen. Auch hier können Sie es an das gewünschte Format anpassen.

+0

Dies ist wahr, ein Offset allein reicht nicht aus, um die Zeitzone zu bestimmen. Haben Sie weitere Informationen, auf die Sie Zugriff haben? Können Sie einen Benutzer nach einer Zeitzone fragen? –

+0

@Matt: Technisch kann ich Zugriff auf alles haben, was Javascript mir sagen kann, aber ich sehe nichts auf dem Javascript DateTime-Objekt, das zurückgegeben wird, wenn der Client derzeit in DST ist oder nicht. –

+0

@Matt: Auch diese ganze Übung ist ein Versuch, den Benutzer NICHT für Informationen zu stören, wenn ich es irgendwie für mich selbst bekommen kann. Da der Benutzer für eine Zeitzone der absolute letzte Ausweg ist. In der Tat ist es in der Zeitzone besser, wenn Sie eine * genaue * Vermutung haben, als wenn Sie direkt fragen (in meinem Fall). –

5

Wenn Sie nur den Offset von UTC kennen, können Sie aufgrund der Sommerzeit nicht feststellen, in welcher Zeitzone Sie sich befinden. Sie könnten in Betracht ziehen, den Zeitpunkt der Zeit zu betrachten, um zu erraten, ob DST damals wirksam war oder nicht, aber politische Erwägungen machen dies nahezu unmöglich, da verschiedene Rechtsordnungen die Definition von DST ändern.

1

Mit ein paar Tricks können Sie 99% der Zeit korrigieren und die anderen 1% schließen. Schauen Sie sich jstimezonedetect für eine extrem gründliche Implementierung an.

Ein armer Mann Ansatz wäre manuell jede mögliche berichtete Zeitzone Offset auf Ihre beste Schätzung abzubilden. Da Sie raten, können Sie auch genau darüber sprechen!