it-swarm.com.de

UTC / GMT-Zeit in Ortszeit umrechnen

Wir entwickeln eine C # -Anwendung für einen Webdienst-Client. Dies läuft auf Windows XP PC's.

Eines der vom Webdienst zurückgegebenen Felder ist ein DateTime-Feld. Der Server gibt ein Feld im GMT-Format zurück, d. H. Mit einem "Z" am Ende.

Wir haben jedoch festgestellt, dass .NET anscheinend eine implizite Konvertierung durchführt und die Zeit immer 12 Stunden abgelaufen ist.

Das folgende Codebeispiel behebt dies in gewissem Maße, indem die 12-Stunden-Differenz vergangen ist, die Sommerzeit in Neuseeland jedoch nicht berücksichtigt wird.

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

Stand diese Datumsseite :

UTC/GMT-Versatz

Standardzeitzone: UTC/GMT +12 Stunden
Sommerzeit: +1 Stunde
Aktuelle Zeitzonenverschiebung: UTC/GMT +13 Stunden

Wie stellen wir uns auf die zusätzliche Stunde ein? Kann dies programmgesteuert erfolgen oder ist dies eine Einstellung auf dem PC?

284
nzpcmad

Für Zeichenfolgen wie 2012-09-19 01:27:30.000, DateTime.Parse kann nicht sagen, aus welcher Zeitzone Datum und Uhrzeit stammen.

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

  • Nicht spezifiziert
  • Lokal
  • Koordinierte Weltzeit

[~ # ~] note [~ # ~] Wenn Sie ein anderes Datum/eine andere Uhrzeit als UTC oder Ihre Ortszeit angeben möchten zone, dann solltest du DateTimeOffset . verwenden


Also für den Code in Ihrer Frage:

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

Sie sagen, Sie wissen, welche Art es ist, also sagen Sie es.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

Sobald das System die UTC-Zeit kennt, können Sie einfach ToLocalTime aufrufen:

DateTime dt = convertedDate.ToLocalTime();

So erhalten Sie das gewünschte Ergebnis.

363
Drew Noakes

Ich würde die Verwendung der System.TimeZoneInfo-Klasse untersuchen, 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);
117
TimeZone.CurrentTimeZone.ToLocalTime(date);
50
coder1

DateTime Objekte haben standardmäßig den Kind von Unspecified, der für die Zwecke von ToLocalTime als UTC angenommen wird.

Um die Ortszeit eines UnspecifiedDateTime Objekts zu erhalten, müssen Sie daher nur Folgendes tun:

convertedDate.ToLocalTime();

Der Schritt, den Kind des DateTime von Unspecified in UTC zu ändern, ist nicht erforderlich. Unspecified wird für die Zwecke von UTC als ToLocalTime angenommen: http://msdn.Microsoft.com/en-us/library/system.datetime) .tolocaltime.aspx

23
CJ7

Ich weiß, dass dies eine ältere Frage ist, aber ich bin auf eine ähnliche Situation gestoßen und wollte mitteilen, was ich für zukünftige Suchende gefunden habe, möglicherweise auch für mich :).

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

Wenn das DateTime von einem Web-Service oder einer anderen Quelle mit einem bekannten Format stammt, sollten Sie etwas in Betracht ziehen

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 Datum und Uhrzeit bereits UTC sind. Die Kombination von AssumeUniversal und AdjustToUniversal weist es an, das Ergebnis nicht in die "lokale" Zeit umzuwandeln. Dies wird standardmäßig versucht. (Ich persönlich versuche sowieso, mich ausschließlich mit UTC in den Schichten Geschäft/Anwendung/Service zu befassen. Aber die Umstellung auf Ortszeit zu umgehen, beschleunigt die Dinge ebenfalls - in meinen Tests um 50% oder mehr, siehe unten.)

Folgendes haben wir zuvor gemacht:

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

