select 문에서 Datetime 열을 UTC에서 현지 시간으로 변환


208

몇 가지 SQL 선택 쿼리를 수행하고 UTC 결과 시간 열을 현지 시간으로 변환하여 쿼리 결과에 현지 시간으로 표시하려고합니다. 코드를 통해이 변환을 수행하지 않고 데이터베이스에 대해 수동 및 임의의 SQL 쿼리를 수행 할 때 참고하십시오.


이 질문이 당신의 상황과 비슷해 보입니까? stackoverflow.com/questions/3404646/…
— 타린 이스트

답변:


322

SQL Server 2008 이상에서 다음과 같이이를 수행 할 수 있습니다.

SELECT CONVERT(datetime, 
               SWITCHOFFSET(CONVERT(datetimeoffset, 
                                    MyTable.UtcColumn), 
                            DATENAME(TzOffset, SYSDATETIMEOFFSET()))) 
       AS ColumnInLocalTime
FROM MyTable

덜 장황한 작업을 수행 할 수도 있습니다.

SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
       AS ColumnInLocalTime
FROM MyTable

당신이 무엇을하든, 날짜를 빼기 위해 사용 하지 마십시오- . 작업이 원자 적이 지 않기 때문에 때때로 시스템 날짜 시간과 다른 날짜에 확인되는 로컬 날짜 시간 사이의 경쟁 조건으로 인해 결정적이지 않은 결과를 얻을 수 있습니다 (즉, 원자가 아닌) .

이 답변은 DST를 고려하지 않습니다. DST 조정을 포함하려면 다음 SO 질문도 참조하십시오.

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


38
일광 절약을 위해이 계정을 만드는 방법이 있습니까?
— Steve

15
여기에 시간대 이름이 표시되지 않으므로 이것이 올바르지 않습니다. 산술을 통해 현지 시간으로 변환 할 수 있다고 가정하는 것은 정말 나쁜 생각입니다.
— JonnyRaa

7
@MichaelGoldshteyn 표준 시간대 오프셋이 있으면 여전히 어떤 표준 시간대가 있는지 알 수 없습니다. 표준 시간대는 사회적이며 정부가 다른 시점에서 변경할 수 있습니다. 시간대에 대한 오프셋은 시간 / 역사에 따라 다를 수 있습니다 (서머 타임은 일반적인 것). UTC에서 현재 오프셋으로 시간을 오프셋합니다. 추가 포인트는 클라이언트가 아닌 서버의 시간대를 제공하므로 다른 국가에서 호스팅하는 경우 추가 문제가 발생할 수 있다는 것입니다.
— JonnyRaa

4
@Niloofar 간단한 대답은하지 말아야한다는 것입니다. 날짜 / 시간은 항상 UTC로 저장해야합니다 (웹 서버, 응용 프로그램 서버 및 클라이언트 시계가 아닌 데이터베이스 서버의 시계를 기준으로하는 것이 바람직 함). 해당 날짜 시간을 표시하는 것은 UI 계층의 함수이며 날짜 시간을 원하는 형식 (필요한 경우 시간대 포함)으로 변환해야합니다.
— Robert McKee 2016 년

11
sql azure를 사용하는 사람에게는 날짜 / 시간 함수가 모두 UTC를 반환하므로 GETDATE ()를 GETUTCDATE ()와 비교하면 아무런 작업도 수행하지 않으며 결과는 처음과 동일하므로 작동하지 않습니다.
— Brian Surowiec

59

이 예제 중 하나는 UTC로 저장된 날짜 시간을 지정된 시간대의 날짜 시간으로 가져 오는 데 도움이되지 않았습니다 (Azure SQL 데이터베이스는 UTC로 실행되므로 서버의 시간대는 아님). 이것이 내가 처리 한 방법입니다. 우아하지는 않지만 간단하며 다른 테이블을 유지하지 않고도 올바른 답변을 제공합니다.

select CONVERT(datetime, SWITCHOFFSET(dateTimeField, DATEPART(TZOFFSET, 
dateTimeField AT TIME ZONE 'Eastern Standard Time')))

4
2016에서만 작동하며 시스템 레지스트리를 사용합니다. 그러나 Azure에는 훌륭한 솔루션입니다.
— Dan Cundy

