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.