Snowflake CONVERT_TIMEZONE bug? - snowflake-cloud-data-platform

In Snowflake, when converting some local dates to UTC and then back to local timezone using CONVERT_TIMEZONE function, the end result is off by one hour. For example:
ALTER SESSION SET TIMEZONE = 'Canada/Eastern';
select
cast('1949-04-24' as timestamp) as date_local -- because TIMEZONE = 'Canada/Eastern'
, convert_timezone('Canada/Eastern', 'UTC', '1949-04-24') as date_utc
, convert_timezone('UTC', 'Canada/Eastern', convert_timezone('Canada/Eastern', 'UTC', '1949-04-24')) as date_local1
The results are:
DATE_LOCAL
DATE_UTC
DATE_LOCAL1
1949-04-24 00:00:00.0
1949-04-24 05:00:00.0
1949-04-24 01:00:00.0
I expect both DATE_LOCAL and DATE_LOCAL1 to be identical, however DATE_LOCAL1 is one hour off.
Is this expected? Am I missing something or there is a bug in the CONVERT_TIMEZONE function?

This is not a bug. This is about Daylight Saving Time (DST). In 1949, DST started on Sunday, 24 April, 00:00. So when you convert it to UTC, It becomes 1949-04-24 05:00:00.0. When you convert it back, it becomes 01:00 because of DST, because it's the time that the clocks were turned forward one hour.

Related

SQL Server UTC to Local time 'at time zone' not offseting time

I am trying to convert from UTC to Eastern Standard Time. But the code below is not producing the result that I expect.
SELECT
GETUTCDATE() AS UTC_Date, --original datetime value
GETUTCDATE() AT TIME ZONE 'Eastern Standard Time' AS ETZ
The result is
UTC_Date = 2022-01-16 01:15:39.920
ETZ =2022-01-16 01:15:39.920 -05:00
How can I get a simple date time with the offset applied instead of just added on to the end of the string?

How to convert AT TIME ZONE return value to actual datetime value in SQL Server 2016?

