OK, ¿qué me falta aquí? MSDN dice lo siguiente con respecto a DateTimeSerializationMode:Roundtrip XML Serialización de DateTime y xsd: date?
En las versiones 2.0 y posteriores del marco .NET , con esta propiedad establecida en objetos RoundtripDateTime son examinados para determinar si están en el local o UTC un tiempo no especificado zona, y se serializan de tal manera que esta información se conserva. Este es el comportamiento predeterminado y es recomendado para todas las aplicaciones nuevas que no se comuniquen con las versiones anteriores del marco.
Sin embargo:
namespace ConsoleApplication1 {
public class DateSerTest {
[XmlElement(DataType = "date")]
public DateTime Date { get; set; }
}
class Program {
static void Main(string[] args) {
DateSerTest d = new DateSerTest {
Date = DateTime.SpecifyKind(new DateTime(2009,8,18), DateTimeKind.Utc),
};
XmlSerializer ser = new XmlSerializer(typeof(DateSerTest));
using (FileStream fs = new FileStream("out.xml", FileMode.Create)) {
ser.Serialize(fs, d);
}
// out.xml will contain:
// <Date>2009-08-18</Date>
using (FileStream fs = new FileStream("out.xml", FileMode.Open)) {
DateSerTest d1 = (DateSerTest) ser.Deserialize(fs);
Console.WriteLine(d1.Date); // yields: 8/18/2009 12:00:00 AM
Console.WriteLine(d1.Date.Kind); // yields: Unspecified
}
// in.xml:
// <DateSerTest>
// <Date>2009-08-18Z</Date>
// </DateSerTest>
using (FileStream fs = new FileStream("in.xml", FileMode.Open)) {
DateSerTest d1 = (DateSerTest) ser.Deserialize(fs);
Console.WriteLine(d1.Date); // yields: 8/17/2009 8:00:00 PM
Console.WriteLine(d1.Date.Kind); // yields: Local
using (FileStream fs1 = new FileStream("out2.xml", FileMode.Create)) {
ser.Serialize(fs1, d1);
// out2.xml will contain:
// <Date>2009-08-17</Date>
}
}
Console.ReadKey();
}
}
}
Así que para los elementos XSD definidos como "fecha" en lugar de "fecha y hora", la fecha no se serializa como UTC. Esto es un problema, porque si deserializo este XML, la fecha resultante será de Tipo no especificado y cualquier conversión a UTC (que de hecho debería ser no operativa porque el UTC-ness de la fecha debería haberse conservado durante el viaje de ida y vuelta), cambiará al menos la hora del día, con un 50% de posibilidades de que la fecha sea ayer, dependiendo de si está al este o al oeste de Greenwich.
En caso de no conseguir la fecha escrita como:
<Date>2009-08-18Z</Date>
?
De hecho, si deserializo un documento que contiene lo anterior, obtengo un DateTime que ya se ha convertido a la hora local (estoy en Nueva York, así que es el 17 de agosto a las 20:00) y si serializo ese objeto inmediatamente de nuevo a XML, me sale:
<Date>2009-08-17</Date>
Así, UTC se convirtió en local en el camino, y la parte de hora de ese local se redujo a la salida, lo que hará que sea especificado en el camino de regreso de nuevo . Perdimos todo conocimiento de la especificación de fecha UTC original del 18 de agosto.
Aquí es lo que dice el W3C sobre xsd: Fecha:
[Definición:] El · espacio de valores · de fecha consiste en intervalos superiores a abrir de exactamente un día en la longitud de los líneas de tiempo de dateTime, comenzando en el momento inicial de cada día (en por zona horaria), es decir, '00: 00: 00 ', hasta pero sin incluir '24: 00: 00' (que es idéntico a '00: 00 : 00 'del próximo día ). Para los valores que no están en hora, los intervalos de apertura superior de cubren de manera disjunta la línea de tiempo no sincronizada, una por día. Para los valores timezoned, los intervalos comienzan en cada minuto y por lo tanto, se superponen.
El problema fundamental es que si hago lo siguiente:
- Construct (o no recibir) un valor DateTime UTC.
- Serializar a XML con un esquema que define ese campo como xsd: date
- Deserializar ese XML a un DateTime.
- Convierta el DateTime a UTC (que no debería tener ningún efecto ya que el "viaje de ida y vuelta" debería haber preservado esto).
O lo siguiente:
- deserializar un documento XML que contiene un xsd UTC: (. Ej 2009-08-18Z) Fecha de objeto.
- Serializarlo de nuevo en un nuevo documento XML sin tocarlo.
Cualquiera de estos procedimientos me debe recibir la misma fecha que puse en.
Solución
La única manera de que pueda ver lo que va a conseguir el ida y vuelta comportamiento espero es aplicar la propiedad Fecha de la siguiente manera, en el supuesto de que todos los xsd: representan elementos de fecha UTC:
[XmlElement(DataType = "date")]
public DateTime Date {
get { return _dt; }
set { _dt = value.Kind == DateTimeKind.Unspecified ?
DateTime.SpecifyKind(value, DateTimeKind.Utc) :
value.ToUniversalTime(); }
}
Pequeña cosa: El Serializador XML no usa '[Serializable]'. –
Ok, bueno con su modificación, ya no veo la pregunta. ¿Cuál es la pregunta? – Cheeso
Todavía estoy tratando de entenderlo, pero supongo que mi pregunta en este momento es: ¿Tengo razón al concluir que la serialización de ida y vuelta XML entre DateTime y xsd: date está rota? – lesscode