.NET, Programming

.NET DateTime Serialization: Eff UTC

12.18.07 | 1 Comment

Handling date and time is tough, and the .NET Framework has more than a few quirks in this area. I have just run into one of the more painful ones, and I think I have found a simple way around it. (Note: this article refers to the .NET Framework 2.0. Other versions may give different results.)

I have a program that retrieves and stores RSS or Atom files from a number of blogs (the output is at CrimeSpot.net). Each provider, such as Typepad, WordPress, or Blogger, has its own quirks, and many of these revolve around date and time. As a result I have had to spend a lot of time writing a routine that calculates the time a particular post was published in Universal Coordinated Time (UTC – acronym must be French) and in local time. Local time is for display, while UTC is used to calculate how long ago posts were published and in what order.

I have recently been testing some modifications to this program that use web services to store the data on a remote server instead of in a local database. Much to my surprise the dates displayed below the posts were off by an hour. WTF?

So I dug a little deeper. As part of the program I take a Visual Basic class I have created to hold and process the posts and serialize it into XML. I then load the resulting XML into a dataset. So I dumped the XML into a file, and discovered that .NET was taking my carefully calculated UTC dates and times and – silent but deadly – converting them to local time!

Let’s take an example: If I publish a post here in Fort Worth (UTC offset: -0600) at 7:15pm, the UTC timestamp would be 1:15am the following morning. That’s the current time in Greenwich, England, upon which UTC is based. When I serialize this value, .NET just takes 1:15am and sticks -0600 on the end of it.

Since the web server I’m saving this too is in a time zone an hour away – voila – the resulting time is an hour off.

The solution, of course, is to change the type to a correctly computed local time before serialization, and I guess that’s what I’ll have to do. But in .NET 2.0 the DateTime structure includes a “Kind” field, which is getting properly set to UTC. Would it have killed them to check this before mashing my data?

Yeah, I guess it would have.

Update: Got it. It was a little more work that I had anticipated, but I got it working. What I ended up having to do was add another Web Services function that returned the offset from UTC on the server. Here’s the code for that:

return TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).ToString

This returns a TimeSpan object containing the offset from UTC. The .ToString function on the end is required because, despite the fact that the object is serializable, TimeSpan.Duration does not in fact serialize.

Once you have parsed the remote UTC offset, get the offset for the zone on the local computer using the same syntax (without .ToString). Then just do LocalOffset – RemoteOffset, which will give you yet another time span, and add that value to all of your times.

I didn’t go into any detail as to why I need to use UTC. My website actually uses three computers: a workstation to gather and publish data, a Web Services server to store this data in a database, and a web server to display it. All of these servers are in different time zones, so I need a value that will be consistent across all sites.

I think I see one reason why the DateTime structure is serialized as a local value, instead of UTC. While fooling around with reading and writing dates as strings of various formats, I discovered that a DataSet would recognize SortableDateTimeFormat as a valid date, but would not recognize UniversalSortableDateTimeFormat (more information at the DateTimeFormatInfo class). So based on how deserializing strings to dates currently works, it may be impossible to pass these values as Universal time.

1 Comment

have your say

Add your comment below, or trackback from your own site. Subscribe to these comments.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>