UTC / GMT-Zeit in Ortszeit umrechnen

Wir entwickeln eine C # -Anwendung für einen Web-Service-Client. Dies wird auf Windows XP PCs ausgeführt.

Eines der vom Webdienst zurückgegebenen Felder ist ein DateTime-Feld. Der Server gibt ein Feld im GMT-Format zurück, dh mit einem “Z” am Ende.

Wir haben jedoch festgestellt, dass .NET eine Art impliziter Konvertierung zu tun scheint und die Zeit war immer 12 Stunden.

Das folgende Codebeispiel behebt dies in einem gewissen Ausmaß, da der 12-Stunden-Unterschied verschwunden ist, aber die Sommerzeit in Neuseeland nicht berücksichtigt wird.

CultureInfo ci = new CultureInfo("en-NZ"); string date = "Web service date".ToString("R", ci); DateTime convertedDate = DateTime.Parse(date); 

Gemäß dieser Datumssite :

UTC / GMT Offset

Standardzeitzone: UTC / GMT +12 Stunden
Sommerzeit: +1 Stunde
Aktueller Zeitzonen-Offset: UTC / GMT +13 Stunden

Wie passen wir uns für die zusätzliche Stunde an? Kann dies programmgesteuert erfolgen oder ist dies eine Art Einstellung auf dem PC?

Bei Strings wie 2012-09-19 01:27:30.000 kann DateTime.Parse nicht feststellen, aus welcher Zeitzone Datum und Uhrzeit stammen.

DateTime hat eine Kind- Eigenschaft, die eine von drei Zeitzonenoptionen haben kann:

  • Nicht spezifiziert
  • Lokal
  • Koordinierte Weltzeit

HINWEIS Wenn Sie ein anderes Datum / eine andere Uhrzeit als UTC oder Ihre lokale Zeitzone darstellen möchten, sollten Sie DateTimeOffset .


Also für den Code in deiner Frage:

 DateTime convertedDate = DateTime.Parse(dateStr); var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified 

Du sagst du weißt was es ist, also sag es.

 DateTime convertedDate = DateTime.SpecifyKind( DateTime.Parse(dateStr), DateTimeKind.Utc); var kind = convertedDate.Kind; // will equal DateTimeKind.Utc 

Sobald das System seine Zeit in UTC kennt, können Sie einfach ToLocalTime :

 DateTime dt = convertedDate.ToLocalTime(); 

Dadurch erhalten Sie das gewünschte Ergebnis.

Ich würde in der Verwendung der System.TimeZoneInfo-class prüfen, wenn Sie in .NET 3.5 sind. Siehe http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx . Dies sollte die Änderungen der Sommerzeit korrekt berücksichtigen.

 // Coordinated Universal Time string from // DateTime.Now.ToUniversalTime().ToString("u"); string date = "2009-02-25 16:13:00Z"; // Local .NET timeZone. DateTime localDateTime = DateTime.Parse(date); DateTime utcDateTime = localDateTime.ToUniversalTime(); // ID from: // "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone" // See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx string nzTimeZoneKey = "New Zealand Standard Time"; TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey); DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone); 
 TimeZone.CurrentTimeZone.ToLocalTime(date); 

DateTime Objekte haben standardmäßig den ToLocalTime Unspecified , der für ToLocalTime als UTC .

Um die Ortszeit eines Unspecified DateTime Objekts zu ermitteln, müssen Sie DateTime tun:

 convertedDate.ToLocalTime(); 

Der Schritt zum Ändern der Kind der DateTime von Unspecified zu UTC ist nicht DateTime . Unspecified wird für die Zwecke von ToLocalTime als UTC ToLocalTime : http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

Ich weiß, dass dies eine ältere Frage ist, aber ich stieß auf eine ähnliche Situation, und ich wollte teilen, was ich für zukünftige Sucher gefunden hatte, möglicherweise einschließlich mich selbst :).

DateTime.Parse() kann schwierig sein – siehe hier zum Beispiel.

Wenn die DateTime von einem Web-Service oder einer anderen Quelle mit einem bekannten Format stammt, möchten Sie vielleicht etwas wie

 DateTime.ParseExact(dateString, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) 

oder, noch besser,

 DateTime.TryParseExact(...) 

Das Flag ” AssumeUniversal teilt dem Parser mit, dass das Datum / die Uhrzeit bereits UTC ist. Die Kombination von AssumeUniversal und AdjustToUniversal , dass das Ergebnis nicht in “lokale” Zeit umgewandelt wird. Dies wird standardmäßig versucht. (Ich versuche persönlich, mich ausschließlich mit UTC in der Business / Application / Service-Schicht zu beschäftigen. Aber die Umrechnung auf Ortszeit beschleunigt auch die Dinge – um 50% oder mehr in meinen Tests, siehe unten.)

Folgendes haben wir vorher gemacht:

 DateTime.Parse(dateString, new CultureInfo("en-US")) 

