Zeitzone von DateTime abrufen

103

Enthält die .Net DateTime Informationen zur Zeitzone, in der sie erstellt wurde?

Ich habe eine Bibliothek, die DateTime aus einem Format mit "+ zz" am Ende analysiert. Während sie korrekt analysiert und eine Ortszeit anpasst, muss ich aus dem DateTime-Objekt die spezifische Zeitzone abrufen.

Ist das überhaupt möglich? Ich kann nur DateTime.Kind sehen, das angibt, ob die Zeit lokal oder UTC ist.

dbkk
quelle
Weitere Informationen zum Umgang mit Zeitzonen und DateTimeStyles finden Sie in den Hinweisen zur DateTime.Parse-Dokumentation . Aber nein, was Sie wollen, ist nicht wirklich möglich.
Jojo

Antworten:

136

DateTime selbst enthält keine echten Zeitzoneninformationen. Es kann wissen, ob es UTC oder lokal ist, aber nicht, was lokal wirklich bedeutet.

DateTimeOffset ist etwas besser - das ist im Grunde eine UTC-Zeit und ein Offset. Dies reicht jedoch immer noch nicht aus, um die Zeitzone zu bestimmen, da viele verschiedene Zeitzonen zu jedem Zeitpunkt den gleichen Versatz haben können. Dies scheint jedoch gut genug für Sie zu sein, da Sie beim Parsen von Datum und Uhrzeit nur mit dem Offset arbeiten müssen.

Die Unterstützung für Zeitzonen ab .NET 3.5 ist viel besser als zuvor, aber ich würde wirklich gerne eine Standard- "ZonedDateTime" oder ähnliches sehen - eine UTC-Zeit und eine tatsächliche Zeitzone. Es ist einfach, eigene zu erstellen, aber es wäre schön, sie in den Standardbibliotheken zu sehen.

EDIT: Fast vier Jahre später würde ich jetzt vorschlagen, Noda Time zu verwenden, das eine größere Auswahl an Datums- / Zeittypen aufweist. Ich bin jedoch voreingenommen, als Hauptautor von Noda Time :)

Jon Skeet
quelle
2
Das PublicDomain-Projekt auf CodePlex erledigt dies für Sie.
Cheeso
Eine TimeZone-Aufzählung in der BCL wäre schön, wenn die Weltzeitzonen statisch sind und sich nicht ändern.
Jeff LaFay
1
@jlafay: Sie ändern sich jedoch - beispielsweise wurden erst im letzten Jahr mehr Zeitzonen zu Windows hinzugefügt.
Jon Skeet
Dieses Projekt wird vom Autor nicht mehr gepflegt. publicdomain.codeplex.com Es scheint, als ob dies hilfreich sein könnte. Abhängig von der Verwendung muss man es einstellen, bevor man es verwendet. timezone.codeplex.com
AnneTheAgile
3
@ AnneTheAgile: Persönlich würde ich natürlich empfehlen, meine eigene Noda Time Bibliothek zu verwenden :)
Jon Skeet
36

Nein.

Ein Entwickler ist dafür verantwortlich, die mit einem DateTime-Wert verknüpften Zeitzoneninformationen über einen externen Mechanismus zu verfolgen.

Ein Zitat aus einem ausgezeichneten Artikel hier . Ein Muss für jeden .Net-Entwickler.

Mein Rat ist also, eine kleine Wrapper-Klasse zu schreiben, die Ihren Anforderungen entspricht.

Gerrie Schenck
quelle
2

Sie können die TimeZoneInfo- Klasse verwenden

Die TimeZone-Klasse erkennt die lokale Zeitzone und kann Zeiten zwischen der koordinierten Weltzeit (UTC) und der Ortszeit konvertieren. Ein TimeZoneInfo-Objekt kann eine beliebige Zeitzone darstellen, und Methoden der TimeZoneInfo-Klasse können verwendet werden, um die Zeit in einer Zeitzone in die entsprechende Zeit in einer anderen Zeitzone zu konvertieren. Die Mitglieder der TimeZoneInfo-Klasse unterstützen die folgenden Vorgänge:

  1. Abrufen einer Zeitzone, die bereits vom Betriebssystem definiert wurde.

  2. Auflisten der Zeitzonen, die auf einem System verfügbar sind.

  3. Konvertieren von Zeiten zwischen verschiedenen Zeitzonen.

  4. Erstellen einer neuen Zeitzone, die noch nicht vom Betriebssystem definiert wurde.

    Serialisierung einer Zeitzone für den späteren Abruf.

Shekhar
quelle
1
... aber angesichts einer DateTime gibt es meines Wissens nach immer noch keine Möglichkeit, TimeZoneInfo zu verwenden, um die TimeZone der DateTime zu bestimmen.
Remi Despres-Smyth
@ RemiDespres-Smyth Ich speichere TimeZoneInfo zusammen mit DateTime in 1 Klasse.
Konrad
0

Im Allgemeinen besteht die Praxis darin, Daten als DateTime mit einer "Zeitzone" von UTC zu übergeben und dann ein TimeZoneInfo-Objekt zu übergeben. Wenn Sie bereit sind, die Daten anzuzeigen, verwenden Sie das TimeZoneInfo-Objekt, um die UTC DateTime zu konvertieren.

Die andere Option besteht darin, die DateTime mit der aktuellen Zeitzone festzulegen und dann sicherzustellen, dass die "Zeitzone" für das DateTime-Objekt unbekannt ist. Stellen Sie dann sicher, dass die DateTime erneut mit einer TimeZoneInfo übergeben wird, die die TimeZone der übergebenen DateTime angibt.

Wie andere hier angedeutet haben, wäre es schön, wenn Microsoft sich darauf einlassen und ein nettes Objekt erstellen würde, um alles zu erledigen, aber im Moment müssen Sie sich mit zwei Objekten befassen.

rauben
quelle
0

DateTime kennt seinen Zeitzonenversatz nicht. Es gibt keine integrierte Methode, um den Offset oder den Zeitzonennamen zurückzugeben (z. B. EAT, CEST, EST usw.).

Wie von anderen vorgeschlagen, können Sie Ihr Datum in UTC konvertieren:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

und dann nur die Differenz berechnen:

TimeSpan difference = localtime - utctime;

Sie können das DateTimeOffset auch einmal in ein anderes konvertieren:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Dies ist jedoch eine Art verlustbehaftete Komprimierung - der Offset allein kann Ihnen nicht sagen, um welche Zeitzone es sich handelt, da sich zwei verschiedene Länder in unterschiedlichen Zeitzonen befinden und nur für einen Teil des Jahres dieselbe Zeit haben (z. B. Südafrika und Europa). Beachten Sie auch, dass die Sommerzeit zu unterschiedlichen Zeitpunkten eingeführt werden kann (EST vs. CET - ein Unterschied von 3 Wochen).

Sie können den Namen Ihrer lokalen Systemzeitzone mithilfe der TimeZoneInfo-Klasse abrufen:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Ich stimme Gerrie Schenck zu, bitte lesen Sie den Artikel, den er vorgeschlagen hat.

Henryalligator
quelle