OK, czego tu brakuje? MSDN mówi, co następuje w odniesieniu do DateTimeSerializationMode:Roundtrip XML Serialization of DateTime i xsd: date?
W wersjach 2.0 i późniejsze Framework z tej właściwości ustawiony na obiektów RoundtripDateTime są badane celu ustalenia, czy są one w lokalnym, lub UTC w nieokreślonym czasie strefa i są serializowane w taki sposób, aby ta informacja została zachowana. Jest to domyślne zachowanie i jest zalecane dla wszystkich nowych aplikacji , które nie komunikują się ze starszymi wersjami architektury .
Jednakże:
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();
}
}
}
Więc dla elementów XSD definiuje się jako "dacie" zamiast "dateTime", data nie jest szeregowane jako UTC. To jest problem, ponieważ jeśli deserializuję ten XML, to wynikowy termin będzie Kind Unspecified i dowolna konwersja na UTC (która w rzeczywistości powinna być no-op, ponieważ data UTC daty powinna zostać zachowana podczas roundtrip), zmieni co najmniej porę dnia, z 50% szansą na wczorajszą randkę, w zależności od tego, czy jesteś na wschód czy na zachód od Greenwich.
Jeżeli nie dacie się zapisać jako:
<Date>2009-08-18Z</Date>
?
Rzeczywiście, jeśli deserializuję dokument, który zawiera powyższe, otrzymuję DateTime, który został już skonwertowany na czas lokalny (jestem w Nowym Jorku, to jest 17 sierpnia 20:00), i jeśli natychmiast serializuje ten obiekt z powrotem do XML, otrzymuję:
<Date>2009-08-17</Date>
Więc UTC przekształcono lokalny po drodze, a część czasu, że lokalne spadła na drodze, która pozwoli Nieokreślony w drodze powrotnej ponownie . Straciliśmy całą wiedzę na temat pierwotnej specyfikacji daty UTC z 18 sierpnia.
Oto co W3C mówi o xsd: Data:
[Definicja:] · przestrzeni wartość · od data składa się z najlepszych otwartych przedziałach dokładnie jeden dzień w długości na terminów z dateTime, rozpoczynając od początkowej chwili każdego dnia (w każdej strefie czasowej), tj. '00: 00: 00 ', do , ale bez "24: 00: 00" (która jest identyczna z '00: 00 : 00 'następnego dnia ). W przypadku wartości niedoświetlonych, przedziały od góry do góry rozłącznie pokrywają się z niezwiązaną linią czasu, jedną na dzień . W przypadku wartości ograniczonych czasowo interwały rozpoczynają się od każdej minuty i dlatego nakładają się na siebie.
Podstawowym problemem jest to, że jeśli I wykonaj następujące czynności:
- Construct (lub inaczej odbierać) wartość UTC DateTime.
- Serializować do XML z schematu definiującego to pole jako xsd: data
- deserializowania że XML z powrotem do DateTime.
- Konwersja DateTime na UTC (która nie powinna wywoływać żadnego efektu, ponieważ "roundtrip" powinien to zachować).
Albo co następuje:
- deserializowania dokument XML zawierający UTC xsd: (np. 2009-08-18Z) Data przedmiot.
- Serialize to z powrotem do nowego dokumentu XML bez dotykania go.
Każda z tych procedur powinno dać mi tę samą datę I umieścić w.
Obejście
jedyny sposób widzę tak daleko, aby uzyskać obie zachowanie Spodziewam jest implementować właściwość Date w następujący sposób, przy założeniu, że wszystkie elementy xsd: date reprezentują UTC:
[XmlElement(DataType = "date")]
public DateTime Date {
get { return _dt; }
set { _dt = value.Kind == DateTimeKind.Unspecified ?
DateTime.SpecifyKind(value, DateTimeKind.Utc) :
value.ToUniversalTime(); }
}
Mała rzecz: Serializator XML nie używa "[Serializable]". –
Dobrze, z twoją modyfikacją, nie widzę już pytania. Jakie jest pytanie? – Cheeso
Nadal próbuję się o tym przekonać, ale domyślam się, że moje pytanie w tym miejscu brzmi: Czy mam rację, twierdząc, że serialowanie w obiegu XML między DateTime i xsd: date jest zepsute? – lesscode