Nope. For DateTimeKind=UTC dates, it's totally broken.
Ttry this (in Linqpad):
var localTime = DateTime.Now;
var utcTime = localTime.ToUniversalTime();
localTime.Dump("Local Time");
utcTime.Dump("UTC time");
utcTime.Kind.Dump("UTC Kind");
utcTime.ToString("yyyy-MM-ddTHH:mm:ss K").Dump("Expected XML");
XmlConvert.ToString(utcTime).Dump("Actual XML from XML Convert");
Gives:
Local Time | 23/10/2012 11:11:11 AM |
---|---|
UTC time | 23/10/2012 3:11:11 AM |
UTC Kind | UTC |
Expected XML | 2012-10-23T03:11:11 Z |
Actual XML from XML Convert | 2012-10-23T03:11:11.0773940+08:00 |
You'll notice immediately (because of the highlighting), that it's done something really really dumb. It's made out that the UTC time is actually a local time in my local timezone offset (+8). It's screwed up the XML representation, and as a result changed the actual time value being passed, even though it knows (based on DateTime.Kind==DateTimeKind.Utc, that the ToUniversalTime() method always gives you) that it's a UTC date.
This is because internally that method does this:
[Obsolete("Use XmlConvert.ToString() that takes in XmlDateTimeSerializationMode")]
public static string ToString(DateTime value)
{
return XmlConvert.ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffzzzzzz");
}
...and those z's add the local timezone offset from your PC. This is wrong for a DateTime with Kind=UTC. A better implementation would be as per my example above, ie:
return XmlConvert.ToString(value, "yyyy-MM-ddTHH:mm:ss.fffffffK");
The K specifier is not so dumb, and adds the time zone to local time datetime instances, and adds the Z to UTC instances. Or alternatively an if{}else{} based on value.Kind==DateTimeKind.UTC.
Anything but what it does right now.
Why do I care? Well WCF generates webservices proxies using DateTime, not DateTimeOffset, so I want to make damn sure it's not making the same mistake.