i want to loop over a period of time in tsql, and print the utc datetimes and our local variant. We live in UTC +1, so i could easily add 1 hour, but in the summertime we live i
Here is a function (again US ONLY) but it is a bit more flexible. It will convert a UTC date to the server local time. It starts by adjusting the appointment date based on the current offset and then adjusts based on the difference of the current offset and the offset of the date of the appointment.
CREATE FUNCTION [dbo].[fnGetServerTimeFromUTC]
(
@AppointmentDate AS DATETIME,
@DateTimeOffset DATETIMEOFFSET
)
RETURNS DATETIME
AS
BEGIN
--DECLARE @AppointmentDate DATETIME;
--SET @AppointmentDate = '2016-12-01 12:00:00'; SELECT @AppointmentDate;
--Get DateTimeOffset from Server
--DECLARE @DateTimeOffset; SET @DateTimeOffset = SYSDATETIMEOFFSET();
DECLARE @DateTimeOffsetStr NVARCHAR(34) = @DateTimeOffset;
--Set a standard DatePart value for Sunday (server configuration agnostic)
DECLARE @dp_Sunday INT = 7 - @@DATEFIRST + 1;
--2006 DST Start First Sunday in April (earliest is 04-01) Ends Last Sunday in October (earliest is 10-25)
--2007 DST Start Second Sunday March (earliest is 03-08) Ends First Sunday Nov (earliest is 11-01)
DECLARE @Start2006 NVARCHAR(6) = '04-01-';
DECLARE @End2006 NVARCHAR(6) = '10-25-';
DECLARE @Start2007 NVARCHAR(6) = '03-08-';
DECLARE @End2007 NVARCHAR(6) = '11-01-';
DECLARE @ServerDST SMALLINT = 0;
DECLARE @ApptDST SMALLINT = 0;
DECLARE @Start DATETIME;
DECLARE @End DATETIME;
DECLARE @CurrentMinuteOffset INT;
DECLARE @str_Year NVARCHAR(4) = LEFT(@DateTimeOffsetStr,4);
DECLARE @Year INT = CONVERT(INT, @str_Year);
SET @CurrentMinuteOffset = CONVERT(INT, SUBSTRING(@DateTimeOffsetStr,29,3)) * 60 + CONVERT(INT, SUBSTRING(@DateTimeOffsetStr,33,2)); --Hours + Minutes
--Determine DST Range for Server Offset
SET @Start = CASE
WHEN @Year <= 2006 THEN CONVERT(DATETIME, @Start2006 + @str_Year + ' 02:00:00')
ELSE CONVERT(DATETIME, @Start2007 + @str_Year + ' 02:00:00')
END;
WHILE @dp_Sunday <> DATEPART(WEEKDAY, @Start) BEGIN
SET @Start = DATEADD(DAY, 1, @Start)
END;
SET @End = CASE
WHEN @Year <= 2006 THEN CONVERT(DATETIME, @End2006 + @str_Year + ' 02:00:00')
ELSE CONVERT(DATETIME, @End2007 + @str_Year + ' 02:00:00')
END;
WHILE @dp_Sunday <> DATEPART(WEEKDAY, @End) BEGIN
SET @End = DATEADD(DAY, 1, @End)
END;
--Determine Current Offset based on Year
IF @DateTimeOffset >= @Start AND @DateTimeOffset < @End SET @ServerDST = 1;
--Determine DST status of Appointment Date
SET @Year = YEAR(@AppointmentDate);
SET @Start = CASE
WHEN @Year <= 2006 THEN CONVERT(DATETIME, @Start2006 + @str_Year + ' 02:00:00')
ELSE CONVERT(DATETIME, @Start2007 + @str_Year + ' 02:00:00')
END;
WHILE @dp_Sunday <> DATEPART(WEEKDAY, @Start) BEGIN
SET @Start = DATEADD(DAY, 1, @Start)
END;
SET @End = CASE
WHEN @Year <= 2006 THEN CONVERT(DATETIME, @End2006 + @str_Year + ' 02:00:00')
ELSE CONVERT(DATETIME, @End2007 + @str_Year + ' 02:00:00')
END;
WHILE @dp_Sunday <> DATEPART(WEEKDAY, @End) BEGIN
SET @End = DATEADD(DAY, 1, @End)
END;
--Determine Appointment Offset based on Year
IF @AppointmentDate >= @Start AND @AppointmentDate < @End SET @ApptDST = 1;
SET @AppointmentDate = DATEADD(MINUTE, @CurrentMinuteOffset + 60 * (@ApptDST - @ServerDST), @AppointmentDate)
RETURN @AppointmentDate
END
GO