C # DateTime.ToString mit zzz bricht im Dotnet-Framework, aber nicht im Dotnet-Kern
Ich habe meine Ortszeit in GMT +01: 00 als Schreibzeit. Ich erlebe etwas, was für mich unerwartet ist, wenn ich einen ToString auf folgende Weise durchführe. Auf geht's:
Demonstration der lokalen Systemeinstellungen mit einer Zeitzone von +01: 00 (alle diese laufen grün):
var myLocalDate = new DateTime(2020, 11, 25, 08, 00, 00, DateTimeKind.Local);
Assert.AreEqual("2020-11-25T08:00:00+01:00", myLocalDate.ToString(@"yyyy-MM-dd\THH:mm:sszzz"));
Assert.AreEqual(DateTimeKind.Local, myLocalDate.Kind);
Assert.AreEqual(myLocalDate, myLocalDate.ToLocalTime());
Und jetzt erstelle ich dieselbe Zeit in utc, indem ich manuell eine Stunde subtrahiere und das "utc" als Art spezifiziere. Aber wenn ich ToString aufrufe, wird die Zeitzone als +01: 00 geschrieben, was ich als +00: 00 erwarten würde:
var myUtcDate = new DateTime(2020, 11, 25, 07, 00, 00, DateTimeKind.Utc);
// THIS Breaks:
Assert.AreEqual("2020-11-25T07:00:00+00:00", myUtcDate.ToString(@"yyyy-MM-dd\THH:mm:sszzz"));
Fehlermeldung:
Nachricht: Assert.AreEqual fehlgeschlagen. Erwartet: <2020-11-25T07: 00: 00 + 00: 00>. Tatsächlich: <2020-11-25T07: 00: 00 + 01: 00>.
Vermisse ich hier etwas über Datumsangaben und Formate oder ist dies möglicherweise ein bekannter Fehler?
Ich führe .Net Framework 4.8 aus
In diesem Beitrag geht es um dasselbe Problem, wie ich sehe: So beheben Sie den DateTimeInvalidLocalFormat-Fehler: "Eine UTC DateTime wird in Text in einem Format konvertiert, das nur für Ortszeiten korrekt ist."
AKTUALISIEREN:
Das Ausführen des folgenden Programms führt zu unterschiedlichen Ergebnissen im Dotnet-Framework und im Dotnet-Kern (wie von evk erwähnt):
Console.WriteLine(new DateTime(2025, 11, 25, 07, 00, 00, DateTimeKind.Utc).ToString(@"yyyy-MM-dd\THH:mm:sszzz"));
Dotnet-Kerndrucke:
2020-11-25T07: 00: 00 + 00: 00
Dotnet-Framework-Drucke:
2020-11-25T07: 00: 00 + 01: 00
Wenn Sie das Dotnet-Framework im Debug-Modus ausführen, wird die folgende Meldung des Debug-Assistenten angezeigt, die jedoch in DateTime.ToString () intern ignoriert wird:
Verwalteter Debugging-Assistent 'DateTimeInvalidLocalFormat': 'Eine UTC DateTime wird in Text in einem Format konvertiert, das nur für Ortszeiten korrekt ist. Dies kann passieren, wenn DateTime.ToString mit dem Formatbezeichner 'z' aufgerufen wird, der einen lokalen Zeitzonenversatz in der Ausgabe enthält. Verwenden Sie in diesem Fall entweder den Formatbezeichner 'Z', der eine UTC-Zeit angibt, oder die Zeichenfolge 'o', mit der empfohlen wird, eine DateTime im Text beizubehalten. Dies kann auch auftreten, wenn eine DateTime übergeben wird, die von XmlConvert oder DataSet serialisiert werden soll. Wenn Sie XmlConvert.ToString verwenden, übergeben Sie XmlDateTimeSerializationMode.RoundtripKind, um die Serialisierung korrekt durchzuführen. Wenn Sie DataSet verwenden, setzen Sie den DateTimeMode für das DataColumn-Objekt auf DataSetDateTime.Utc. '
Antworten
Nein, es verhält sich wie dokumentiert. Aus der Dokumentation des zzzFormatbezeichners (Schwerpunkt Mine):
Bei
DateTime
Werten repräsentiert der benutzerdefinierte Formatbezeichner "zzz" den vorzeichenbehafteten Versatz der Zeitzone des lokalen Betriebssystems von UTC, gemessen in Stunden und Minuten. Es spiegelt nicht den Wert derDateTime.Kind
Eigenschaft einer Instanz wider . Aus diesem Grund wird der Formatbezeichner "zzz" für die Verwendung mitDateTime
Werten nicht empfohlen .
Das ist wohl unglücklich, aber kein Fehler.
Beachten Sie, dass sich .NET Core (und .NET 5.0) anscheinend nicht wie dokumentiert verhalten. Während Sie argumentieren könnten, dass es in .NET Core "behoben" ist, würde ich vorschlagen, dass ein undokumentiertes Verhalten ein Fehler an sich ist und die Codemigration schwieriger als erwartet machen könnte.
Ich schlage vor, dass Sie der Empfehlung in den Dokumenten folgen und die Verwendung zzz
mit DateTime
Werten vermeiden . Ich würde auch vorschlagen, stattdessen meine Noda Time- Bibliothek zu verwenden, bei der es keine Mehrdeutigkeit in Bezug auf den Wert "vielleicht lokal oder vielleicht UTC sein" gibt, aber das ist eine etwas andere Sache. (Ich würde nicht erwarten, dass Sie mit Noda Time auf dieses Problem stoßen, und Ihr anderer Datums- / Zeitcode wäre hoffentlich klarer.)