2
UTC에 저장 푸른 시간에 대한이 하나 개의 작품들 덕분에
— 널

3
시간대에 사용할 수있는 문자열 목록은 다음과 같습니다. stackoverflow.com/a/7908482/631277
— Matt Kemp

1
SQL 2016과 사용하는 경우 AT TIME ZONE구문을 고려 stackoverflow.com/a/44941536/112764을 - 당신이 할 수있는 체인 여러 변환을 함께 단순히 여러 연결하여 at time zone <blah>들.
— NateJ

3
이도 조금 이상한이지만,이 힘 작업과 같은 몇 가지 아주 기본적인 테스트 외모도 - dateTimeField AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'- 단지 체인 AT TIME ZONE문을. (@NateJ는 내가 지금 본 위에서 언급 했음)
— David Mohundro

22

현지 날짜 시간을 말하고 Eastern Standard TimeUTC에서 해당 날짜 로 변환하려면 Azure SQL 및 SQL Server 2016 이상에서 다음을 수행 할 수 있습니다.

SELECT YourUtcColumn AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time' AS
       LocalTime
FROM   YourTable

시간대 이름의 전체 목록은 다음에서 찾을 수 있습니다.

SELECT * FROM sys.time_zone_info 

그렇습니다. 시간대는 이름이 잘못 지정되었지만 Eastern Standard Time일광 절약 시간제를 고려합니다.


2
표준 시간대 및 오프셋은 SQL Server에서도 찾을 수 있습니다. SELECT * FROM sys.time_zone_info
— rayzinnz

21

서버 위치 이외의 변환이 필요한 경우 표준 오프셋을 전달하고 미국 일광 절약 시간제를 설명 할 수있는 기능이 있습니다.

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

    declare 
        @DST datetime,
        @SSM datetime, -- Second Sunday in March
        @FSN datetime  -- First Sunday in November

    -- get DST Range
    set @SSM = datename(year,@UTC) + '0314' 
    set @SSM = dateadd(hour,2,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
    set @FSN = datename(year,@UTC) + '1107'
    set @FSN = dateadd(second,-1,dateadd(hour,2,dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

    -- add an hour to @StandardOffset if @UTC is in DST range
    if @UTC between @SSM and @FSN
        set @StandardOffset = @StandardOffset + 1

    -- convert to DST
    set @DST = dateadd(hour,@StandardOffset,@UTC)

    -- return converted datetime
    return @DST

END

GO

2
Ron Smith 나는 이것이 오래된 게시물이라는 것을 알고 있지만 하드 코딩 된 '0314'와 '1107'이 DST 범위를 얻는 데 무엇을 나타내는 지 궁금했습니다. DTS로 인해 변경되는 하드 코딩 된 일로 보입니다. 3 월 둘째 주 일요일과 11 월 첫째 주 일요일에 해당하는 날짜에 따라 날짜가 변경되므로 계산 날짜 여야 할 때이 코드를 왜 하드 코딩해야합니까? 하드 코딩 된 시절에는이 코드가 근본적으로 결함이 있습니다.
— Mike

2
좋은 질문 :) 3 월 둘째 주 일요일과 11 월 첫째 주 일요일이 일어날 수있는 최대 날짜입니다. 다음 줄은 변수를 실제 날짜로 설정합니다.
— Ron Smith

8

새로운 SQL Server 2016 기회 사용 :

CREATE FUNCTION ToLocalTime(@dtUtc datetime, @timezoneId nvarchar(256))
RETURNS datetime
AS BEGIN

return @dtUtc AT TIME ZONE 'UTC' AT TIME ZONE @timezoneId

/* -- second way, faster

return SWITCHOFFSET(@dtUtc , DATENAME(tz, @dtUtc AT TIME ZONE @timezoneId))

*/

/* -- third way

declare @dtLocal datetimeoffset
set @dtLocal = @dtUtc AT TIME ZONE @timezoneId
return dateadd(minute, DATEPART (TZoffset, @dtLocal), @dtUtc)

*/

END
GO

그러나 clr 절차는 5 배 빠르게 작동합니다 .'- (

한 TimeZone의 오프셋이 겨울 또는 여름 시간으로 변경 될 수 있다는 점에 유의하십시오. 예를 들어

select cast('2017-02-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'
select cast('2017-08-08 09:00:00.000' as datetime) AT TIME ZONE 'Eastern Standard Time'

결과 :

2017-02-08 09:00:00.000 -05:00
2017-08-08 09:00:00.000 -04:00

상수 오프셋을 추가 할 수는 없습니다.


5

데이터베이스에서 CLR을 사용하는 것이 SQL 서버의 시간대를 사용하는 것뿐만 아니라 옵션 인 경우 .Net으로 매우 쉽게 작성할 수 있습니다.

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime fn_GetLocalFromUTC(SqlDateTime UTC)
    {
        if (UTC.IsNull)
            return UTC;

        return new SqlDateTime(UTC.Value.ToLocalTime());
    }
}

UTC 날짜 시간 값이 들어가고 서버와 관련된 로컬 날짜 시간 값이 나옵니다. 널값은 널을 리턴합니다.


5

올바른 일반적인 방법으로이를 수행하는 간단한 방법은 없습니다.

우선 오프셋은 해당 날짜, 시간대 및 DST에 따라 달라집니다. GetDate()-GetUTCDate오늘은 서버의 TZ에서만 오프셋을 제공하지만 관련이 없습니다.

나는 두 가지 작동 솔루션 만 보았고 많이 검색했습니다.

1) 시간대 및 TZ 당 DST 규칙과 같은 몇 가지 기본 데이터 테이블이있는 사용자 정의 SQL 함수. 일하지만 우아하지는 않습니다. 코드를 소유하지 않아 게시 할 수 없습니다.

편집 : 다음은이 방법의 예입니다 https://gist.github.com/drumsta/16b79cee6bc195cd89c8

2) .net 어셈블리를 db에 추가하면 .Net 이이를 쉽게 수행 할 수 있습니다. 이것은 잘 작동하지만 단점은 서버 수준에서 여러 매개 변수를 구성해야하며 데이터베이스를 복원하는 경우 구성이 쉽게 손상된다는 것입니다. 이 방법을 사용하지만 코드를 소유하지 않아 게시 할 수 없습니다.


