How to calculate the local datetime from a utc datetime in tsql (sql 2005)?

前端 未结 10 1354
Happy的楠姐
Happy的楠姐 2021-02-02 14:13

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

10条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-02 15:06

    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
    

提交回复
热议问题