OK, what am I missing here? MSDN says the following with regard to DateTimeSerializationMode:
In versions 2.0 and later of the .Net Framework, with this
I don't see the problem you described.
Your sample code doesn't deserialize. I added some code to deserialize, and it roundtrips as I would expect. I did not see the date move back a day, or forward a day.
I did notice that the time portion of the d.Date field is stripped for serialization, regardless of the DateTimeKind. This seems correct to me. It doesn't make sense to me, intuitively, to either serialize a timezone with a "Date", or to convert to UTC. It would be surprising to me that if I had a Date value of 8-18-2009, and when serialized, it showed up as 8-19-2009Z. So I think the way it works now seems correct.
[XmlElement(DateType="time")]
(xsd:time), the timezone would not be included. I didn't test this. So the problem as I see it is, this behavior, which makes sense to me, isn't documented clearly, especially with the changes introduced for roundtripping. The fact that DataType="date" and DataType="time" do not convert to UTC for serialization, should be clearly stated.
you wrote:
and any conversion to UTC will change at least the time of day,
But I didn't see this at all. When I convert a time that is DateTimeKind.Unspecified, to Utc, it doesn't change the time of day. It just changes the kind.
class Program
{
static System.IO.MemoryStream StringToMemoryStream(string s)
{
byte[] a = System.Text.Encoding.ASCII.GetBytes(s);
return new System.IO.MemoryStream(a);
}
static void Main(string[] args)
{
var settings = new System.Xml.XmlWriterSettings { OmitXmlDeclaration = true, Indent= true };
XmlSerializerNamespaces _ns = new XmlSerializerNamespaces();
_ns.Add( "", "" );
Console.WriteLine("\nDate Serialization testing...");
for (int m=0; m < 2; m++)
{
var builder = new System.Text.StringBuilder();
DateTime t = DateTime.Parse("2009-08-18T22:31:24.0019-04:00");
DateSerTest d = new DateSerTest
{
Date = t,
DateTime = t
};
Console.WriteLine("\nRound {0}", m+1);
if (m==1)
d.Date = d.Date.ToUniversalTime();
Console.WriteLine("d.Date {2,-11} = {0} Kind({1})", d.Date.ToString("u"), d.Date.Kind.ToString(),
(m==1) ? "(converted)" : "(original)" );
Console.WriteLine("d.DateTime = {0} Kind({1})", d.DateTime.ToString("u"), d.DateTime.Kind.ToString());
XmlSerializer ser = new XmlSerializer(typeof(DateSerTest));
Console.WriteLine("\nSerialize d");
using ( var writer = System.Xml.XmlWriter.Create(builder, settings))
{
ser.Serialize(writer, d, _ns);
}
string xml = builder.ToString();
Console.WriteLine("{0}", xml);
Console.WriteLine("\nDeserialize into d2");
System.IO.MemoryStream ms = StringToMemoryStream(xml);
DateSerTest d2= (DateSerTest) ser.Deserialize(ms);
Console.WriteLine("d2.Date = {0} Kind({1})", d2.Date.ToString("u"), d2.Date.Kind.ToString());
Console.WriteLine("d2.DateTime= {0} Kind({1})", d2.DateTime.ToString("u"), d2.DateTime.Kind.ToString());
Console.WriteLine("\nAfter SpecifyKind");
d2.Date = DateTime.SpecifyKind(d2.Date, DateTimeKind.Utc);
Console.WriteLine("d2.Date = {0} Kind({1})", d2.Date.ToString("u"), d2.Date.Kind.ToString());
Console.WriteLine("\nRe-Serialize d2");
builder = new System.Text.StringBuilder();
using ( var writer = System.Xml.XmlWriter.Create(builder, settings))
{
ser.Serialize(writer, d2, _ns);
}
xml = builder.ToString();
Console.WriteLine("{0}", xml);
}
}
}
The results:
Date Serialization testing... Round 1 d.Date (original) = 2009-08-18 22:31:24Z Kind(Local) d.DateTime = 2009-08-18 22:31:24Z Kind(Local) Serialize dDeserialize into d2 d2.Date = 2009-08-18 00:00:00Z Kind(Unspecified) d2.DateTime= 2009-08-18 22:31:24Z Kind(Local) After SpecifyKind d2.Date = 2009-08-18 00:00:00Z Kind(Utc) Re-Serialize d2 2009-08-18 2009-08-18T22:31:24.0019-04:00 Round 2 d.Date (converted) = 2009-08-19 02:31:24Z Kind(Utc) d.DateTime = 2009-08-18 22:31:24Z Kind(Local) Serialize d 2009-08-18 2009-08-18T22:31:24.0019-04:00 Deserialize into d2 d2.Date = 2009-08-19 00:00:00Z Kind(Unspecified) d2.DateTime= 2009-08-18 22:31:24Z Kind(Local) After SpecifyKind d2.Date = 2009-08-19 00:00:00Z Kind(Utc) Re-Serialize d2 2009-08-19 2009-08-18T22:31:24.0019-04:00 2009-08-19 2009-08-18T22:31:24.0019-04:00