4

이것들 중 어느 것도 나를 위해 일하지는 않았지만 아래에서는 100 % 효과가있었습니다. 이것이 내가 다른 것처럼 그것을 변환하려고하는 사람들을 도울 수 있기를 바랍니다.

CREATE FUNCTION [dbo].[fn_UTC_to_EST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = DATEADD(dd,7 + (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 2,0))+'02:00:00' 
set @FSN = DATEADD(dd, (6-(DATEDIFF(dd,0,DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0))%7)),DATEADD(mm,(YEAR(GETDATE())-1900) * 12 + 10,0)) +'02:00:00'

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

1
이것이 정답입니다. 내가 바꿀 유일한 것은 이름이 EST 시간임을 의미하므로 실제로는 현지 시간으로 표준 오프셋이 매개 변수로 전달되는 경우입니다.
— Greg Gum

동의, 최선의 대답 ...하지만 오프셋을 매개 변수로 전달하는 대신 함수 본문 내에 이것을 추가했습니다.declare @StandardOffset int = datediff (hh, GETUTCDATE(), GETDATE())
— Tom Warfield

이전 제안에 대한 후속 조치-@StandardOffset을 계산하면 DST 수정을 수행 할 필요가 없습니다.
— Tom Warfield 2018 년

3

다음은 일광 절약 시간제, UTC 오프셋을 설명하고 특정 연도에 잠겨 있지 않은 버전입니다.

---------------------------------------------------------------------------------------------------
--Name:     udfToLocalTime.sql
--Purpose:  To convert UTC to local US time accounting for DST
--Author:   Patrick Slesicki
--Date:     3/25/2014
--Notes:    Works on SQL Server 2008R2 and later, maybe SQL Server 2008 as well.
--          Good only for US States observing the Energy Policy Act of 2005.
--          Function doesn't apply for years prior to 2007.
--          Function assumes that the 1st day of the week is Sunday.
--Tests:        
--          SELECT dbo.udfToLocalTime('2014-03-09 9:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-03-09 10:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 8:00', DEFAULT)
--          SELECT dbo.udfToLocalTime('2014-11-02 9:00', DEFAULT)
---------------------------------------------------------------------------------------------------
ALTER FUNCTION udfToLocalTime
    (
    @UtcDateTime    AS DATETIME
    ,@UtcOffset     AS INT = -8 --PST
    )
