Convert getdate() to EST - sql

I would like to convert getdate() in SQL Server to EST time.

UPDATED ANSWER (05-29-2020)
The Azure SQL team has released a new function which makes this even easier. SELECT CURRENT_TIMEZONE_ID() will return your server's timezone. Adding this function into the ORIGINAL ANSWER below yields a single query will work globally on all Azure SQL Servers.
SELECT CONVERT(DATETIME,GETDATE() AT TIME ZONE (SELECT CURRENT_TIMEZONE_ID()) AT TIME ZONE 'Eastern Standard Time')
This query will work on any Azure SQL Server.
ORIGINAL ANSWER:
There are a lot of answers here that are unnecessarily complex, or that don't account for daylight savings time. No massive CASE statements needed. No new stored procedure, or scalar/user defined functions are needed. As of SQL Server 2016, converting between timezones can be done with a single line of native sql. This has advantages. For example, it can be called from reports or used on databases that are read-only.
SELECT CONVERT(DATETIME,GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')
That's it. Above, we are using the AT TIME ZONE features, described in more detail here. There may be some functions and features that are new here, so an explanation is warranted. The query above calls GETDATE() and sets it's timezone as UTC using AT TIMEZONE. Implicitly, this is also changing it's datatype from a datetime to datetimeoffset. Next, we'll call AT TIMEZONE again to cut it over to EST. Lastly, we'll wrap the entire thing in CONVERT() to get it back to a datetime, dropping the unneeded +/- hours portion during the process.
Taking the query step-by-step ...
SELECT [GetDate] = GETDATE()
SELECT [GetDateAtUtc] = GETDATE() AT TIME ZONE 'UTC'
SELECT [GetDateAtUtcAtEst] = GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'
SELECT [GetDateEst] = CONVERT(DATETIME,GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')

Have you considered GETUTCDATE() and performing the offset from there?
If you mean EST as in standard time, then that is UTC-5, so
select dateadd(hour,-5,GETUTCDATE())

SQL server itself has the table current_utc_offset with correct offset for summer and winter time.
Please, try the query select * from current_utc_offset, change the date to different season on your server and review the table again.
So the correct function to get EST would be:
CREATE FUNCTION [dbo].[Getestlocaldatetime] ()
returns DATETIME
AS
BEGIN
DECLARE #zz NVARCHAR(12);
DECLARE #hh NVARCHAR(3);
DECLARE #dd DATETIME;
SET #zz = (SELECT current_utc_offset
FROM sys.time_zone_info
WHERE NAME = N'US Eastern Standard Time')
SET #hh = Substring(#zz, 1, 3);
SET #dd = Dateadd(hh, CONVERT(INT, #hh), Getutcdate())
RETURN #dd
END

EST is GMT-5 hours while EDT is GMT-4 hours.
To get EST:
select dateadd(hour,-5,GETUTCDATE())
To get EDT :
select dateadd(hour,-4,GETUTCDATE())

SELECT CONVERT(VARCHAR, CONVERT(DATETIME, GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'), 100) AS [Date_Result]
https://stackoverflow.com/a/49449695/6559330

using GETDATE() :
GMT :
DATE WILL BE DISPLAYED:
SELECT GETDATE()
EST :
USE GETDATE() FOR CONVERSION NOW:
SELECT DATEADD(HOUR, -4, CONVERT(varchar(20),GETDATE(),120))

If you are attempting to output a local time, such as eastern time, with Daylight savings time, you need a function that Detects the start and end of daylight savings time and then applies a variable offset: I've found this: http://joeyiodice.com/convert-sql-azure-getdate-utc-time-to-local-time/ useful.

GetDate() is the system time from the server itself.
Take the hour difference of the GetDate() now and the time it is now in EST use this code where 1 is that said difference ( in this instance the server is in Central Time zone) (This is also assuming your server is accounting for DST)
SELECT Dateadd(hour, 1, Getdate()) AS EST

For those who are using latest version of sql server can create a .net function
A scalar-valued function (SVF) returns a single value, such as a string, integer, or bit value. You can create scalar-valued user-defined functions in managed code using any .NET Framework programming language. These functions are accessible to Transact-SQL or other managed code. For information about the advantages of CLR integration and choosing between managed code and Transact-SQL.
Since .NET has access to all time zone at operating system so you don't have to calculate daylight saving -4 or -5 fundamentals.
var timeUtc = DateTime.UtcNow;
TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime easternTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);

Select CONVERT(DATETIME,GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')

If you want to do this without calling a function, you can do it with a CASE statement as well. The code below converts a UTC field to Mountain Time accounting for daylight savings. For EST, you would just change all the -6 to -4 and change all the -7 to -5.
--Adjust a UTC value, in the example the UTC field is identified as UTC.Field, to account for daylight savings time when converting out of UTC to Mountain time.
CASE
--When it's between March and November, it is summer time which is -6 from UTC
WHEN MONTH ( UTC.Field ) > 3 AND MONTH ( UTC.Field ) < 11
THEN DATEADD ( HOUR , -6 , UTC.Field )
--When its March and the day is greater than the 14, you know it's summer (-6)
WHEN MONTH ( UTC.Field ) = 3
AND DATEPART ( DAY , UTC.Field ) >= 14
THEN
--However, if UTC is before 9am on that Sunday, then it's before 2am Mountain which means it's still Winter daylight time.
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '9:00'
--Before 2am mountain time so it's winter, -7 hours for Winter daylight time
THEN DATEADD ( HOUR , -7 , UTC.Field )
--Otherwise -6 because it'll be after 2am making it Summer daylight time
ELSE DATEADD ( HOUR , -6 , UTC.Field )
END
WHEN MONTH ( UTC.Field ) = 3
AND ( DATEPART ( WEEKDAY , UTC.Field ) + 7 ) <= DATEPART ( day , UTC.Field )
THEN
--According to the date, it's moved onto Summer daylight, but we need to account for the hours leading up to 2am if it's Sunday
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '9:00'
--Before 9am UTC is before 2am Mountain so it's winter Daylight, -7 hours
THEN DATEADD ( HOUR , -7 , UTC.Field )
--Otherwise, it's summer daylight, -6 hours
ELSE DATEADD ( HOUR , -6 , UTC.Field )
END
--When it's November and the weekday is greater than the calendar date, it's still Summer so -6 from the time
WHEN MONTH ( UTC.Field ) = 11
AND DATEPART ( WEEKDAY , UTC.Field ) > DATEPART ( DAY , UTC.Field )
THEN DATEADD ( HOUR , -6 , UTC.Field )
WHEN MONTH ( UTC.Field ) = 11
AND DATEPART ( WEEKDAY , UTC.Field ) <= DATEPART ( DAY , UTC.Field )
--If the weekday is less than or equal to the calendar day it's Winter daylight but we need to account for the hours leading up to 2am.
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '8:00'
--If it's before 8am UTC and it's Sunday in the logic outlined, then it's still Summer daylight, -6 hours
THEN DATEADD ( HOUR , -6 , UTC.Field )
--Otherwise, adjust for Winter daylight at -7
ELSE DATEADD ( HOUR , -7 , UTC.Field )
END
--If the date doesn't fall into any of the above logic, it's Winter daylight, -7
ELSE
DATEADD ( HOUR , -7 , UTC.Field )
END

Related

SQL Convert int64/Time to Date

I have a SQL table with a column of varchar datatype that contains dates in timestamp format.
AccessId Date ComputerName NumberOfTries
-------------------------------------------------------------
1 132926085611026702 TESTE 1
When I use the command
[datetime]::FromFileTime('132926085611026702')
in PowerShell, I can get properly the data:
Thursday, March 3, 2022 4:03:42 PM
But I would like to know how I do this direct conversion through SQL to use in Power BI
Given that DateTime.FromFileTime(Int64) handles 1601-01-01 00:00:00Z-based values....
A Windows file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC).
...then you need to use CONVERT( bigint, "Date" ), and then pass that into DATEADD with nanosecond and '1601-01-01 00:00:00':
SELECT
DATEADD( nanosecond, CONVERT( bigint, "Date" ), CONVERT( datetime2(7), '1601-01-01 00:00:00' ) )
FROM
myTable

DateTime conversion and comparison in SQL Query

I have a sql query for pulling a report from a table. The idea is to pull the sum of counts, grouped by day of the week, in the local timezone. Dates in the table are stored in UTC.
SELECT (SUM(t.di1) + SUM(t.di2) + SUM(t.di3) + SUM(t.di4)) AS [ScanCount],
DATEPART(WEEKDAY, t.LocalTime) AS [weekday]
FROM (SELECT di1,
di2,
di3,
di4,
CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS LocalTime
FROM tableName
WHERE DeviceId = 649754) t
WHERE t.LocalTime > '03/16/2020 00:00'
AND t.LocalTime < '03/16/2020 23:59:59'
GROUP BY DATEPART(WEEKDAY, t.LocalTime)
ORDER BY DATEPART(WEEKDAY, t.LocalTime);
A query like this should only return a single day of the week count, but it returns 2 days. This obviously has something to do with the difference in time zones, whereas the UTC time contains dates from both 3/15 and 3/16. It seems that the conversion from UTC to Pacific Time works in the output but the UTC values are used in the where clause. How can I do this comparison to the new converted datetimes and not to the original UTC times?
Comparison between datetimeoffset and string literal works in UTC.
Simplest solution will be to convert datetimeoffset to datetime2.
Modify your inner query to:
cast(CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' as datetime2(0)) AS LocalTime

Add or remove hours to timestamp while select

We have timestamp stored in utc in format "2017-08-25 14:34:20.0000000 +00:00". Our customer selects timestamps directly from db and they want to add additional hours in order to fit timestamp stored with their timezone. Can I set a select query to make it to add hours to current timestamp? Database sql-server
Maybe this would help:
The DATEADD() function adds or subtracts a specified time interval from a date.
DATEADD(interval, number, date)
interval Required. The time/date part to return. Can be one of the
following values:
year, yyyy, yy = Year quarter,
qq, q = Quarter month,
mm, m = month
dayofyear = Day of the year day, dy,
y = Day
week, ww, wk = Week
weekday, dw, w = Weekday
hour, hh = hour
minute, mi, n = Minute
second, ss, s = Second
millisecond, ms = Millisecond
number Required. The number of intervals to use
date Required. The date to which the interval should be added
DATEADD(HOUR,1,fieldFromSQL)
I find the new command "AT TIME ZONE" very useful for this.
This requires SQL Server 2016 sp1.
Here is how:
DECLARE #FieldFromSQL DATETIME2= GETUTCDATE()
SELECT #FieldFromSQL AS DateTimeInUTC , #FieldFromSQL
AT TIME ZONE 'utc'
AT TIME ZONE 'Central Europe Standard Time' AS DateTimeInLocalTime
It also works across Daylight time changes, with which I've had many problems.

UTC time to Local Time Zone(Central Time) Conversion MS SQL Sever

This question is a follow up from this question.
I have a UTC time column and I want convert to into current local time (Central Time Zone or America/Chicago). I tried to use the function from #Ron Smith's answer, which is [dbo].[fn_UTC_to_DST] function.
In that function, it needs two arguments such as UTC time and offset. I input both like this,
SELECT dbo.fn_UTC_to_DST([time(UTC)],5) as Date
FROM tbl
Since we are in Day Light Saving time, I am using 5 as my offset. My output looks like this,
2017-09-27 20:55:00.000
2017-09-27 20:56:00.000
2017-09-27 20:57:00.000
2017-09-27 20:58:00.000
...
Which should be (central time),
2017-09-27 09:55:00.000
2017-09-27 09:56:00.000
2017-09-27 09:57:00.000
2017-09-27 09:58:00.000
...
So, I changed #Ron Smith's function like this,
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
#UTC datetime,
#StandardOffset int
)
RETURNS datetime
AS
BEGIN
declare
#DST datetime,
#SSM datetime, -- Second Sunday in March
#FSN datetime -- First Sunday in November
-- get DST Range
set #SSM = datename(year,#UTC) + '0314'
set #SSM = dateadd(hour,-5,dateadd(day,datepart(dw,#SSM)*-1+1,#SSM)) -- Changed from 2 to -5
set #FSN = datename(year,#UTC) + '1107'
set #FSN = dateadd(second,-6,dateadd(hour,2,dateadd(day,datepart(dw,#FSN)*-1+1,#FSN))) -- changed from 1 to -6
-- add an hour to #StandardOffset if #UTC is in DST range
if #UTC between #SSM and #FSN
set #StandardOffset = #StandardOffset + 1
-- convert to DST
set #DST = dateadd(hour,#StandardOffset,#UTC)
-- return converted datetime
return #DST
END
GO
However, this still gives me the same result as above.
1. What should I change for Central time?
2. Is there a way to automatically change to -5 during daylight saving time and -6 during standard time?
EDIT:
After looking at the Answer and the reference link from #Siyual,I created the dbo.TZCalendar table and I tried to create a function like this (takes one argument and returns a date from refrence link)
CREATE FUNCTION dbo.ConvertUTCToLocal
(
#utc DATETIME
)
RETURNS Datetime
AS BEGIN
SELECT UTCToLocal = DATEADD(HOUR, CASE
-- within Daylight Savings Time
WHEN #utc >= UTC_DST_Start AND #utc < UTC_DST_End
THEN -5
-- within Standard Time
ELSE -6 END, #utc)
FROM dbo.TZCalendar
WHERE CONVERT(DATE,#utc) >= [Year]
AND CONVERT(DATE,#utc) < DATEADD(YEAR, 1, [Year])
END
GO
This, does not work. The logic seems right for me, but, I just need a function without SCHEMABINDING (which is done in the reference link). How can I do that?
If you're using SQL Server 2016+ (or Azure SQL Database) this is built in:
SELECT YourInputDatetimeInUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Central Standard Time'
The first one asserts your input is UTC, the second one converts it to US Central time, inclusive of DST when applicable (using a Windows time zone identifier).
However, since you said SQL 2012, I'll recommend my SQL Server Time Zone Support project, where this is a single operation and uses IANA identifiers:
SELECT Tzdb.UtcToLocal(YourInputDatetimeInUTC, 'America/Chicago')
The linked answer (Sql Server Specify time in another timezone) will get you most of the way there, but to answer the rest of your question, you'll have to make some modifications.
Firstly, I would create a DST calendar, since the DST start and end dates are something that we can compute:
CREATE TABLE dbo.TZCalendar
(
Year Int PRIMARY KEY,
UTC_DST_Start SMALLDATETIME NOT NULL,
UTC_DST_End SMALLDATETIME NOT NULL
);
SET DATEFIRST 7;
;WITH cte(d,p) AS
(
-- all the years from 2000 through 50 years after the current year:
SELECT TOP (YEAR(GETDATE())-2000+51) DATEADD(YEAR,number,'20000101'),
CASE WHEN number < 7 THEN 1 ELSE 0 END -- year < 2007 = 1, else 0
FROM [master].dbo.spt_values WHERE [type] = N'P' ORDER BY number
)
INSERT dbo.TZCalendar([Year],UTC_DST_Start,UTC_DST_End)
SELECT Year(d),
-- First Sunday in April (< 2007) or second Sunday in March (>= 2007):
DATEADD(HOUR, 7, DATEADD(DAY,(7-DATEPART(WEEKDAY,DATEADD(MONTH,2+p,d))+1)%7
+(7*ABS(p-1)),DATEADD(MONTH,2+p,d))),
-- Last Sunday in October (< 2007) or first Sunday in November (>= 2007):
DATEADD(HOUR, 6, DATEADD(DAY,(7-DATEPART(WEEKDAY,DATEADD(MONTH,10,d))+1)%7
-(7*p),DATEADD(MONTH,10,d)))
FROM cte
ORDER BY d;
This will generate the DST times from the year 2000 to 2067 (this can be expanded based on your needs).
Next, I would create a function to take a DATE in UTC and return the value in either CST or CDT, depending on the time of the year.
Create Function dbo.fnConvertUTCToCT(#UTC DateTime)
Returns DateTime
As Begin
Declare #Offset Int = 0
Select #Offset = Case When #UTC Between UTC_DST_Start And UTC_DST_End Then -5 Else -6 End
From dbo.TZCalendar
Where Year = Year(#UTC)
Set #UTC = DateAdd(Hour, #Offset, #UTC)
Return #UTC
End
Then you can just call that function with any time specified and get the CST or CDT translation returned:
Select dbo.fnConvertUTCToCT(GetUTCDate())
2017-09-27 12:24:26.377
UTC time to Central time including DST adjustments
This SQL expression converts UTC time to Central Standard time which also adjusts itself for the Day Light Saving Time period.
DATEADD(HOUR,datediff(HOUR,[HTMPOSTEDDATETIME] at time zone 'Central Standard Time',[HTMPOSTEDDATETIME]),[HTMPOSTEDDATETIME]) [JNL Posted Date]

Determine if daylight saving time is active? SQL Server

I have a table with users, UTC time offset, and if they observe daylight saving time. Is there a built in way to get the correct user time?
The sys.time_zone_info table introduced in SQL 2016 allows to determine the offset from UTC and whether DST is currently in effect.
SELECT * FROM sys.time_zone_info
The query result will be:
Right now I'm doing this:
SELECT
CASE USEDAYLIGHTSAVING
WHEN 1 THEN
CASE DATEDIFF(HH,GETUTCDATE(),GETDATE())
-- I know the server is set to Mountan time and follows daylight saving time
-- MDT = -6
-- MST = -7
WHEN -6 THEN
DATEADD(HH,TIMEZONEOFFSET+1,GETUTCDATE())
ELSE
DATEADD(HH,TIMEZONEOFFSET,GETUTCDATE())
END
ELSE
DATEADD(HH,TIMEZONEOFFSET,GETUTCDATE())
END
FROM
USERS
It works but if the server get's moved to another timezone or doesn't fallow daylight saving time I'm hosed.
I have a table with users, UTC time offset, and if they observe daylight saving time. Is there a built in way to get the correct user time?
Different time zones around the world observe DST in different ways. They start and stop at different times of the day. Simply having an offset and DST flag is not enough to reliably convert.
Instead, you need a time zone identifier, such as America/Los_Angeles, or one of the others listed here. Once you have that, you can use my SQL Server Time Zone Support project to do the conversions.
This won't work in all cases, but is a quick fix for those in the US w/ DST defined as between the 2nd Sunday of March and the 1st Sunday of November.
DECLARE #Date datetime2 = '2018-11-04 02:01:00'
SELECT
CASE
WHEN #Date between
DATETIMEFROMPARTS(YEAR(#Date), 3, (8 - DATEPART(WEEKDAY, DATEFROMPARTS(YEAR(#Date), 3, 1))) + 8, 02, 00, 00, 00)
and
DATETIMEFROMPARTS(YEAR(#Date), 11, (8 - DATEPART(WEEKDAY, DATEFROMPARTS(YEAR(#Date), 11, 1))) + 1, 02, 00, 00, 00)
THEN 1
ELSE 0
END --Is it dst?
using SQL 2016 system table (noted by #anacv),
To get current time for a timezone (DST or PDT) if server/timestamp is GMT
declare #currentDatetime datetime
declare #tzone varchar(100)
set #tzone = 'Pacific Standard Time'
set #currentDatetime = dateadd(MINUTE, (select cast(right(current_utc_offset,2) as int) FROM sys.time_zone_info where name=#tzone) , dateadd(HOUR,(select cast(left(current_utc_offset,3) as int) FROM sys.time_zone_info where name=#tzone), CURRENT_TIMESTAMP))