Wednesday, July 30, 2008

WCF DateTime field adjusted automatically for time zone

Well, I got bit by DateTime serialization yesterday. Our server is in the U.S. Central Standard Time (CST) zone and our client is in the U.S. Eastern Standard Time (EST) zone. All data saved in the database is relative to the client and NOT the server. So when the client wants to see all data for today, only the date is specified using DateTime.Today. So when the EST client sent a date of 7/29/08 00:00:00 AM to our WCF webservice on the CST server, the date was converted to 7/28/08 11:00:00 PM. The symptom from the client's point of view was that they could never retrieve data for today.

According to Coding Best Practices Using DateTime in the .NET Framework there are several ways to work around this; however, they missed one. If you change your dates so that DateTimeKind is unspecified, the XML serializer will NOT try to convert them. For example, this code will convert a date to DateTimeKind.Unspecified:


DateTime newDate = DateTime.SpecifyKind(oldDate, DateTimeKind.Unspecified);


References:

14 comments:

Anonymous said...

In your subtitle you use the word personnel. I think you mean personal.

Assaf S. said...

Thank you for this post - it was a lifesaver!

BTW, you can use DateTime.SpecifyKind to change the Kind of an existing DateTime object

Goodman said...

I have the same problem right now. Thanks!

Anonymous said...

It is remarkable, rather amusing answer

Anonymous said...

It is remarkable, it is very valuable answer

Anonymous said...

Your blog keeps getting better and better! Your older articles are not as good as newer ones you have a lot more creativity and originality now keep it up!

cyberguest said...

good info.

and also to give some credit to the linked best practice article, the author was referring to .NET 1.0 and 1.1. back then, there was no Kind for DateTime.

Anonymous said...

Thanks 4 the post!

Anonymous said...

Very helpful thanks!

Anonymous said...

After many hours spent to understand my timezone problem, i must say you : THANK YOU !

Marc Fearby said...

I've also found that I can do this on the server-side to get the non-adjusted value:

date.Value.ToLocalTime()

Unknown said...

Hi,
Thank you for the post. We have the exact same issue, but setting it to Unspecified, work only if my client and server are EST, if my client time is EST and server is CST, still I have same problem. Any help would appreciated.

Thanks,
Akila.

Dave said...

@Akila - If you are storing UTC time in your database and then set the time to Unspecified before sending it over the web, you should not have a problem on the client side if you set the datetimekind back to UTC. If you are storing local times in your database, you're probably going to have issues.

Dave said...

@Akila - so you are storing local time and not UTC time. That's not really a good idea since databases like SQL Server do not store the date time kind. If you are using JSON serialization, it will send the time as UTC regardless of what you do, which means it may translate it back to local time on the other side, which will put your time off by hours. If you are using XML serialization or the DataContractSerializer as long as you set the DateTime kind to unspecified before sending and don't fiddle with it on the client side, you should be fine. Are you trying to translate it back to local time for the client? If so, I'd recommend you store UTC and save yourself a lot of trouble. Besides, if you ever move your server location you don't want to store local times. You need something that is universal and captures a time relative to something known. That is what UTC time is all about since it doesn't observer Day Light Savings time and is always the same.