RETURNS DATETIME
AS 
BEGIN
    DECLARE 
        @PstDateTime    AS DATETIME
        ,@Year          AS CHAR(4)
        ,@DstStart      AS DATETIME
        ,@DstEnd        AS DATETIME
        ,@Mar1          AS DATETIME
        ,@Nov1          AS DATETIME
        ,@MarTime       AS TIME
        ,@NovTime       AS TIME
        ,@Mar1Day       AS INT
        ,@Nov1Day       AS INT
        ,@MarDiff       AS INT
        ,@NovDiff       AS INT

    SELECT
        @Year       = YEAR(@UtcDateTime)
        ,@MarTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset, '1900-01-01 02:00'))
        ,@NovTime   = CONVERT(TIME, DATEADD(HOUR, -@UtcOffset - 1, '1900-01-01 02:00'))
        ,@Mar1      = CONVERT(CHAR(16), @Year + '-03-01 ' + CONVERT(CHAR(5), @MarTime), 126)
        ,@Nov1      = CONVERT(CHAR(16), @Year + '-11-01 ' + CONVERT(CHAR(5), @NovTime), 126)
        ,@Mar1Day   = DATEPART(WEEKDAY, @Mar1)
        ,@Nov1Day   = DATEPART(WEEKDAY, @Nov1)

    --Get number of days between Mar 1 and DST start date
    IF @Mar1Day = 1 SET @MarDiff = 7
    ELSE SET @MarDiff = 15 - @Mar1Day

    --Get number of days between Nov 1 and DST end date
    IF @Nov1Day = 1 SET @NovDiff = 0
    ELSE SET @NovDiff = 8 - @Nov1Day

    --Get DST start and end dates
    SELECT 
        @DstStart   = DATEADD(DAY, @MarDiff, @Mar1)
        ,@DstEnd    = DATEADD(DAY, @NovDiff, @Nov1)

    --Change UTC offset if @UtcDateTime is in DST Range
    IF @UtcDateTime >= @DstStart AND @UtcDateTime < @DstEnd SET @UtcOffset = @UtcOffset + 1

    --Get Conversion
    SET @PstDateTime = DATEADD(HOUR, @UtcOffset, @UtcDateTime)
    RETURN @PstDateTime
END
GO

3

많은 데이터가있을 때 일회용 기능이 너무 느리다는 것을 알았습니다. 그래서 시간 차이를 계산할 수있는 테이블 함수에 조인하여 수행했습니다. 기본적으로 시간 오프셋이있는 날짜 / 시간 세그먼트입니다. 1 년은 4 행입니다. 그래서 테이블 함수

dbo.fn_getTimeZoneOffsets('3/1/2007 7:00am', '11/5/2007 9:00am', 'EPT')

이 테이블을 반환합니다 :

startTime          endTime   offset  isHr2
3/1/07 7:00     3/11/07 6:59    -5    0
3/11/07 7:00    11/4/07 6:59    -4    0
11/4/07 7:00    11/4/07 7:59    -5    1
11/4/07 8:00    11/5/07 9:00    -5    0

일광 절약 시간을 고려합니다. 사용 방법에 대한 샘플은 다음과 같으며 전체 블로그 게시물은 여기에 있습니다 .

select mt.startTime as startUTC, 
    dateadd(hh, tzStart.offset, mt.startTime) as startLocal, 
    tzStart.isHr2
from MyTable mt 
inner join dbo.fn_getTimeZoneOffsets(@startViewUTC, @endViewUTC, @timeZone)  tzStart
on mt.startTime between tzStart.startTime and tzStart.endTime

DST를 올바른 방식으로 고려하지 않는 것 같습니다. 미국 만 존재하고 DST 규칙이 변경되지 않는지 확실하지 않습니다.
— vikjon0

@ vikjon0 네, 제가이 프로젝트를 위해 만든 프로젝트는 미국 시간대 만있었습니다.
— JBrooks

