XmlSerialization of DateTime in .NET Framework 2.0
I have seen numerous blog and newsgroup posts about how XmlSerialization and ASMX WebServices serialize DateTime in v1.0 and v1.1 of the framework. Well, I have some good news, bad news and good bad news for you.
Good news: We fixed it.
Bad news: If you worked around it then you might be broken on upgrade to v2.0
Good of the bad news: Don’t worry there is a workaround to get the old broken behavior back.
In case you missed it, here is a quick summary of the problem:
In v1.0 and v1.1 of the framework when serializing DateTime values with the XmlSerializer, we would always append the local timezone of the machine.
There are several problems with that:
1) DateTime doesn’t have a notion of timezone so why would we append it
2) Since DateTime didn’t have a timezone indicator a DateTime intended to represent UTC would come up with the local timezone on it
3) When reading a DateTime off the wire, we would automatically adjust the time based on the timezone offset relative to the local timezone on the receiving machine
Needless to say, this caused some problems for some folks.
How we fixed it
v2.0 now has a notion of DateTimeKind to help developers indicate the nature of the DateTime. It can be Local, UTC or Unspecified.
Using this value in XmlSerialization and System.Xml.XmlConvert allows us to now de/serialize DateTime and preserve its desired timezone.
Here is a little table to show you the differences:
DateTime.Now |
new DateTime() |
DateTime.UtcNow |
|
v1.0 and v1.1 output |
2004-10-13T15:16:11.5427356-07:00 |
1999-02-02T12:24:48.0000000-08:00 |
2004-10-13T22:16:11.5427356-07:00 |
DateTimeKind on v2.0 |
Local |
Unspecified |
UTC |
v2.0 output |
2004-10-13T15:16:11.5427356-07:00 |
1999-02-02T12:24:48.0000000 |
2004-10-13T22:16:11.5427356Z |
In order to get this new behavior you only need to upgrade to v2.0 of the .NET Framework.
How you could be broken on upgrade
The reason I am telling you this is that you might have code that works around this problem today and upgrading will change the date representation on the wire and could break your existing applications.
Some interesting things to note:
- DateTime comparison functions ignore the new DateTimeKind field
o Even though 3pm in UTC is technically before 4pm in New York the Compare functions will still indicate the 4pm is later. This is to remain consistent with v1.0 and v1.1 behavior.
o There are no new DateTimeKind aware comparison functions.
- Deserializing a UTC time in v2.0 will not cause the time to shift on deserialization
o In v1.0 and v1.1 the DateTime was always shifted a local time from the UTC offset. In v2.0 the DateTime will remain unchanged but the DateTimeKind will be UTC
o This means that round-tripping a DateTime through a service that only returns the UTC time will look like the time has shifted (see note on comparisons above) when it has really just been converted to UTC
How to get the old behavior back
In order to preserve backwards compatibility you can add the following section to your web.config and control the XmlSerialization of DateTime on a per application basis:
<system.xml.serialization>
<dateTimeSerialization mode="Local" />
</system.xml.serialization>
Setting the dateTimeSerialization mode to Local will give you the v1.0 and v1.1 behavior. Doing nothing or setting the value to Roundtrip will give you the new behavior that changes the serialization of DateTime based on the specified DateTimeKind.
Enjoy!
Comments
- Anonymous
April 02, 2007
PingBack from http://alekseysanin.wordpress.com/2007/04/03/microsoft-and-backward-compatibility/