views:

633

answers:

6

UPDATE

I am dealing with a legacy database where the datetime values have been stored in a specific timezone (not UTC). Assume it is not possible to change how we are storing these values.

END UPDATE

Say I have a SQL Server 2005 database with a table as follows:

[id] (int) not null   
[create_date] (datetime) not null

Suppose my [create_date] has been stored, by convention, as timezone TZ-A.

Suppose I want to retrieve this value (using SqlClient) from the database and display it in another timezone, TZ-B.

How do I do this?

DateTime from_db = // retrieve datetime from database, in timezone TZ-A
DateTime to_display = //convert from_db to another timezone, TZ-B
+1  A: 

use the TimeZoneInfo class, it gives you built in time zone conversion functions using the Windows API.

http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

Mike Mooney
A: 

Check the method TimeZoneInfo.ConvertTime.

Fernando
+1  A: 

Use TimeZoneInfo

TimeZoneInfo timeZone1 = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
TimeZoneInfo timeZone2 = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime to_display= TimeZoneInfo.ConvertTime(from_db, timeZone1, timeZone2);

I also agree that storing in UTC is the way to go. The only downside is trying to explain UTC to users who want to write their own reports.

Kevin Gale
Thanks for the answer :)
frankadelic
+2  A: 

Everyone has C# ways, I give you TSQL (sadly only 2008):

See below for doc, you probably want something like:

-- up here set the @time_zone variable.

 SELECT 
    COl0, TODATETIMEOFFSET(COLDATE, @time_zone),.... ColN, from 
Table_Original;

From MSDN

The SWITCHOFFSET function adjusts an input DATETIMEOFFSET value to a specified time zone, while preserving the UTC value. The syntax is SWITCHOFFSET(datetimeoffset_value, time_zone). For example, the following code adjusts the current system datetimeoffset value to time zone GMT +05:00:

SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), '-05:00');

So if the current system datetimeoffset value is February 12, 2009 10:00:00.0000000 -08:00, this code returns the value February 12, 2009 13:00:00.0000000 -05:00.

The TODATETIMEOFFSET function sets the time zone offset of an input date and time value. Its syntax is TODATETIMEOFFSET(date_and_time_value, time_zone).

This function is different from SWITCHOFFSET in several ways. First, it is not restricted to a datetimeoffset value as input; rather it accepts any date and time data type. Second, it does not try to adjust the time based on the time zone difference between the source value and the specified time zone but instead simply returns the input date and time value with the specified time zone as a datetimeoffset value.

The main purpose of the TODATETIMEOFFSET function is to convert types that are not time zone aware to DATETIMEOFFSET by the given time zone offset. If the given date and time value is a DATETIMEOFFSET, the TODATETIMEOFFSET function changes the DATETIMEOFFSET value based on the same original local date and time value plus the new given time zone offset.

For example, the current system datetimeoffset value is February 12, 2009 10:00:00.0000000 -08:00, and you run the following code:

SELECT TODATETIMEOFFSET(SYSDATETIMEOFFSET(), '-05:00');

The value February 12, 2009 10:00:00.0000000 -05:00 is returned. Remember that the SWITCHOFFSET function returned February 12, 2009 13:00:00.0000000 -05:00 because it adjusted the time based on the time zone differences between the input (-08:00) and the specified time zone (-05:00).

As mentioned earlier, you can use the TODATETIMEOFFSET function with any date and time data type as input. For example, the following code takes the current system date and time value and returns it as a datetimeoffset value with a time zone -00:05:

SELECT TODATETIMEOFFSET(SYSDATETIME(), '-05:00');

Hogan
DATETIMEOFFSET is SQL 2008 specific, unavailable in SQL 2005
Remus Rusanu
@Remus: good point, I edited to point that out... clearly frank should buy 2008 for this feature (grin).
Hogan
data page compression, now there's a reason for buying SQL 2008 ;)
Remus Rusanu
+1  A: 

Always store the data in the database as UTC. Then convert it in the client for display purposes from UTC to the local time using DateTime.ToLocalTime();

Remus Rusanu
+2  A: 

I'm not going to offer an answer, but rather a word of advice: Always store absolute dates in UTC, no matter what.

kprobst
We are dealing with a legacy system where that is not possible.
frankadelic
Oh, OK. I know how that sucks :(
kprobst