2
 declare @mydate2 datetime
 set @mydate2=Getdate()
 select @mydate2 as mydate,
 dateadd(minute, datediff(minute,getdate(),@mydate2),getutcdate())

1

Ron의 답변에 오류가 있습니다. UTC에 해당하는 현지 시간으로 오전 2시를 사용합니다. Ron의 답변에 대해 언급 할 평판이 충분하지 않으므로 수정 된 버전이 아래에 나타납니다.

-- =============================================
-- Author:      Ron Smith
-- Create date: 2013-10-23
-- Description: Converts UTC to DST
--              based on passed Standard offset
-- =============================================
CREATE FUNCTION [dbo].[fn_UTC_to_DST]
(
    @UTC datetime,
    @StandardOffset int
)
RETURNS datetime
AS
BEGIN

declare 
    @DST datetime,
    @SSM datetime, -- Second Sunday in March
    @FSN datetime  -- First Sunday in November
-- get DST Range
set @SSM = datename(year,@UTC) + '0314' 
set @SSM = dateadd(hour,2 - @StandardOffset,dateadd(day,datepart(dw,@SSM)*-1+1,@SSM))
set @FSN = datename(year,@UTC) + '1107'
set @FSN = dateadd(second,-1,dateadd(hour,2 - (@StandardOffset + 1),dateadd(day,datepart(dw,@FSN)*-1+1,@FSN)))

-- add an hour to @StandardOffset if @UTC is in DST range
if @UTC between @SSM and @FSN
    set @StandardOffset = @StandardOffset + 1

-- convert to DST
set @DST = dateadd(hour,@StandardOffset,@UTC)

-- return converted datetime
return @DST

END

버그가 아닌 기능입니다.) 대부분의 미국은 오전 2:00에 일광 절약 시간제를 시작합니다. en.wikipedia.org/wiki/Daylight_saving_time
— Ron Smith

@RonSmith 그렇습니다. 현지 시간으로 오전 2시입니다. UTC로 변환하여 주어진 UTC 시간이 DST 범위에 있는지 확인해야합니다.
— jlspublic

1

UNIX 타임 스탬프는 특정 날짜와 Unix Epoch 사이의 시간 (초)입니다.

SELECT DATEDIFF (SECOND, {d '1970-01-01'}, GETDATE ()) // SQL 서버에서 UNIX 타임 스탬프를 반환합니다

SQL Server에서 Country Offset 함수를 Unix Time Stamp로 사용하여 현지 날짜 시간을 Unix UTC로 변환하는 함수를 만들 수 있습니다.


1

간단 해. Azure SQL Server에 대해 이것을 시도하십시오.

SELECT YourDateTimeColumn AT TIME ZONE 'Eastern Standard Time' FROM YourTable

로컬 SQL Server의 경우 :

SELECT CONVERT(datetime2, SWITCHOFFSET(CONVERT(datetimeoffset, gETDATE()), DATENAME(TzOffset, gETDATE() AT TIME ZONE 'Eastern Standard Time'))) FROM YourTable

1
일광 절약 시간제 (표준 시간대에 "동부 표준시"라고 표시되어 있기 때문에)에 어떤 일이 발생합니까?
— Mark

1

Azure SQL 및 @@Version> = SQL Server 2016 사용자의 경우 아래는를 사용하는 간단한 함수 AT TIME ZONE입니다.

CREATE FUNCTION [dbo].[Global_Convert_UTCTimeTo_LocalTime]
(
   @LocalTimeZone        VARCHAR(50),
   @UTCDateTime          DATETIME
)
RETURNS DATETIME
AS
BEGIN
   DECLARE @ConvertedDateTime DATETIME;

   SELECT @ConvertedDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE @LocalTimeZone
   RETURN @ConvertedDateTime

END
GO

@LocalTimeZone사용할 수 있는 값 유형에 대해서는 이 링크로 이동하거나KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones


0

경고로-다음을 사용하려는 경우 (분 대신 밀리 초 참고) :

    SELECT DATEADD(ms, DATEDIFF(ms, GETUTCDATE(), GETDATE()), MyTable.UtcColumn) 
    AS ColumnInLocalTime
    FROM MyTable

DATEDIFF 부분이 항상 같은 숫자를 반환하지는 않습니다. 따라서 DateTimes를 밀리 초로 비교하는 데 사용하지 마십시오.


