2010-07-06 7 views
25

Mam klasy, które serializuje/deserializacji przy użyciu XmlSerializer. Ta klasa zawiera pole DateTime.Zapobieganie konwersji strefy czasowej przy deserializacji wartości DateTime

Po serializacji pole DateTime jest reprezentowane przez ciąg znaków, który zawiera przesunięcie od GMT, np. 2010-05-05T09:13:45-05:00. Po deserializacji te czasy są konwertowane na lokalny czas maszyny przeprowadzającej deserializację.

Z powodów, które nie są warte wyjaśnienia, chciałbym zapobiec tej konwersji strefy czasowej. Serializacja dzieje się na wolności, gdzie istnieje wiele wersji tej klasy. Deserializacja dzieje się na serwerze, który jest pod moją kontrolą. W związku z tym wydaje się, że byłoby najlepiej obsłużyć podczas deserializacji.

Jak mogę to zrobić, poza wprowadzeniem IXmlSerializable i wykonaniem całej deserializacji "ręcznie?"

+0

Czy ktoś może podać mi link dokładnie na odwrót tego pytania? (Przekazywanie DateTime z serwera .Net do klienta JavaScript) – Siddhant

Odpowiedz

22

Zamiast analizować jako DateTime można przeanalizować go jako DateTimeOffset i użyć właściwości DateTimeOffset.DateTime, aby zignorować strefę czasową. Tak:

[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

Ponadto, ponieważ używam framework podmiotu, musiałem umieścić [NotMapped] na [XmlElement ...], ale to rozwiązanie działa idealnie dla mnie. dzięki –

2

można spróbować coś takiego this sugeruje postu i zrobić nową właściwość ciąg i XmlIgnore istniejący:

Put [XmlIgnore] na własność czasowa.

Następnie dodać nową właściwość:

[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

Potrzebuję deserializować stare wersje klasy przy użyciu zaktualizowanej wersji. Czy to nie złamie kompatybilności? Mogę zmienić nazwę mojej właściwości DateTime i dodać właściwość łańcucha o takiej samej nazwie, do której używał DateTime. Ale spowoduje to zerwanie klientów odwołujących się do właściwości DateTime. – Odrade

+1

Och, teraz widzę, że nazwa elementu pozostanie taka sama w Xml. Pozwól mi to wypróbować. – Odrade

+1

Ten kod nie będzie działać z istniejącymi klientami, ponieważ parametr DateTime.ParseExact zakończy się niepowodzeniem (ponieważ czas nie jest w tym formacie). Jeśli analizujesz jako DateTimeOffset, będzie on działał z Twoimi istniejącymi klientami. –

2

wiem, że to jest stary, ale mam nadzieję, że to pomoże komuś w przyszłości.

Oto XML byłem deserializacji:

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

Po deserializacji XML I skończyć z 30 a nie 31:

enter image description here

Wydaje się 3rd party, które wytwarzają ten XML (którego używam) zmienia strefę czasową na +11 podczas zmiany czasu na letni i zachowuje ją jako +10, gdy nie jest to Daylight Saving (DST).

Według Jon Skeet UTC nie powinny rozważyć DST: https://stackoverflow.com/a/5495816/495455


pamiętać także dokumentację Coding Best Practices Using DateTime in the .NET Framework:

serializer XML zawsze zakłada, że ​​wartości DateTime są szeregowane reprezentować lokalną czas maszynowy, tak stosuje przesunięcie strefy lokalnej czasu maszyny jako część przesuniętą zakodowanego czasu XML. Kiedy deserializujemy to na inną maszynę, pierwotne przesunięcie jest odejmowane od analizowanej wartości i dodawane jest przesunięcie strefy czasowej bieżącej maszyny.


Poniższy kod pozwolił mi uzyskać datę sformatowaną jako 31, ale to nie będzie działać w 100% dla dat non Daylioght oszczędzania energii (podanych w tej paszy):

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

Stąd rozwiązanie jest popraw plik danych XML, aby nie wyświetlał się na przemian z UTC za pomocą UTC.

EDIT:dlaczego dane zostały wkręca się

Jak się okazuje to nie 3rd dostawcą partii zmieniając UTC z DST. Kanał XML jest tworzony przez framework Java Swing czytający SQL dB. Zwykle zalecałbym trzymanie standardowej reprezentacji XML (xsd: dateTime) - IS0 8601, ale w tym przypadku użycie łańcucha i zgrywanie wszystkiego po T działa. Zastrzeżenie, wciąż próbuję zmienić kanał, polecam NIE robić tego w PROD. Używaj na własne ryzyko !!

27

co zrobiłem, było używać DateTime.SpecifyKind metody, jak następuje:

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

I to rozwiązać mój problem, mam nadzieję, że to pomoże.

Powiązane problemy