복붙노트

[SQL] SQL Server의 일광 절약 시간 시작 및 종료 기능을 만드는 방법

SQL

SQL Server의 일광 절약 시간 시작 및 종료 기능을 만드는 방법

나는 반환 일광 절약 시간이 날짜를 시작하고 일광 절약 시간 종료 날짜 있다는 SQL 서버에서 함수를 작성해야합니다.

나는 그러나 그들은 모두 3 월 1 일 및 11 월과 그게 기술적으로 정확하지의 첫 번째 날짜를 사용하고, 웹에서 몇 가지 예를 통해 왔어요.

일광 절약 시간은 11 월 첫 번째 일요일 오전 2시에서 3 월의 두 번째 일요일 오전 2시과 끝에서 시작됩니다.

나는 아래의 코드로 시작했지만 나는 확실히 그 틀렸다. 모든 지원에 감사드립니다! :)

DECLARE @DSTSTART DATETIME

SELECT @DSTSTART = CASE WHEN 
DATEPART(MONTH, SYSDATETIME()) = 3
AND DATEPART(weekday, SYSDATETIME()) = 1
AND DATEDIFF(week,dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, SYSDATETIME()), 0)), 0), SYSDATETIME() - 1) = 2
AND DATEPART(HOUR, SYSDATETIME()) = 2
THEN SYSDATETIME()
END
RETURN (@DSTSTART)
END
GO