0

이 기능은 별도의 테이블이나 루프를 사용하는 다른 솔루션보다 빠릅니다. 기본적인 사례 진술 일뿐입니다. 4 월에서 10 월 사이의 모든 달에 -4- 시간 오프셋 (동부 표준시)이 있기 때문에 프린지 일에 몇 가지 사례를 추가하기 만하면됩니다. 그렇지 않으면 오프셋은 -5 시간입니다.

UTC에서 동부 시간으로의 변환에만 해당되지만 필요에 따라 추가 시간대 기능을 추가 할 수 있습니다.

USE [YourDatabaseName]
GO

/****** Object:  UserDefinedFunction [dbo].[ConvertUTCtoEastern]    Script Date: 11/2/2016 5:21:52 PM ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE FUNCTION [dbo].[ConvertUTCtoEastern]
(
@dtStartDate DATETIME
)
RETURNS DATETIME
AS
BEGIN
DECLARE @Working DATETIME
DECLARE @Returned DATETIME

SET @Working = @dtStartDate
SET @Working = 
case when month(@Working) between 4 and 10 then dateadd(HH,-4,@Working) 
     when @Working between '2017-03-12' and '2017-11-05' then dateadd(HH,-4,@Working) 
     when @Working between '2016-03-13' and '2016-11-06' then dateadd(HH,-4,@Working) 
     when @Working between '2015-03-08' and '2015-11-01' then dateadd(HH,-4,@Working) 
     when @Working between '2014-03-09' and '2014-11-02' then dateadd(HH,-4,@Working) 
     when @Working between '2013-03-10' and '2013-11-03' then dateadd(HH,-4,@Working) 
     when @Working between '2012-03-11' and '2012-11-04' then dateadd(HH,-4,@Working) 
else dateadd(HH,-5,@Working) end

SET @Returned = @Working

RETURN @Returned

END


GO

0

DST로 서버 시간을 확보 할 수 있어야합니다.

declare @dt datetime
set @dt = getutcdate() -- GMT equivalent

sysdatetimeoffset은 DST를 고려합니다

select [InputTime] = @dt
       , [LocalTime2] = dateadd(mi, datediff(mi, sysdatetimeoffset(),getdate()), @dt) 

0

첫 번째 기능 : 이탈리아어 시간대 (+1, +2)로 구성, 날짜 전환 : 3 월과 10 월 마지막 일요일, 현재 시간대와 날짜 시간의 차이를 매개 변수로 반환합니다.

Returns:
current timezone < parameter timezone ==> +1
current timezone > parameter timezone ==> -1
else 0

코드는 다음과 같습니다

CREATE FUNCTION [dbo].[UF_ADJUST_OFFSET]
(
    @dt_utc datetime2(7)
)
RETURNS INT
AS
BEGIN


declare @month int,
        @year int,
        @current_offset int,
        @offset_since int,
        @offset int,
        @yearmonth varchar(8),
        @changeoffsetdate datetime2(7)

declare @lastweek table(giorno datetime2(7))

select @current_offset = DATEDIFF(hh, GETUTCDATE(), GETDATE())

select @month = datepart(month, @dt_utc)

if @month < 3 or @month > 10 Begin Set @offset_since = 1 Goto JMP End

if @month > 3 and @month < 10 Begin Set @offset_since = 2 Goto JMP End

--If i'm here is march or october
select @year = datepart(yyyy, @dt_utc)

if @month = 3
Begin

Set @yearmonth = cast(@year as varchar) + '-03-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of march
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc < @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

if @month = 10
Begin

Set @yearmonth = cast(@year as varchar) + '-10-'

Insert Into @lastweek Values(@yearmonth + '31 03:00:00.000000'),(@yearmonth + '30 03:00:00.000000'),(@yearmonth + '29 03:00:00.000000'),(@yearmonth + '28 03:00:00.000000'),
                         (@yearmonth + '27 03:00:00.000000'),(@yearmonth + '26 03:00:00.000000'),(@yearmonth + '25 03:00:00.000000')

--Last week of october
Select @changeoffsetdate = giorno From @lastweek Where  datepart(weekday, giorno) = 1

    if @dt_utc > @changeoffsetdate 
    Begin 
        Set @offset_since = 1 
    End Else Begin
        Set @offset_since = 2
    End
End

JMP:

if @current_offset < @offset_since Begin
    Set @offset = 1
End Else if @current_offset > @offset_since Set @offset = -1 Else Set @offset = 0

Return @offset

END

그런 다음 날짜를 변환하는 함수

CREATE FUNCTION [dbo].[UF_CONVERT]
(
    @dt_utc datetime2(7)
)
RETURNS datetime
AS
BEGIN

    declare @offset int


    Select @offset = dbo.UF_ADJUST_OFFSET(@dt_utc)

    if @dt_utc >= '9999-12-31 22:59:59.9999999'
        set @dt_utc = '9999-12-31 23:59:59.9999999'
    Else
        set @dt_utc = (SELECT DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), @dt_utc) )

    if @offset <> 0
        Set @dt_utc = dateadd(hh, @offset, @dt_utc)

    RETURN @dt_utc

END

0

-utc에서 인도 표준시를 얻으십시오

CREATE FUNCTION dbo.getISTTime
(
@UTCDate datetime
)
RETURNS datetime
AS
BEGIN

    RETURN dateadd(minute,330,@UTCDate)

END
GO

0

기능없이 수행 할 수 있습니다. 아래 코드는 일광 절약 시간 제로 UTC 시간을 산지 시간 계산으로 변환합니다. 모든 -6 및 -7 숫자를 시간대에 맞게 조정하십시오 (예 : EST의 경우 각각 -4 및 -5로 조정)

--Adjust a UTC value, in the example the UTC field is identified as UTC.Field, to account for daylight savings time when converting out of UTC to Mountain time.
CASE
    --When it's between March and November, it is summer time which is -6 from UTC
    WHEN MONTH ( UTC.Field ) > 3 AND MONTH ( UTC.Field ) < 11 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    --When its March and the day is greater than the 14, you know it's summer (-6)
    WHEN MONTH ( UTC.Field ) = 3
        AND DATEPART ( DAY , UTC.Field ) >= 14 
        THEN
            --However, if UTC is before 9am on that Sunday, then it's before 2am Mountain which means it's still Winter daylight time.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 2am mountain time so it's winter, -7 hours for Winter daylight time
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise -6 because it'll be after 2am making it Summer daylight time
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    WHEN MONTH ( UTC.Field ) = 3
        AND ( DATEPART ( WEEKDAY , UTC.Field ) + 7 ) <= DATEPART ( day , UTC.Field ) 
        THEN 
            --According to the date, it's moved onto Summer daylight, but we need to account for the hours leading up to 2am if it's Sunday
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '9:00'
                    --Before 9am UTC is before 2am Mountain so it's winter Daylight, -7 hours
                    THEN DATEADD ( HOUR , -7 , UTC.Field )
                --Otherwise, it's summer daylight, -6 hours
                ELSE DATEADD ( HOUR , -6 , UTC.Field )
            END
    --When it's November and the weekday is greater than the calendar date, it's still Summer so -6 from the time
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) > DATEPART ( DAY , UTC.Field ) 
        THEN DATEADD ( HOUR , -6 , UTC.Field )
    WHEN MONTH ( UTC.Field ) = 11
        AND DATEPART ( WEEKDAY , UTC.Field ) <= DATEPART ( DAY , UTC.Field ) 
            --If the weekday is less than or equal to the calendar day it's Winter daylight but we need to account for the hours leading up to 2am.
            CASE 
                WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1 
                    AND UTC.Field < '8:00'
                    --If it's before 8am UTC and it's Sunday in the logic outlined, then it's still Summer daylight, -6 hours
                    THEN DATEADD ( HOUR , -6 , UTC.Field )
                --Otherwise, adjust for Winter daylight at -7
                ELSE DATEADD ( HOUR , -7 , UTC.Field )
            END
    --If the date doesn't fall into any of the above logic, it's Winter daylight, -7
    ELSE
        DATEADD ( HOUR , -7 , UTC.Field )
END

0

문자열을 다시 포맷하고 올바른 시간으로 변환해야합니다. 이 경우 Zulu 시간이 필요했습니다.

Declare @Date datetime;
Declare @DateString varchar(50);
set @Date = GETDATE(); 
declare @ZuluTime datetime;

Declare @DateFrom varchar (50);
Declare @DateTo varchar (50);
set @ZuluTime = DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), @Date);
set @DateString =  FORMAT(@ZuluTime, 'yyyy-MM-ddThh:mm:ssZ', 'en-US' )  
select @DateString;

0

오라클을위한 최상의 방법 :

하드 코딩 된 날짜 시간 :

SELECT TO_CHAR(CAST((FROM_TZ(CAST(TO_DATE('2018-10-27 21:00', 'YYYY-MM-DD HH24:MI') AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM DUAL

Result: 2018-10-28 00:00

열과 테이블 이름으로 :

SELECT TO_CHAR(CAST((FROM_TZ(CAST(COLUMN_NAME AS TIMESTAMP), 'UTC') AT  TIME ZONE 'EET') AS DATE), 'YYYY-MM-DD HH24:MI') UTC_TO_EET FROM TABLE_NAME

0

이와 같은 코드를 사용하여 변환 할 수있는 UTC to Local 및 Local to UTC 시간을 수행하는 코드가 있습니다.

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @utcDT DATETIME=GetUTCDate()
DECLARE @userDT DATETIME=[dbo].[funcUTCtoLocal](@utcDT, @usersTimezone)

과

DECLARE @usersTimezone VARCHAR(32)='Europe/London'
DECLARE @userDT DATETIME=GetDate()
DECLARE @utcDT DATETIME=[dbo].[funcLocaltoUTC](@userDT, @usersTimezone)

이 기능은 NodaTime에서 제공 한대로 IANA / TZDB의 시간대 전체 또는 일부를 지원할 수 있습니다. https://nodatime.org/TimeZones 에서 전체 목록을 참조하십시오.

내 유스 케이스는 '현재'창만 필요하므로 지금부터 약 +/- 5 년 범위 내에서 시간을 변환 할 수 있습니다. 이것은 주어진 날짜 범위에서 각 시간대 간격에 대한 코드를 생성하는 방식으로 인해 매우 넓은 시간이 필요한 경우 내가 사용한 방법이 적합하지 않을 수 있음을 의미합니다.

이 프로젝트는 GitHub에 있습니다 : https://github.com/elliveny/SQLServerTimeConversion

이 예제에 따라 SQL 함수 코드를 생성합니다.


0

데이터베이스에 UTC 날짜로 데이터를 저장하면 간단한 작업을 수행 할 수 있습니다.

select 
 [MyUtcDate] + getdate() - getutcdate()
from [dbo].[mytable]

TIME ZONE 'your time zone name'데이터베이스가 클라이언트 설치와 같은 다른 시간대로 이동하면 하드 코딩 된 시간대가 물릴 수 있습니다. 이것은 서버 시점에서 항상 로컬이며 AT로 혼란스럽지 않습니다 .


0

postgres에서 이것은 매우 잘 작동합니다 .. 시간이 저장된 시간을 'utc'로 지정한 다음 특정 시간대로 변환하도록 요청하십시오 (이 경우 'Brazil / East')

quiz_step_progresses.created_at  at time zone 'utc' at time zone 'Brazil/East'

다음을 선택하여 시간대의 전체 목록을 얻으십시오.

select * from pg_timezone_names;

자세한 내용은 여기를 참조하십시오.

https://popsql.com/learn-sql/postgresql/how-to-convert-utc-to-local-time-zone-in-postgresql


-1

여기에 dst를 고려한 더 간단한 것이 있습니다.

CREATE FUNCTION [dbo].[UtcToLocal] 
(
    @p_utcDatetime DATETIME 
)
RETURNS DATETIME
AS
BEGIN
    RETURN DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), @p_utcDatetime), GETDATE())
END

6
이것은 실제로 DST를 고려하지 않습니다. 시도해보십시오 : SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, GETUTCDATE(), '20150101'), GETDATE()). 현재 CEST (UTC + 2)에 있지만 새해에는 DST가 적용되지 않으므로 올바른 답변은 2015 년 1 월 1 일 01:00입니다. 답변은 수락 된 답변과 마찬가지로 2015 년 1 월 1 일 02:00을 반환합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.