2010-07-06 3 views
25

Ich habe eine Klasse, die ich serialisieren/deserialize mit XmlSerializer. Diese Klasse enthält ein Feld DateTime.Verhindern Zeitzone Konvertierung bei der Deserialisierung von DateTime Wert

Bei der Serialisierung wird das Feld DateTime durch eine Zeichenfolge dargestellt, die den Offset von GMT enthält, z. B. 2010-05-05T09:13:45-05:00. Bei der Deserialisierung werden diese Zeiten in die lokale Zeit der Maschine umgewandelt, die die Deserialisierung durchführt.

Aus Gründen, die nicht zu erklären sind, möchte ich verhindern, dass diese Zeitzonenumwandlung stattfindet. Die Serialisierung findet in der freien Wildbahn statt, wo mehrere Versionen dieser Klasse existieren. Die Deserialisierung findet auf einem Server statt, der unter meiner Kontrolle steht. Daher scheint es, dass dies während der Deserialisierung am besten gehandhabt wird.

Wie kann ich dies erreichen, außer IXmlSerializable implementieren und die gesamte Deserialisierung "von Hand"?

+0

Kann jemand mir einen Link auf die genaue umgekehrt von dieser Frage geben? (Übergabe von DateTime vom .Net Server zum JavaScript Client) – Siddhant

Antwort

22

Anstatt als DateTime zu analysieren, können Sie es als analysieren und die DateTimeOffset.DateTime Eigenschaft verwenden, um die Zeitzone zu ignorieren. Wie folgt aus:

[XmlIgnore()] 
public DateTime Time { get; set; } 

[XmlElement(ElementName = "Time")] 
public string XmlTime 
{ 
    get { return XmlConvert.ToString(Time, XmlDateTimeSerializationMode.RoundtripKind); } 
    set { Time = DateTimeOffset.Parse(value).DateTime; } 
} 
+0

Da ich Entity Framework verwende, musste ich [NotMapped] auf das [XmlElement ...] setzen, aber diese Lösung funktioniert perfekt für mich. Danke –

2

Könnten Sie versuchen, so etwas wie this Post schlägt und eine neue String-Eigenschaft machen und XmlIgnore die bestehenden:

Put [XmlIgnore] auf der Zeit Eigenschaft.

Dann eine neue Eigenschaft hinzu:

[XmlElement(DataType="string",ElementName="Time")] 
public String TimeString 
{ 
    get { return this.timeField.ToString("yyyy-MM-dd"); } 
    set { this.timeField = DateTime.ParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture); } 
} 
+0

Ich muss alte Versionen der Klasse mit der aktualisierten Version deserialisieren. Wird das die Kompatibilität nicht zerstören? Ich kann meine DateTime-Eigenschaft umbenennen und eine Zeichenfolgeneigenschaft hinzufügen, die denselben Namen hat, an dem auch die DateTime-Eigenschaft verwendet wurde. Dies wird jedoch Clients brechen, die auf die DateTime-Eigenschaft verweisen. – Odrade

+1

Oh, ich sehe jetzt, dass der Elementname im Xml gleich bleibt. Lass mich das ausprobieren. – Odrade

+1

Dieser Code wird nicht mit Ihren vorhandenen Clients funktionieren, da DateTime.ParseExact fehlschlägt (da die Zeit nicht in diesem Format ist). Wenn Sie stattdessen ein DateTimeOffset analysieren, funktioniert es mit Ihren vorhandenen Clients. –

2

Ich weiß, das ist alt, aber hoffen, dass dies jemand in der Zukunft hilft. Hier

ist das XML-I wurde Deserialisieren:

<timePeriod>1982-03-31T00:00:00+11:00</t 

Nach Deserialisieren des XML ich mit dem 30. am Ende nicht der 31.:

enter image description here

Es erscheint die dritte Partei, die produzieren Dieses XML (das ich verwende) ändert die Zeitzone während der Sommerzeit auf +11 und behält es als +10, wenn es nicht Sommerzeit (DST) ist.

Laut Jon Skeet UTC sollte DST nicht berücksichtigen: https://stackoverflow.com/a/5495816/495455


auch die Dokumentation beachten Coding Best Practices Using DateTime in the .NET Framework:

Die XML-Serializer geht immer davon aus, dass die Werte Datetime lokale Maschinenzeit serialisiert darstellen, so Es wendet den lokalen Zeitzonenoffset der Maschine als Offset-Teil der codierten XML-Zeit an. Wenn wir dies auf einer anderen Maschine deserialisieren, wird der ursprüngliche Offset von dem analysierten Wert subtrahiert und der Zeitzonen-Offset der aktuellen Maschine wird hinzugefügt.


Der folgende Code erlaubt mir das Datum als 31. formatiert zu bekommen, aber es funktionieren wird nicht 100% für nicht Daylioght Speichern von Daten (in diesem Feed angegeben):

TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time"); 
DateTime easternTimeNow = TimeZoneInfo.ConvertTimeFromUtc(dataPoint.timePeriod, easternZone); 
System.Diagnostics.Debug.WriteLine(easternTimeNow.ToString()); 

Daher ist die Lösung Fixieren Sie den XML-Feed, so dass keine UTCs mit DST alternieren.

EDIT:, warum die Daten nach oben geschraubt wurden

Da es sich nicht der 3rd-Party-Anbieter stellt sich heraus, die UTC mit dem DST ändern. Der XML-Feed wird vom Java Swing-Framework erstellt, indem ein SQL-DB gelesen wird. Normalerweise würde ich empfehlen, bei der XML-Standarddarstellung (xsd: dateTime) zu bleiben - IS0 8601, aber in diesem Fall mit string und ripping alles nach dem T funktioniert. Haftungsausschluss, ich versuche immer noch, den Feed geändert zu bekommen, empfehle Ihnen, dies nicht in PROD zu tun. Benutzung auf eigene Gefahr!!

27

Was ich tat, war es Methode zu verwenden DateTime.SpecifyKind, wie folgend:

DateTime dateTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified); 

Und das ist mein Problem zu beheben, ich hoffe, diese Hilfe Sie.