Wir hatten die App profiliert und festgestellt, dass die DateTime.Parse einen signifikanten Prozentsatz der CPU-Auslastung darstellte. (Der CultureInfo Konstruktor trug CultureInfo nicht wesentlich zur CPU-Nutzung bei.)

Also habe ich eine Konsolen-App eingerichtet, um eine Datum / Zeit-Zeichenfolge 10000 Mal auf verschiedene Arten zu analysieren. Endeffekt:
Parse() 10 Sek
ParseExact() (Umwandlung in Lokal) 20-45 ms
ParseExact() (konvertiert nicht zu local) 10-15 ms
… und ja, die Ergebnisse für Parse() sind in Sekunden , während die anderen in Millisekunden sind .

Ich möchte nur eine allgemeine Anmerkung zur Vorsicht hinzufügen.

Wenn Sie nur die aktuelle Uhrzeit von der internen Uhr des Computers abrufen, um ein Datum / eine Uhrzeit auf dem Display oder einem Bericht anzuzeigen, ist alles in Ordnung. Aber wenn Sie die Datums- / Uhrzeitinformationen zur späteren Bezugnahme speichern oder Datum und Uhrzeit des Computers angeben, sollten Sie sich in Acht nehmen!

Nehmen wir an, Sie bestimmen, dass ein Kreuzfahrtschiff am 20. Dezember 2007 um 15:00 UTC in Honolulu angekommen ist. Und Sie möchten wissen, welche Ortszeit das war.
1. Es sind wahrscheinlich mindestens drei “Einheimische” beteiligt. Lokal kann bedeuten, dass es sich um Honolulu handelt, oder es kann bedeuten, wo sich Ihr Computer befindet, oder es kann der Ort sein, an dem sich Ihr Kunde befindet.
2. Wenn Sie die integrierten functionen verwenden, um die Konvertierung durchzuführen, wird es wahrscheinlich falsch sein. Dies liegt daran, dass die Sommerzeit (wahrscheinlich) derzeit auf Ihrem Computer wirksam ist, aber im Dezember NICHT in Kraft war. Aber Windows weiß das nicht … Alles, was es hat, ist eine Flagge, um zu bestimmen, ob die Sommerzeit gerade in Kraft ist. Und wenn es gerade in Kraft ist, dann wird es sogar zu einem Datum im Dezember eine Stunde hinzufügen.
3. Die Sommerzeit wird in verschiedenen politischen Bereichen unterschiedlich (oder gar nicht) umgesetzt. Denken Sie nicht, dass nur, weil sich Ihr Land zu einem bestimmten Zeitpunkt ändert, auch andere Länder dies tun werden.

Vergessen Sie nicht, wenn Sie bereits ein DateTime-Objekt haben und nicht sicher sind, ob es UTC oder Local ist, ist es einfach genug, die Methoden für das Objekt direkt zu verwenden:

 DateTime convertedDate = DateTime.Parse(date); DateTime localDate = convertedDate.ToLocalTime(); 

Wie passen wir uns für die zusätzliche Stunde an?

Sofern nicht anders angegeben, verwendet .net die lokalen PC-Einstellungen. Ich würde lesen: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

Nach dem Aussehen könnte der Code etwa so aussehen:

 DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year ); 

Und wie bereits erwähnt, überprüfen Sie, welche Zeitzoneneinstellung Ihr Server hat. Es gibt Artikel im Internet, um die Änderungen in IIS sicher zu beeinflussen.

Als Antwort auf Danas Vorschlag:

Das Codebeispiel sieht jetzt so aus:

 string date = "Web service date"..ToString("R", ci); DateTime convertedDate = DateTime.Parse(date); DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate); 

Das ursprüngliche Datum war 20/08/08; die Art war UTC.

Sowohl “convertedDate” als auch “dt” sind gleich:

21/08/08 10:00:26; die Art war lokal

Ich hatte das Problem damit, dass ein Datensatz über die Leitung (Webservice zu Client) geschoben wurde, der automatisch geändert würde, weil das DateType-Feld der DataColumn auf local gesetzt war. Stellen Sie sicher, dass Sie überprüfen, was DateType ist, wenn Sie DataSets übergreifend ausführen.

Wenn Sie nicht möchten, dass es sich ändert, legen Sie es auf “Nicht angegeben” fest

Ich bin auf diese Frage gestoßen, da ich ein Problem mit den UTC-Daten hatte, die Sie über die Twitter-API erhalten (created_at-Feld in einem Status). Ich muss sie in DateTime konvertieren. Keine der Antworten / Codebeispiele in den Antworten auf dieser Seite war ausreichend, um mich daran zu hindern, den Fehler “Zeichenfolge wurde nicht als gültige DateTime erkannt” zu erhalten (aber es ist am nächsten, dass ich die richtige Antwort auf SO finden muss)

Wenn du diesen Link hier schreibst, falls dies jemand anderem hilft – die Antwort, die ich brauchte, wurde in diesem Blogbeitrag gefunden: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ – Verwenden Sie DateTime.ParseExact grundsätzlich mit einer Format-Zeichenfolge anstelle von DateTime.Parse

 @TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)