• Full disclosure, I attempted to convert from this function I wrote 10 years ago, but am getting the math wrong now.  - I'm pretty sure each part in this script works, I'm just not applying the new variables correctly.
    CREATE FUNCTION [dbo].[udfConvertFromGMT]
    (
      @InputDate DATETIME
    )
    RETURNS DATETIME
    AS
    /*
    Script Date: 08/11/2009
    Author: Sean Senneka
    Purpose: Converts from GMT to CST (or CDT if date is during daylight savings time)
    */
    --DECLARE @InputDate datetime
    --Select @InputDate = '10/4/1985 08:00:00'
    BEGIN
      DECLARE @converted_date DATETIME;
      DECLARE @DST_Start DATETIME;
      DECLARE @DST_End DATETIME;
      DECLARE @GMT_Offset_Destination INT;
      -- Get start and end dates for daylight savingstime for the year in question
      SELECT @DST_Start = CASE
              WHEN DATEPART(YEAR, @InputDate) >= 2007 THEN
               '3/1/' + CONVERT(VARCHAR, DATEPART(YEAR, @InputDate))
              WHEN DATEPART(YEAR, @InputDate)
               BETWEEN 1986 AND 2006 THEN
               '4/1/' + CONVERT(VARCHAR, DATEPART(YEAR, @InputDate))
              ELSE -- Year prior to 1986

               '4/30/' + CONVERT(VARCHAR, DATEPART(YEAR, @InputDate))
            END,
        @DST_End = CASE
             WHEN DATEPART(YEAR, @InputDate) >= 2007 THEN
              '11/1/' + CONVERT(VARCHAR, DATEPART(YEAR, @InputDate))
             ELSE
              '10/31/' + CONVERT(VARCHAR, DATEPART(YEAR, @InputDate))
            END;

      SELECT @DST_Start
       =
       --2007 till present get second Sunday of March, 1986-2006 get first Sunday of April, prior to 1986 get last sunday in April

       CASE
        WHEN DATEPART(YEAR, @InputDate) >= 2007 THEN
          DATEADD(
             HOUR,
             8,
             DATEADD(
                 DAY,
                 ((CEILING((CAST(17 AS DECIMAL(8, 2)) % DATEPART(dw, @DST_Start)) / 10) * 7) + 8)
                 - DATEPART(dw, @DST_Start),
                 @DST_Start
                )
            )
        WHEN DATEPART(YEAR, @InputDate)
          BETWEEN 1986 AND 2006 THEN
          DATEADD(
             HOUR,
             8,
             DATEADD(
                 DAY,
                 ((CEILING((CAST(17 AS DECIMAL(8, 2)) % DATEPART(dw, @DST_Start)) / 10) * 7) + 1)
                 - DATEPART(dw, @DST_Start),
                 @DST_Start
                )
            )
        ELSE -- Year prior to 1986

          DATEADD(HOUR, 8, DATEADD(DAY, 0 - (DATEPART(dw, @DST_Start) - 1), @DST_Start))
       END,

        --2007 till present get first Sunday of November, else get last Sunday of October

        @DST_End
         = CASE
           WHEN DATEPART(YEAR, @InputDate) >= 2007 THEN
             DATEADD(
                SECOND,
                -1,
                DATEADD(
                    HOUR,
                    8,
                    DATEADD(
                        DAY,
                        ((CEILING((CAST(17 AS DECIMAL(8, 2)) % DATEPART(dw, @DST_End))
                           / 10
                           ) * 7
                        ) + 1
                        ) - DATEPART(dw, @DST_End),
                        @DST_End
                      )
                   )
               )
           ELSE
             DATEADD(SECOND, -1, DATEADD(HOUR, 8, DATEADD(DAY, 0 - (DATEPART(dw, @DST_End) - 1), @DST_End)))
          END,
        @GMT_Offset_Destination = -360;

      RETURN CASE
         WHEN @InputDate
           BETWEEN @DST_Start AND @DST_End THEN
           DATEADD(MINUTE, @GMT_Offset_Destination + 60, @InputDate)
         ELSE
           DATEADD(MINUTE, @GMT_Offset_Destination, @InputDate)
        END;

    END;