Evite la conversión de zona horaria en la deserialización del valor de DateTime

Tengo una clase que serializo / deserialize usando XmlSerializer . Esta clase contiene un campo DateTime .

Cuando se serializa, el campo DateTime está representado por una cadena que incluye el desplazamiento de GMT, por ejemplo, 2010-05-05T09:13:45-05:00 . Cuando se deserializan, estos tiempos se convierten a la hora local de la máquina que realiza la deserialización.

Por razones que no vale la pena explicar, me gustaría evitar que ocurra esta conversión de zona horaria. La serialización ocurre en la naturaleza, donde existe una versión múltiple de esta clase. La deserialización ocurre en un servidor que está bajo mi control. Como tal, parece que esto se manejaría mejor durante la deserialización.

¿Cómo puedo hacer que esto suceda, aparte de implementar IXmlSerializable y hacer toda la deserialización “a mano”?

En lugar de analizar como DateTime , puede analizarlo como DateTimeOffset y usar la propiedad DateTimeOffset.DateTime para ignorar la zona horaria. Me gusta esto:

 [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; } } 

Lo que hice fue utilizar el método DateTime.SpecifyKind, de la siguiente manera:

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

Y esto resuelve mi problema, espero que esto te ayude.

¿Podría probar algo como esta publicación? Sugiera y cree una nueva propiedad de cadena y XmlIgnore la existente:

Ponga [XmlIgnore] en la propiedad Time.

Luego agrega una nueva propiedad:

 [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); } } 

Sé que esto es viejo, pero espero que esto ayude a alguien en el futuro.

Aquí está el XML que estaba deserializando:

 1982-03-31T00:00:00+11:00 

Después de deserializar el XML, termino con el 30 y no el 31:

enter image description here

Parece que el tercero que produce este XML (que estoy usando) cambia el TimeZone a +11 durante el horario de verano y lo mantiene como +10 cuando no es Daylight Saving (DST).

Según Jon Skeet, los UTC no deberían considerar el horario de verano: https://stackoverflow.com/a/5495816/495455


También tenga en cuenta la documentación Codificación de mejores prácticas utilizando DateTime en .NET Framework :

El serializador XML siempre asume que los valores de DateTime que se serializan representan la hora local de la máquina, por lo que aplica la compensación de zona horaria local de la máquina como la parte de desplazamiento del tiempo XML codificado. Cuando deserializamos esto en otra máquina, el desplazamiento original se resta del valor que se está analizando y se agrega el desplazamiento de la zona horaria actual de la máquina.


El siguiente código me permitió obtener la fecha formateada como la 31ª pero no funcionará al 100% para las fechas que no guardan el horario (incluidas en este feed):

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

Por lo tanto, la solución es corregir el feed XML para que no alterne los UTC con DST.

EDITAR: por qué se estropearon los datos

Como resultado, NO es el proveedor de terceros que cambia el UTC con el horario de verano. El feed XML es creado por Java Swing framework leyendo un SQL dB. Normalmente, recomendaría mantener la representación estándar XML (xsd: dateTime) - IS0 8601, pero en este caso usar una cadena y extraer todo después de que la T funcione. Descargo de responsabilidad, todavía estoy tratando de cambiar el feed, recomiendo que NO lo haga en PROD. ¡¡Úselo bajo su propio riesgo!!