해결법

  1. ==============================

    1.일정은 국가에 따라 변경이 일광 절약 시간을 잊고, 또한 수년에 걸쳐 변경 될 수 있습니다하지 마십시오 : 현재 미국의 시스템은 예를 들어, 2007 년에 발효.

    일정은 국가에 따라 변경이 일광 절약 시간을 잊고, 또한 수년에 걸쳐 변경 될 수 있습니다하지 마십시오 : 현재 미국의 시스템은 예를 들어, 2007 년에 발효.

    당신이 미국의 현재 시스템을 원하는 가정하면, 여기에 특정 연도에 대한 대답의 한 형태입니다.

    SET DATEFIRST 7
    
    DECLARE @year INT = 2013
    DECLARE
        @StartOfMarch DATETIME ,
        @StartOfNovember DATETIME ,
        @DstStart DATETIME ,
        @DstEnd DATETIME
    
    
    
    SET @StartOfMarch = DATEADD(MONTH, 2, DATEADD(YEAR, @year - 1900, 0))
    SET @StartOfNovember = DATEADD(MONTH, 10, DATEADD(YEAR, @year - 1900, 0));
    SET @DstStart = DATEADD(HOUR, 2,
                            DATEADD(day,
                                    ( ( 15 - DATEPART(dw, @StartOfMarch) ) % 7 )
                                    + 7, @StartOfMarch))
    SET @DstEnd = DATEADD(HOUR, 2,
                          DATEADD(day,
                                  ( ( 8 - DATEPART(dw, @StartOfNovember) ) % 7 ),
                                  @StartOfNovember))
    
    
    SELECT
        @DstStart AS DstStartInUS ,
        @DstEnd AS DstEndInUS
    

    또는 기능으로,하지만 당신은 그렇지 않으면 수학이 꺼집니다, DATEFIRST가 7로 설정되어 있는지 알아야합니다.

    CREATE FUNCTION GetDstStart ( @Year AS INT )
    RETURNS DATETIME
    AS
        BEGIN
    
            DECLARE
                @StartOfMarch DATETIME ,
                @DstStart DATETIME 
    
            SET @StartOfMarch = DATEADD(MONTH, 2,
                                        DATEADD(YEAR, @year - 1900, 0))
            SET @DstStart = DATEADD(HOUR, 2,
                                    DATEADD(day,
                                            ( ( 15 - DATEPART(dw,
                                                              @StartOfMarch) )
                                              % 7 ) + 7, @StartOfMarch))
            RETURN @DstStart
        END
    
    GO;
    
    
    CREATE FUNCTION GetDstEnd ( @Year AS INT )
    RETURNS DATETIME
    AS
        BEGIN
            DECLARE
                @StartOfNovember DATETIME ,
                @DstEnd DATETIME
    
            SET @StartOfNovember = DATEADD(MONTH, 10,
                                           DATEADD(YEAR, @year - 1900, 0))
            SET @DstEnd = DATEADD(HOUR, 2,
                                  DATEADD(day,
                                          ( ( 8 - DATEPART(dw,
                                                           @StartOfNovember) )
                                            % 7 ), @StartOfNovember))
            RETURN @DstEnd
        END
    
  2. ==============================

    2.개인적으로, 나는 그것이 3 월 두 번째 일요일을 발견하는 것보다 11 월 첫 번째 일요일을 쉽게 찾을 생각합니다. 당신이 하나를 찾을 경우 항상 그들 사이 2백38일이 때문에 다행히, 당신은 다른 사람을 찾을 수 있습니다. 그래서 여기 DST의 끝을 찾을 수있는 편리한 기능입니다 :

    개인적으로, 나는 그것이 3 월 두 번째 일요일을 발견하는 것보다 11 월 첫 번째 일요일을 쉽게 찾을 생각합니다. 당신이 하나를 찾을 경우 항상 그들 사이 2백38일이 때문에 다행히, 당신은 다른 사람을 찾을 수 있습니다. 그래서 여기 DST의 끝을 찾을 수있는 편리한 기능입니다 :

    create function GetDstEnd (
                               @Year int
                              )
    returns datetime
    as
    begin
    
       declare @DstEnd datetime;
    
       ;with FirstWeekOfNovember
       as (
           select top(7)
                  cast(@Year as char(4))
                + '-11-0'
                + cast(row_number() over(order by object_id) as char(1))
                + ' 02:00:00'
                  'DST_Stops'
             from sys.columns
          )
       select @DstEnd = DST_Stops
         from FirstWeekOfNovember
        where datepart(weekday,DST_Stops) = 1
    
       return @DstEnd;
    
    end;
    

    이제 DST의 시작은 238일 이전 버전과 동일한 기능입니다.

    create function GetDstStart (
                                 @Year int
                                )
    returns datetime
    as
    begin;
    
       declare @DstStart datetime;
    
       ;with FirstWeekOfNovember
       as (
           select top(7)
                  cast(@Year as char(4))
                + '-11-0'
                + cast(row_number() over(order by object_id) as char(1))
                + ' 02:00:00'
                  'DST_Stops'
             from sys.columns
          )
       select @DstStart = dateadd(day,-238,DST_Stops)
         from FirstWeekOfNovember
        where datepart(weekday,DST_Stops) = 1
    
       return @DstStart;
    
    end;
    go
    
  3. ==============================

    3.SQL Server 버전 2016는 한번에 모두이 문제를 해결합니다. 이전 버전에 대한 CLR 솔루션은 아마 가장 쉬운 방법입니다. 또는 (미국 만 같은) 특정의 DST 규칙를 들어, T-SQL 기능은 상대적으로 간단 할 수있다.

    SQL Server 버전 2016는 한번에 모두이 문제를 해결합니다. 이전 버전에 대한 CLR 솔루션은 아마 가장 쉬운 방법입니다. 또는 (미국 만 같은) 특정의 DST 규칙를 들어, T-SQL 기능은 상대적으로 간단 할 수있다.

    그러나, 나는 일반 T-SQL 솔루션은 수있을 것 같아요. 긴 공격자는 xp_regread 작품으로,이 시도 :

    CREATE TABLE #tztable (Value varchar(50), Data binary(56));
    DECLARE @tzname varchar(150) = 'SYSTEM\CurrentControlSet\Control\TimeZoneInformation'
    EXEC master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @tzname, 'TimeZoneKeyName', @tzname OUT;
    SELECT @tzname = 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\' + @tzname
    INSERT INTO #tztable
    EXEC master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @tzname, 'TZI';
    SELECT                                                                                  -- See http://msdn.microsoft.com/ms725481
     CAST(CAST(REVERSE(SUBSTRING(Data,  1, 4)) AS binary(4))      AS int) AS BiasMinutes,   -- UTC = local + bias: > 0 in US, < 0 in Europe!
     CAST(CAST(REVERSE(SUBSTRING(Data,  5, 4)) AS binary(4))      AS int) AS ExtraBias_Std, --   0 for most timezones
     CAST(CAST(REVERSE(SUBSTRING(Data,  9, 4)) AS binary(4))      AS int) AS ExtraBias_DST, -- -60 for most timezones: DST makes UTC 1 hour earlier
     -- When DST ends:
     CAST(CAST(REVERSE(SUBSTRING(Data, 13, 2)) AS binary(2)) AS smallint) AS StdYear,       -- 0 = yearly (else once)
     CAST(CAST(REVERSE(SUBSTRING(Data, 15, 2)) AS binary(2)) AS smallint) AS StdMonth,      -- 0 = no DST
     CAST(CAST(REVERSE(SUBSTRING(Data, 17, 2)) AS binary(2)) AS smallint) AS StdDayOfWeek,  -- 0 = Sunday to 6 = Saturday
     CAST(CAST(REVERSE(SUBSTRING(Data, 19, 2)) AS binary(2)) AS smallint) AS StdWeek,       -- 1 to 4, or 5 = last <DayOfWeek> of <Month>
     CAST(CAST(REVERSE(SUBSTRING(Data, 21, 2)) AS binary(2)) AS smallint) AS StdHour,       -- Local time
     CAST(CAST(REVERSE(SUBSTRING(Data, 23, 2)) AS binary(2)) AS smallint) AS StdMinute,
     CAST(CAST(REVERSE(SUBSTRING(Data, 25, 2)) AS binary(2)) AS smallint) AS StdSecond,
     CAST(CAST(REVERSE(SUBSTRING(Data, 27, 2)) AS binary(2)) AS smallint) AS StdMillisec,
     -- When DST starts:
     CAST(CAST(REVERSE(SUBSTRING(Data, 29, 2)) AS binary(2)) AS smallint) AS DSTYear,       -- See above
     CAST(CAST(REVERSE(SUBSTRING(Data, 31, 2)) AS binary(2)) AS smallint) AS DSTMonth,
     CAST(CAST(REVERSE(SUBSTRING(Data, 33, 2)) AS binary(2)) AS smallint) AS DSTDayOfWeek,
     CAST(CAST(REVERSE(SUBSTRING(Data, 35, 2)) AS binary(2)) AS smallint) AS DSTWeek,
     CAST(CAST(REVERSE(SUBSTRING(Data, 37, 2)) AS binary(2)) AS smallint) AS DSTHour,
     CAST(CAST(REVERSE(SUBSTRING(Data, 39, 2)) AS binary(2)) AS smallint) AS DSTMinute,
     CAST(CAST(REVERSE(SUBSTRING(Data, 41, 2)) AS binary(2)) AS smallint) AS DSTSecond,
     CAST(CAST(REVERSE(SUBSTRING(Data, 43, 2)) AS binary(2)) AS smallint) AS DSTMillisec
    FROM #tztable;
    DROP TABLE #tztable
    

    A (복잡한) T-SQL 함수는 현재 DST 규칙 중 정확한 모든 날짜 오프셋을 결정하기 위해이 데이터를 사용할 수 있습니다.

  4. ==============================

    4.내가 정말 현지 시간으로 UTC로 변환 온라인으로 볼 수있는 솔루션의 만족되지 않은, 그래서 나는이 기능을 함께했다. 여기 내 SO 답변에서보세요

    내가 정말 현지 시간으로 UTC로 변환 온라인으로 볼 수있는 솔루션의 만족되지 않은, 그래서 나는이 기능을 함께했다. 여기 내 SO 답변에서보세요

    표준 날짜 범위 DST의 용도에 따라 활성화 계산 일광 절약 여부가 (; 첫째 일요일에 표준 시간으로 11 월 되돌리기에 오전 2시 년 3 월의 두 번째 일요일 시계가 앞으로 이동) 점에서 몇 가지 논리가있다

  5. from https://stackoverflow.com/questions/19732896/how-to-create-daylight-savings-time-start-and-end-function-in-sql-server by cc-by-sa and MIT license