We are developing an application in C# 4 that uses SQL Server 2008 R2 as backend. SQL Server Compact 4 is also used for disconnected clients in a very few rare scenarios. We are wondering what's the best way to store date/time data into these databases so that:

  1. Data containing different time offsets (coming from different time zones) can co-exist nicely. This means being sorted and compared.
  2. Data in SQL Server 2008 R2 and SQL Server Compact 4 can be transferred back and forth seamlessly; this is a secondary requirement that should not compromise the chosen design.

Our main concern is to preserve the local time for each recorded event, but without losing the ability to compare and sort events that have been generated from different time zones and therefore have different time offsets.

We have considered the datetimeoffset data type, since it stores the time offset and because it maps nicely to .NET's DateTimeOffset. However, it is not supported in SQL Server Compact 4. An alternative would be to remove offset info from the database and use a simple datetime data type, so that every piece of data in the database is normalized, and the issues with Compact are fewer. However, this introduces the problem that offset info would need to be reconstructed somehow on retrieval before the user sees the data.

So my question is, are there any best practices or guidelines on how to store date/time values in SQL Server, taking into account that we will need to deal with different time zones, and making the interoperability between 2008 R2 and Compact 4 as easy as possible?

Thank you.

有帮助吗?

解决方案

It sounds like the relevant points are:

  • Your incoming data is a good fit for DateTimeOffset
  • You only care about the offset at that particular time, so you don't need a real time zone. (An offset isn't a time zone.)
  • You do care about that original offset - you can't just normalize everything to UTC and ignore the offset entirely.
  • You want to query on the local time.

It does sound like DateTimeOffset is basically the most appropriate type in this case. You should make sure everyone on the team is clear about what it means though - the offset is the offset when the data was originally received. If you want to display that instant in time in a different time zone, you effectively need to go back to UTC, and find out what the offset would be in that display time zone. It's easy to get confused about this sort of thing :)

If you need to maintain the data in SqlServerCE with full fidelity, you'll probably want a DateTime field and then a separate field for the offset (e.g. in minutes, or as a TimeSpan if SqlServerCE supports that).

其他提示

You are probably right to use DateTimeOffset on the server. You might also want to read my answer on DateTime vs DateTimeOffset.

On the client, where you are using SQLCE, store a DateTime with UTC values. When you send the data to the server, you can use the local time zone of the client to determine the DateTimeOffset that the UTC value corresponds to.

If it's possible that the user might be changing their time zones, then you might also need to store the time zone's id in the client database. But you would just use this during conversion. There's no need to send it to the server unless you might be editing those values on the server or in some other client.

Don't try storing the time on the client in the local time of the client. You will encounter abiguities. For example, when daylight saving time rolls backwards, you don't want two different possible UTC times for the same local time.

Why not use datetime and always store the value as a UTC value, then you can format it to the end users (display) time zone when required.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top