OK, cosa mi manca qui? MSDN dice quanto segue per quanto riguarda DateTimeSerializationMode:Serializzazione XML roundtrip di DateTime e xsd: date?
Nelle versioni 2.0 e successive di .NET framework , con questa proprietà impostata su oggetti RoundtripDateTime vengono esaminate per determinare se sono in locali, UTC o una zona non specificata , e sono serializzate in modo tale che questa informazione è conservata. Questo è il comportamento predefinito ed è consigliato per tutte le nuove applicazioni che non comunicano con le precedenti versioni del framework.
Tuttavia:
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();
}
}
}
Così, per gli elementi XSD definiti come "data", piuttosto che "datetime", la data non viene serializzato come UTC. Questo è un problema, perché se deserializzo questo XML la data risultante sarà di tipo Non specificato, e qualsiasi conversione in UTC (che dovrebbe in effetti essere un no-op perché l'UTC-ness della data avrebbe dovuto essere conservato durante il roundtrip), cambierà almeno l'ora del giorno, con una probabilità del 50% di rendere la data di ieri, a seconda che tu sia a est oa ovest di Greenwich.
non dovrebbe la data di ottenere scritto come:
<Date>2009-08-18Z</Date>
?
Infatti, se deserializzi un documento che contiene quanto sopra, ricevo un DateTime che è già stato convertito in Ora locale (sono a New York quindi è il 17 agosto 20:00) e se eseguo immediatamente la serializzazione di quell'oggetto torna a XML, ottengo:
<Date>2009-08-17</Date>
Così, UTC è stato convertito in locale sul modo in, e la parte di tempo di quella locale è sceso sulla via d'uscita, che lo renderà non specificato sulla via del ritorno di nuovo . Abbiamo perso tutta la conoscenza delle specifiche originali della data UTC del 18 agosto.
Ecco cosa dice il W3C su xsd: Data:
[Definizione:] Il · spazio valore · di data è costituito da intervalli di top-open di esattamente un giorno di lunghezza sulle tempistiche di dateTime, a partire dal momento all'inizio di ogni giornata (in ogni fuso orario), vale a dire '00: 00: 00' , fino a esclusi '24: 00: 00' (che è identica a '00: 00 : 00 'del prossimo giorno ). Per i valori non temporizzati, gli intervalli di apertura massima coprono in modo disgiunto la linea temporale non temporizzata, una per il giorno . Per i valori timezoned, gli intervalli iniziano ogni minuto e quindi si sovrappongono.
Il problema fondamentale è che se faccio la seguente:
- Construct (o in altro modo ricevere) un valore UTC DateTime.
- Serializzare in XML con uno schema che definisce il campo come xsd: date
- Deserializzare tale XML su un DateTime.
- Converti il DateTime in UTC (che non dovrebbe avere alcun effetto poiché il "roundtrip" avrebbe dovuto conservare questo).
o il seguente:
- deserializzare un documento XML contenente un xsd UTC: (es. 2009-08-18Z) data di oggetto.
- Serializzare di nuovo su un nuovo documento XML senza toccarlo.
Ciascuna di queste procedure me dovrebbe ottenere la stessa data ho messo in.
Soluzione
L'unico modo che posso vedere così lontano per ottenere il andata e ritorno comportamento mi aspetto è quello di implementare la proprietà data come segue, partendo dal presupposto che tutti xsd: gli elementi data rappresentano UTC:
[XmlElement(DataType = "date")]
public DateTime Date {
get { return _dt; }
set { _dt = value.Kind == DateTimeKind.Unspecified ?
DateTime.SpecifyKind(value, DateTimeKind.Utc) :
value.ToUniversalTime(); }
}
Piccola cosa: il serializzatore XML non usa '[Serializable]'. –
Ok, bene con la tua modifica, non vedo più la domanda. Quale è la domanda? – Cheeso
Sto ancora cercando di capirlo, ma suppongo che la mia domanda a questo punto sia: Ho ragione di concludere che la serializzazione XML roundtrip tra DateTime e xsd: data è rotta? – lesscode