Durch Deserialisieren der JSON-Zeichenfolge in .NET DateTime in der lokalen Zeitzone werden zwei Stunden hinzugefügt
Wenn ich diesen JSON-String "2020-10-05T07: 29: 00 + 00: 00" auf meinem lokalen PC in ein DateTime-Objekt deserialisiere, endet er als 2020-10-05 09:29, wo er 07:29 sein sollte. Das Datum wird als lokal angegeben (+00: 00), daher verstehe ich nicht, woher die zusätzlichen zwei Stunden kommen. Ich habe versucht, diese Frage zu betrachten. Die Deserialisierung der Datetime-Zeitzone, aber das Konvertieren des Datums mit .ToLocalTime () führt zu nichts.
Der Kontext ist eine große JSON-Zeichenfolge mit Flughäfen von einer externen API mit vielen Datenzeiten, einige sind UTC, andere sind Ortszeiten. Ich muss den einfachsten Weg finden, um den String zu deserialisieren, der die richtigen Datumszeiten erzeugt.
Beachten Sie, dass die Ortszeit überall auf der Welt liegen kann und daher nicht vom Server abhängen sollte, auf dem die Anwendung ausgeführt wird.
Hier ist ein Codebeispiel mit NewtonSoft.Json zum Deserialisieren:
static void Main(string[] args)
{
var json =
"{\"UTC\": \"2020-10-05T05:29:00Z\",\"Local\": \"2020-10-05T07:29:00+00:00\" }";
var expected = new DateTime(2020,10,5,7,29,0);
var foo = JsonConvert.DeserializeObject<CustomTime>(json);
Console.WriteLine($"UTC:{foo.UTC} ({foo.UTC.Kind}).\r\nLOC:{foo.Local} ({foo.Local.Kind})");
System.Console.WriteLine(foo.Local.Equals(expected) ? "All good" : "Conversion failed");
}
public sealed class CustomTime
{
public DateTime UTC { get; set; }
public DateTime Local { get; set; }
}
Dies ist meine Ausgabe in meiner Zeitzone (UTC +2 DaylightSavingTime):
UTC: 05-10-2020 05:29:00 (Utc). LOC: 05-10-2020 09:29:00 (Lokal) Konvertierung fehlgeschlagen
Hier ist eine Dotnet-Geige https://dotnetfiddle.net/uHLdAh Dies erzeugt die korrekte Ausgabe, da auf dem Server wahrscheinlich GMT ausgeführt wird.
Antworten
Das Problem ist, dass "2020-10-05T07: 29: 00 + 00: 00" keine Ortszeit ist, sondern als UTC-Zeit mit einem Versatz von 0 Stunden interpretiert wird. Wenn Sie es auf Ihrem Computer ausführen, wird der Versatz Ihrer aktuellen Zeitzone hinzugefügt, dh +02: 00h.
Zum Beispiel ist die Zeit jetzt 08:36 und meine Zeitzone ist MEZ. Wenn ich ein DateTimeOffset-Objekt in UTC erstellen würde, würde dies 2020-11-27T06: 36: 00 + 02: 00 sagen.
Das Ausführen des folgenden Codes führt also je nach Zeitzone des ausführenden Computers zu unterschiedlichen Ergebnissen:
// Current time
dto = DateTimeOffset.Now;
Console.WriteLine(dto.LocalDateTime);
// UTC time
dto = DateTimeOffset.UtcNow;
Console.WriteLine(dto.LocalDateTime);
Ausgabe bei Ausführung auf dotnetfiddle.net:
3/11/2007 10:30:00 AM
3/11/2007 9:30:00 AM
Ausgabe bei Ausführung auf meinem lokalen Computer:
2020-11-27 08:54:09
2020-11-27 08:54:09
Sie müssen feststellen, ob Ihre Eingabe in UTC-Zeit mit einem korrekten Versatz von 0 oder in "lokaler" Zeit mit einem fehlerhaften Versatz erfolgt. Dann sollten Sie ein DateTimeOffset-Objekt erstellen müssen, das die Zeitzone angibt, die das neue datetime-Objekt haben soll.
var dto = new DateTimeOffset(2020,10,5,7,29,0, new TimeSpan(2, 0, 0));
Console.WriteLine(dto);
Console.WriteLine(dto.LocalDateTime.Kind);
Console.WriteLine(dto.UtcDateTime);
Console.WriteLine(dto.UtcDateTime.Kind);
Was die folgende Ausgabe ergibt:
2020-10-05 07:29:00 +02:00
Local
2020-10-05 05:29:00
Utc
Sie haben jetzt ein DateTimeOffset-Objekt, das sich wie erwartet verhält.
Die Lösung des Problems erwies sich als einfach. Nehmen Sie einfach an, dass alle Zeiten UTC sind. Dies behebt alle Probleme bei der Konvertierung.
var foo = JsonConvert.DeserializeObject<CustomTime>(json, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});