I want to convert UTC value to Eastern Time Zone (any time zone) in SQL directly. I am trying below query but getting DATETIMEOFFSET.
I am trying to convert below UTC DateTime into Eastern time zone.
SELECT CONVERT(DATETIME,'2019-05-27 13:00:00' AT TIME ZONE 'Eastern Standard Time'
I am expecting output for above query is '2019-05-27 09:00:00' but the actual output is coming like '2019-05-27 13:00:00 -04:00'
you can do this
select CONVERT(datetime, SWITCHOFFSET(CONVERT(datetimeoffset, '2019-05-27 13:00:00'), DATEPART(TZOFFSET,
SYSDATETIMEOFFSET() AT TIME ZONE 'Eastern Standard Time')))
You're close. So far, you've told SQL Server the native time zone for the datetime that you've passed in. Now you need to tell it to convert it to something else. This should do the trick:
SELECT CONVERT(DATETIME,'2019-05-27 13:00:00')
AT TIME ZONE 'Eastern Standard Time'
AT TIME ZONE 'UTC';
This should give you something with the -00:00 offset. If you don't want that, cast the result back to a time zone-less datatype.

Convert UTC on Azure to EST Time (including Daylight saving Time-dynamic version)

I have a question about converting UTC time zone to EST time zone since I am still new to SQL language and Azure platform. In log file, I used system built-in function "GetDate()" in log file to get the Date/Time. However, while accessing Azure database on my SSMS, using system-built in function (GetDate()) gives me the datetime in UTC time zone, which is 4 hours ahead of Eastern Time Zone (EST). I have asked similar question before for converting UTC to EST here
, and #DanGuzman helped me fix my code. But this question is more about converting UTC to EST (considering Daylight saving time dynamically). Below is my code so far, and I used this link as a reference. However, I would like to make my code dynamic so that I can keep using it for 2020, 2021 as well.
Below code works ONLY for 2019 (since Daylight Saving starts on March 10,2019 until November 3, 2019. Within the date range, below code forward one hour of EST time during daylight saving time range.
CREATE FUNCTION [dbo].[EST_GetDateTime]
(
-- no parameter
)
RETURNS datetime
AS
BEGIN
DECLARE
#EST datetime,
#StandardOffset int,
#DST datetime, -- Daylight Saving Time
#SSM datetime, -- Second Sunday in March
#FSN datetime -- First Sunday in November
-- get DST Range
set #EST = CAST(DATEADD(hh,-5,GETDATE()) AS DATETIME)
set #StandardOffset = 0
set #SSM = datename(year,#EST) + '0310' -- Set which day daylight saving start (for 2019, March 10)
set #SSM = dateadd(hour,2,dateadd(day,datepart(dw,#SSM)*-1+1,#SSM))
set #FSN = datename(year,#EST) + '1103' -- Set which day daylight saving start (for 2019, March 10)
set #FSN = dateadd(second,-1,dateadd(hour,2,dateadd(day,datepart(dw,#FSN)*-1+1,#FSN)))
-- add an hour to #StandardOffset if #EST is in DST range
if #EST between #SSM and #FSN
set #StandardOffset = #StandardOffset + 1
-- convert to DST
set #EST = CAST(DATEADD(hh,-5+#StandardOffset ,GETDATE()) AS DATETIME)
RETURN #EST
END
GO
Can someone please give any suggestions how to improve my existing code (able to work dynamically) so that I do not need to change the function every single year for adjusting day light saving.
Since Azure SQL is ahead of the on-premises version, I think you can use the syntax select getutcdate() at time zone 'UTC' at time zone 'Eastern Standard Time'. Also, I'd switch to getutcdate() as that should be invariant regardless of the server's TZ. More information on at time zone here.
One method is a function that converts SYSDATETIMEOFFSET() to EST and converts the result to datetime:
CREATE FUNCTION dbo.EST_GetDateTime()
RETURNS datetime
AS
BEGIN
RETURN(SELECT CAST(SYSDATETIMEOFFSET() AT TIME ZONE 'Eastern Standard Time' AS datetime));
END
GO
--example usage
SELECT dbo.EST_GetDateTime();
GO
This should do exactly what you need.
SELECT CONVERT(DATETIME,GETDATE() AT TIME ZONE (SELECT CURRENT_TIMEZONE_ID()) AT TIME ZONE 'Eastern Standard Time')
Explanation: This gets the current datetime in the server's local timezone using CURRENT_TIMEZONE_ID(). We then use AT TIME ZONE to make it a datetimeoffset, then we cut that datetimeoffset over to requested timezone... here 'Eastern Standard Time'. Lastly the whole thing is wrapped in a CONVERT() to cut the datetimeoffset objects over to a proper datetime datatype.

(T-SQL) Did daylight savings occur in the last hour?

I have a process that is going to use table partitioning (each partition is 1 hour) and I need to handle the daylight savings flips when archiving out the data.
For instance, this past weekend it went from 1:59:59 to 1:00:00, so the second time that the partitioning code ran at 1:05am nothing would occur - the midnight hour had already been SWITCHed out.
However, when spring rolls around, the time goes from 1:59am to 3:00am, so when the job runs at 3:05, it would SWITCH out 2am.... leaving the data from the 1am hour in the original table.
In theory I can just look for the oldest not-current partition with data and flip that one (partition key is a default getdate() constraint), but I was wondering if there was some way to use AT TIME ZONE to determine that daylight savings had "occurred", so that we could have different code to handle that older hour still being out there.
Thanks.
Maybe something like this. Basically take your current getdate() and use AT TIME ZONE with any time zone that observes. Then use DATEPART tz and compare your current and before.
Regardless of what the server time zone is, using AT TIME ZONE will get you the offset for a particular datetime value in that time zone.
For comparison of before I think you'd need to use 2 hours, 1 for the switch and 1 for how far back you want to check.
Give this a look:
DECLARE #BeforeDate DATETIME = '2018-11-04 1:59' --Before the change
DECLARE #AfterDate DATETIME = '2018-11-04 3:00' --After the change
--use can use AT TIME ZONE with DATEPART tz which tells you offset in minutes
--I'm in central, any should work for any that observe the time change
--Your offset is different because of the change.
SELECT DATEPART(tz, #BeforeDate AT TIME ZONE 'Central Standard Time')
SELECT DATEPART(tz, #AfterDate AT TIME ZONE 'Central Standard Time')
--using the above you could possibly compare current offset to 2 hours prior to see if they changed. 2 hours, 1 for the switch and 1 for how far back you want to compare.
DECLARE #CurrentDate DATETIME = '2018-11-04 3:00' --"simulate" getdate() as of the time change
DECLARE #PriorOffSet INT = (SELECT DATEPART(tz, DATEADD(HOUR, -2, #CurrentDate) AT TIME ZONE 'Central Standard Time')) --You'd have to subtract 2 hours to account for the hour shift and the hour back you want to check.
DECLARE #CurrentOffset INT = (SELECT DATEPART(tz, #CurrentDate AT TIME ZONE 'Central Standard Time'))
SELECT #PriorOffSet, #CurrentOffset
IF #PriorOffSet <> #CurrentOffset
SELECT 'Time changed in the last hour'
ELSE
SELECT 'No time change in the last hour'

Sql Server Convert between UTC-0 string dates and the server local TimeZone

When I execute the following, when the server's TimeZone is +01:00:
Convert(datetime, '2015-02-10T23:00:00Z', 127)
The result is:
10.02.2015 23:00:00
That is the Date at UTC-0. My expected value would be 11.02.2015 00:00:00, that is the date converted to the server's TimeZone.
Convert function doesn't convert time to UTC. It just simply changes the format of the input string. Here is what you need to do.
Find difference in hours between server local time and UTC time:
DECLARE #hour INT
SELECT #hour = DATEDIFF(HOUR, GETUTCDATE(), GETDATE())
Add the difference to the date you're trying to convert:
SELECT CONVERT(DATETIME, DATEADD(hour, #hour, '2015-02-10T23:00:00Z'), 127)
If you know your timezone difference in hours and you know that it's unlikely to be changed, then use a shorter version:
SELECT CONVERT(DATETIME, DATEADD(hour, -1, '2015-02-10T23:00:00Z'), 127)
You shouldn't really depend on the time zone setting of a server. However, if you have a specific time zone in mind, you could use my SQL Server Time Zone Support project.
After installation:
SELECT Tzdb.UtcToLocal('2015-02-10T23:00:00Z', 'Europe/Paris')
Choose a time zone from the list here.

Resources