Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Effectively Converting dates between UTC and Local (ie. PST) time in SQL 2005

Tags:

sql-server

What is the best way to convert a UTC datetime into local datetime. It isn't as simple as a getutcdate() and getdate() difference because the difference changes depending on what the date is.

CLR integration isn't an option for me either.

The solution that I had come up with for this problem a few months back was to have a daylight savings time table that stored the beginning and ending daylight savings days for the next 100 or so years, this solution seemed inelegant but conversions were quick (simple table lookup)

like image 911
Jon Erickson Avatar asked Aug 24 '08 02:08

Jon Erickson


People also ask

How do I convert UTC time to local time in SQL?

SELECT CONVERT(datetime, SWITCHOFFSET(CONVERT(DATETIMEOFFSET, GETUTCDATE()), DATENAME(TZOFFSET, SYSDATETIMEOFFSET()))) AS LOCAL_IST; Here, the GETUTCDATE() function can be used to get the current date and time UTC. Using this query the UTC gets converted to local IST.

How do you calculate UTC time in SQL?

SQL Server GETUTCDATE() Function The GETUTCDATE() function returns the current database system UTC date and time, in a 'YYYY-MM-DD hh:mm:ss.

How do you convert PST to GMT in SQL?

PST is 8 hours behind GMT , use add_to-date function to convert to GMT.


2 Answers

Create two tables and then join to them to convert stored GMT dates to local time:

TimeZones     e.g. ---------     ---- TimeZoneId    19 Name          Eastern (GMT -5) Offset        -5 

Create the daylight savings table and populate it with as much information as you can (local laws change all the time so there's no way to predict what the data will look like years in the future)

DaylightSavings --------------- TimeZoneId    19 BeginDst      3/9/2008 2:00 AM EndDst        11/2/2008 2:00 AM 

Join them like this:

inner join  TimeZones       tz on x.TimeZoneId=tz.TimeZoneId left join   DaylightSavings ds on tz.TimeZoneId=ds.LocalTimeZone      and x.TheDateToConvert between ds.BeginDst and ds.EndDst 

Convert dates like this:

dateadd(hh, tz.Offset +      case when ds.LocalTimeZone is not null      then 1 else 0 end, TheDateToConvert) 
like image 156
Eric Z Beard Avatar answered Oct 22 '22 20:10

Eric Z Beard


If you're in the US and only interested in going from UTC/GMT to a fixed time zone (such as EDT) this code should suffice. I whipped it up today and believe it's correct but use at your own risk.

Adds a computed column to a table 'myTable' assuming your dates are on the 'date' column. Hope someone else finds this useful.

ALTER TABLE myTable ADD date_edt AS 
  dateadd(hh, 
        -- The schedule through 2006 in the United States was that DST began on the first Sunday in April 
        -- (April 2, 2006), and changed back to standard time on the last Sunday in October (October 29, 2006). 
        -- The time is adjusted at 02:00 local time.
              CASE WHEN YEAR(date) <= 2006 THEN  
                    CASE WHEN 
                              date >=  '4/' + CAST(abs(8-DATEPART(dw,'4/1/' + CAST(YEAR(date) as varchar)))%7 + 1 as varchar) +  '/' + CAST(YEAR(date) as varchar) + ' 2:00' 
                          AND 
                              date < '10/' + CAST(32-DATEPART(dw,'10/31/' + CAST(YEAR(date) as varchar)) as varchar) +  '/' + CAST(YEAR(date) as varchar) + ' 2:00' 
                    THEN -4 ELSE -5 END
              ELSE
        -- By the Energy Policy Act of 2005, daylight saving time (DST) was extended in the United States in 2007. 
        -- DST starts on the second Sunday of March, which is three weeks earlier than in the past, and it ends on 
        -- the first Sunday of November, one week later than in years past. This change resulted in a new DST period 
        -- that is four weeks (five in years when March has five Sundays) longer than in previous years.[35] In 2008 
        -- daylight saving time ended at 02:00 on Sunday, November 2, and in 2009 it began at 02:00 on Sunday, March 8.[36]
                    CASE WHEN 
                              date >= '3/' + CAST(abs(8-DATEPART(dw,'3/1/' + CAST(YEAR(date) as varchar)))%7 + 8 as varchar) +  '/' + CAST(YEAR(date) as varchar) + ' 2:00' 
                          AND 
                              date < 
                                '11/' + CAST(abs(8-DATEPART(dw,'11/1/' + CAST(YEAR(date) as varchar)))%7 + 1 as varchar) +  '/' + CAST(YEAR(date) as varchar) + ' 2:00' 
                    THEN -4 ELSE -5 END
              END
  ,date)
like image 22
Bob Albright Avatar answered Oct 22 '22 19:10

Bob Albright