Wir hatten die App profiliert und festgestellt, dass DateTime.Parse einen signifikanten Prozentsatz der CPU-Auslastung darstellt. (Übrigens war der Konstruktor CultureInfo not ein wesentlicher Faktor für die CPU-Auslastung.)

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

16
David

Ich möchte nur einen allgemeinen Hinweis zur Vorsicht hinzufügen.

Wenn Sie lediglich die aktuelle Uhrzeit von der internen Uhr des Computers abrufen, um ein Datum/eine Uhrzeit auf dem Display oder in einem Bericht anzuzeigen, ist alles in Ordnung. Aber wenn ja sparen die Datums-/Uhrzeitangaben zur späteren Bezugnahme oder rechnen Datum/Uhrzeit, Vorsicht!

Angenommen, Sie stellen fest, dass ein Kreuzfahrtschiff am 20. Dezember 2007 um 15:00 UTC in Honolulu eingetroffen ist. Und Sie möchten wissen, wie spät es war.
1. Es sind wahrscheinlich mindestens drei "Einheimische" beteiligt. Lokal kann Honolulu bedeuten, oder es kann bedeuten, wo sich Ihr Computer befindet, oder es kann der Ort bedeuten, an dem sich Ihr Kunde befindet.
2. Wenn Sie die eingebauten Funktionen verwenden, um die Konvertierung durchzuführen, ist dies wahrscheinlich falsch. Dies liegt daran, dass (wahrscheinlich) die Sommerzeit auf Ihrem Computer aktiv ist, diese jedoch im Dezember NICHT aktiv war. Aber Windows weiß das nicht ... alles, was es hat, ist ein Flag, um zu bestimmen, ob die Sommerzeit aktuell aktiv ist. Und wenn es gerade in Kraft ist, 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 andere Länder dies auch tun, nur weil sich Ihr Land zu einem bestimmten Zeitpunkt ändert.

14
Mark T

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

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

Wie stellen wir uns auf die zusätzliche Stunde ein?

Sofern nicht anders angegeben, verwendet .net die lokalen PC-Einstellungen. Ich habe gelesen: http://msdn.Microsoft.com/en-us/library/system.globalization.daylighttime.aspx

Der Code könnte ungefähr so ​​aussehen:

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

Und wie oben erwähnt, überprüfen Sie noch einmal, auf welcher Zeitzone sich Ihr Server befindet. Es gibt Artikel im Internet, in denen erläutert wird, wie Sie die Änderungen in IIS sicher beeinflussen können.

4
Brendan Kowitz
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
4
Prince Prasad

Als Antwort auf Danas Vorschlag:

Das Codebeispiel sieht nun folgendermaßen 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 der 20.08.08; Die Art war UTC.

Sowohl "convertDate" als auch "dt" sind gleich:

21.08.08 10:00:26; Die Art war lokal

2
nzpcmad

Ich bin auf diese Frage gestoßen, als ich ein Problem mit den UTC-Daten hatte, die Sie über die Twitter-API zurückerhalten (Feld created_at für einen Status). Ich muss sie in DateTime konvertieren. Keines der Antworten/Codebeispiele in den Antworten auf dieser Seite hat ausgereicht, um zu verhindern, dass ich den Fehler "Zeichenfolge wurde nicht als gültige Datums- und Uhrzeitangabe erkannt" erhalte (dies ist jedoch der Fehler, der meiner Suche nach der richtigen Antwort auf SO am nächsten kommt).

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

1
DannykPowell

Ich hatte das Problem, dass in einem Datensatz, der über die Leitung übertragen wurde (Webservice zum Client), dieser automatisch geändert wurde, weil das Feld "DateType" von DataColumn auf "local" gesetzt war. Stellen Sie sicher, dass Sie den Datumstyp überprüfen, wenn Sie DataSets übertragen.

Wenn Sie nicht möchten, dass es sich ändert, setzen Sie es auf Nicht angegeben

1
Miles