1

In my WPF .NET client application I assign a DateTime variable the current Time value:

class MyClass
{
  public DateTime CreatedDate {get; set;}
}

MyClass myClass = new MyClass();
myClass.CreatedDate = DateTime.Now;

After the assignment I send the object to a WCF service located in Europe (UTC+1) that saves the object in the database. If client and service are in the same TimeZone there are no issues. However if I change TimeZone, for instance my client is in (UTC-6) and service in (UCT+1), the service will read the CreatedDate value as it is DateTime.Now on the service so (UCT+1) instead of (UCT-6) as assigned on the client. If set CreatedDate on the client (UTC-6) the 31/10/2014 at 20:00 in the service it will be stored as (UTC+1) the 01/11/2014 at 01:00 and this affects some processes on my system.

This is not the behavior that I would like to have, I want the service always to store that Date as submitted by the client.

I have access to the code for both server and client, I tried to set when assign the CreatedDate as:

myClass.CreatedDate = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Unspecified);

with no luck. The only solution I can think about is to use string instead of DateTime but that implies a lot of changes in the code. Anybody know a way to ignorne the TimeZone settings?

CiccioMiami
  • 8,028
  • 32
  • 90
  • 151
  • 3
    Why don't you store `DateTime` in UT? Each client will "see" with its local time (when you convert to string in visualization, for example what you see here on StackOverflow). As alternative (to keep each timestamp with its time zone) you may use `DateTimeOffset`. In general...don't ever think to use strings when there is a better type... – Adriano Repetti Oct 20 '14 at 13:48
  • 2
    Document your service and claim that it should only be sent utc-values, and will only return utc-values. Let the user interface handle the conversion. Look into http://nodatime.org/ it's sweet sweet music to datetime damaged ears... – sisve Oct 20 '14 at 13:50
  • Thanks for your hints! However I got a bit lost about UTC. If the client in (UTC+6) stores the CreatedDate at 31/10/2014 at 20:00 the value read by the service in UTC is still 01/11/2014 at 00:00, right? – CiccioMiami Oct 20 '14 at 13:59
  • Storing and returning dates in UTC means that you do it in UTC+0. No timezones involved. That also means it's up to the client to determine the current time zone and format/change datetimes accordingly. – sisve Oct 20 '14 at 14:14
  • Maybe I am misisng something. If I have everything in (UTC+0) that also means my service will store CreatedDate in (UTC+0) but this is not what I want to achieve. I want the service to keep the date as stored in the client :) – CiccioMiami Oct 20 '14 at 14:51
  • `DateTime` doesn't store timezone information, it just can differentiate between UTC and local time. There is no way to say that this is a `DateTime` from another time zone (other than the local timezone). You should store in UTC. – heavyd Oct 20 '14 at 15:17
  • If I use UTC therefore my service will always store UTC time in the database, since it is not aware of the TimeZone where the value was given as input. DateTimeOffset is the only way to know let the service aware of the TimeZone? – CiccioMiami Oct 20 '14 at 16:03

1 Answers1

4

You have a few different options:

  • Keep everything as DateTime, but work with UTC values instead of local values. That means using DateTime.UtcNow to fetch the current time.

    On the client, you can generate a display value using ToLocalTime to convert the value from UTC to the local time zone of the computer the client code is running on.

  • Switch to DateTimeOffset. This ensures when transmitting the value from the client to the server that you retain the time zone offset - which tells you how far away from UTC that particular timestamp is.

    You can get the current time using either DateTimeOffset.UtcNow, or DateTimeOffset.Now. The latter has the advantage of retaining the local time as the client understood it. If you plan to do any aggregate analysis of the data based on local date/time, then you will need this information. Remember, "today" is not the same for everyone on the Earth simultaneously.

  • If you have another way to communicate the time zone of the client, or if you know this already from outside information, then you can transmit either a DateTime or a DateTimeOffset, and then use the TimeZoneInfo class to do conversions on the server.

    There is one "gotcha" however. If you transmit a local DateTime that is in a daylight saving time ambiguity period (during the "fall-back" transition), then you can potentially convert incorrectly. Using either UTC or DateTimeOffset will avoid this problem.

See also The Case Against DateTime.Now, and DateTime vs DateTimeOffset.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575