TSQL : 현지 시간을 UTC로 변환하는 방법은 무엇입니까? (SQL Server 2008)


82

우리는 다른 시간대와 일광 절약 시간 설정의 글로벌 시간 데이터를 처리해야하는 응용 프로그램을 다루고 있습니다. 아이디어는 내부적으로 모든 것을 UTC 형식으로 저장하고 지역화 된 사용자 인터페이스에 대해서만 앞뒤로 변환하는 것입니다. SQL Server는 시간, 국가 및 시간대가 지정된 번역을 처리하기위한 메커니즘을 제공합니까?

이것은 일반적인 문제 일 것이므로 Google이 사용할 수있는 항목을 표시하지 않을 것이라는 점에 놀랐습니다.

포인터가 있습니까?


내 mssql-server가 mysql-server에 연결되어 있습니다. 쿼리에서 mysql CONVERT_TZ (time, srczone, dstzone)을 실행할 수 있는지 궁금합니다. :-) 이상한이 함수가 없습니다. 그것은 리눅스에 내장되어 있습니다.
Leif Neland

1
@BuschnicK 아래 내 대답을 참조하십시오. 사실 다른 사람이 쉽게 찾을 수 있도록 받아 들일 수 있다고 생각합니다.
Piotr Owsiak

짧은 대답 : SQL Server 2016 이전에는이 ​​작업을 수행하는 기본 제공 방법이 없으므로 이전 버전에서는 사용자 지정 코드가 필요합니다.
lehiester

중간 답변 : SQL Server 2016 이전의 모든 시간 오프셋 기능은 일광 절약 시간으로 인해 대부분의 표준 시간대에서 발생하는 변수 오프셋에 대한 지원없이 절대 오프셋으로 만 작동했습니다. 쿼리는 변환을 자동화하는 데 쓸모가없는 서버 로컬 시간의 현재 오프셋을 제외하고는 시간 오프셋에 액세스 할 수있는 방법이 없습니다.
lehiester

답변:


49

7 년이 지났고
실제로 필요한 작업을 정확히 수행하는 새로운 SQL Server 2016 기능이 있습니다.
AT TIME ZONE이라고하며 서머 타임 (DST) 변경을 고려하여 날짜를 지정된 시간대로 변환합니다.
자세한 정보 : https://msdn.microsoft.com/en-us/library/mt612795.aspx


19
더 이상이 작업을하지 않습니다. 해당 프로젝트가 아니라 SQL Server, 같은 회사가 아니라 같은 국가에서도 마찬가지입니다 .-) 그래서 도움이되지는 않지만이 질문을 찾는 사람들을 위해 찬성 할 것입니다. 지금.
BuschnicK

2
@BuschnicK 그래, 나는 생각한다. 그러나 나는 당신이 가진 것과 같은 문제에 대한 해결책을 찾기 위해 여기에 왔기 때문에 나는 진짜 해결책이 있다는 지금 aswer를 게시하기로 결정했다 : D
Piotr Owsiak

5
질문은 SQL Server 2008에 대한 것입니다.이 답변에 동의하면 질문을 업데이트하십시오. 들으
로버트

1
UTC로 변환하려면 'AT TIME ZONE'UTC '를 수행 할 수 있습니다.
Krzyserious

1
@Piotr Owsiak : 그렇습니다.하지만 입력 시간이 UTC라고 가정합니다. 현지 시간을 UTC로 변환하려는 경우 의미가 없습니다 ... 그래서 7 년이 지났지 만 여전히 제대로 처리 할 가치가 없다고 생각합니다. ..
Stefan Steiger

65

이것은 현재 SQL Server의 호스트와 동일한 UTC 오프셋을 가진 날짜에 대해 작동합니다. 일광 절약 시간 변경을 고려하지 않습니다. YOUR_DATE변환 할 현지 날짜로 바꿉니다 .

SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);


2
고마워, 이것은 좋은 생각이지만 정확히 하나의 시간대, 즉 로컬 시스템에서만 작동합니다. 하지만 임의의 시간대에서 작동하려면이 기능이 필요합니다 ...
BuschnicK 2010

51
이것은 일광 절약 시간을 고려하지 않습니다
Gabriel McAdams

10
아니! 차이는 정확한 날짜에 따라 다릅니다. 일광 절약에 따라 다릅니다.
usr

3
제 경우에는 1 개의 시간대가 필요했고 이것은 훌륭하게 작동했습니다! 감사.
M Thelen 2011

10
이것은 당신이 오늘의 달리기를 안다면 잘 작동합니다. 감사합니다
David Adlington

22

이러한 답변 중 몇 가지가 당신을 구장에 가져다 줄 것이지만, 일광 절약 시간 때문에 SqlServer 2005 및 이전 버전에 대해 임의의 날짜로하려는 작업을 수행 할 수 없습니다. 현재 로컬과 현재 UTC의 차이를 사용하면 현재 존재하는 오프셋을 얻을 수 있습니다. 문제의 날짜에 대해 오프셋이 무엇 이었을지 결정하는 방법을 찾지 못했습니다.

즉, SqlServer 2008이이 문제를 해결할 수있는 몇 가지 새로운 날짜 기능을 제공한다는 것을 알고 있지만 이전 버전을 사용하는 사람들은 제한 사항을 알고 있어야합니다.

우리의 접근 방식은 UTC를 유지하고 변환의 정확성을 더 많이 제어 할 수있는 클라이언트 측에서 변환을 수행하는 것입니다.


16

SQL Server 2016 이상 및 Azure SQL Database의 경우 기본 제공 AT TIME ZONE문을 사용합니다 .

이전 버전의 SQL Server의 경우 SQL Server 표준 시간대 지원 프로젝트를 사용하여 여기에 나열된대로 IANA 표준 표준 시간대간에 변환 할 수 있습니다 .

UTC to Local은 다음과 같습니다.

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')

로컬에서 UTC는 다음과 같습니다.

SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)

숫자 옵션은 현지 시간 값이 일광 절약 시간의 영향을받는 경우 동작을 제어하기위한 플래그입니다. 이것들은 프로젝트 문서에 자세히 설명되어 있습니다.


1
어떻게 ... Matt의이 프로젝트는 훌륭하고 CLR이 필요하지 않습니다. Matt는이 +100에 대해 많은 신용을받을 자격이 있습니다
buckley

14

SQL Server 2008에는 datetimeoffset. 이런 종류의 물건에 정말 유용합니다.

http://msdn.microsoft.com/en-us/library/bb630289.aspx

그런 다음 함수 SWITCHOFFSET를 사용하여 한 시간대에서 다른 시간대로 이동할 수 있지만 여전히 동일한 UTC 값을 유지합니다.

http://msdn.microsoft.com/en-us/library/bb677244.aspx

Rob


6
SWITCHOFFSET은 일광 절약을 고려하지 않으므로 일부 상황에서만 유용합니다.
robocat 2013 년

2
아니요. 그러나 질문은 요청 된 시간대로의 전환을 처리 할 수 ​​있는지에 관한 것이 었습니다.
Rob Farley 2013 년

"다른 시간대 및 일광 절약 시간 설정"질문에서. 우리도 현지 시대를위한 해결책을 찾고 있습니다. 귀하의 제안으로 일광 절약 문제가 해결되지 않습니까?
robocat 2013 년

클라이언트에서 시간대를 감지 한 다음 데이터베이스가 지정된 시간대로 시간을 반환해야 할 때 SWITCHOFFSET 함수는 매우 유용합니다.
Rob Farley

3
@RobFarley 클라이언트에서 시간대를 감지하고 SWITCHOFFSET을 사용하면 여전히 문제가 발생할 수 있습니다. 변환하는 날짜와 시간에 일광 절약 시간이 적용되었는지 여부를 알아야합니다. 표준 시간대를 감지하고 현재 오프셋을 UTC에 적용하는 것만으로도 한 시간 늦을 수 있습니다. 이는 모든 변환이 동일한 국가에있는 간단한 경우입니다. 모든 국가가 같은 날짜에 일광 절약 시간 제로 전환하는 것은 아닙니다. SWITCHOFFSET은 현지 시간을 저장하고 동일한 국가 내에서 원래 지역과 대상 지역의 차이를 알고 있다면 잘 작동합니다.
JamieSee

12

다음은 한 영역 DateTime을 다른 영역 으로 변환하는 코드입니다.DateTime

DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;

-- 'UTC' to 'India Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS IndiaStandardTime

-- 'India Standard Time' to 'UTC' DATETIME
SET @UTCDateTime = @ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT @ConvertedZoneDateTime AS IndiaStandardTime,@UTCDateTime AS UTCDATE

참고 : AT TIME ZONE SQL Server 2016+에서만 작동 하며 특정 시간대로 변환 할 때 자동으로 일광을 고려 한다는 장점이 있습니다.


2
여러 AT TIME ZONE호출 (구문?)을 함께 연결할 수 있다는 사실을 보여주는 것 외에 다른 이유가 없다면 저는 이것을 좋아 합니다! 단순히 우아합니다. 앞서 stackoverflow.com/a/44579178/112764 가 내 요구를 충족 했다고 말 했지만 이것이 더 좋습니다. 주요 명성.
NateJ

DECLARE @UTCDateTime DATETIME = GETUTCDATE(); DECLARE @ConvertedZoneDateTime DATETIME; -- 'UTC' to 'India Standard Time' to 'Eastern Standard Time' DATETIME SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time' AT TIME ZONE 'Eastern Standard Time' SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS EasternStandardTime 예, 여러 체인 수 AT TIME ZONE호출 만 에서 그리고 하려면 어떤 변환을위한 충분하고 대부분의 우리는 필요
KarthikeyanMlp

4

나는 지역 이벤트 (예 : 회의 / 파티 등, 박물관에서 12 pm-3pm)와 관련이없는 모든 날짜-시간 저장소에 DateTimeOffset을 사용하는 경향이 있습니다.

현재 DTO를 UTC로 가져 오려면 :

DECLARE @utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE @utcToday DATE = CONVERT(DATE, @utcNow);
DECLARE @utcTomorrow DATE = DATEADD(D, 1, @utcNow);
SELECT  @utcToday [today]
        ,@utcTomorrow [tomorrow]
        ,@utcNow [utcNow]

참고 : 유선으로 전송할 때 항상 UTC를 사용합니다. 클라이언트 측 JS는 로컬 UTC에 쉽게 접근 할 수 있습니다. 참조 : new Date().toJSON()...

다음 JS는 ISO8601 형식의 UTC / GMT 날짜를 로컬 datetime으로 구문 분석합니다.

if (typeof Date.fromISOString != 'function') {
  //method to handle conversion from an ISO-8601 style string to a Date object
  //  Date.fromISOString("2009-07-03T16:09:45Z")
  //    Fri Jul 03 2009 09:09:45 GMT-0700
  Date.fromISOString = function(input) {
    var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
    if (!isNaN(date)) return date;

    //early shorting of invalid input
    if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;

    var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;

    //normalize input
    var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');

    if (!iso8601Format.test(input))
      return null; //invalid format

    var d = input.match(iso8601Format);
    var offset = 0;

    date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));

    //use specified offset
    if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
    else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();

    date.setTime(date.getTime() + (offset * 60000));

    if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
      return null;

    return date;
  };
}

+1 나도 DateTimeOffset으로 전환했습니다. UTC + 로컬 변환과 관련된 여러 문제를 방지합니다. 그러나 유사한 이유로 인해 유선 (JSON을 통해) 오프셋이있는 값도 전송하는 것이 좋습니다.
user2864740

참고로, 나는 당신이 하는 일을 정확히 반대로 합니다. 로컬 이벤트에 연결된 DateTimes의 경우 DateTimeOffset을 저장합니다. 로컬 이벤트에 연결되지 않은 DateTime의 경우 DateTime을 UTC로 저장합니다. 전자에는 두 개의 관련 데이터 포인트 (현지 시간 및 현지 시간)가 있고, 후자는 하나 (언제)
Martijn

@Martijn 그러나 시간대는 위치를 제공하지 않으므로 어쨌든 별도로 저장해야합니다.
Tracker1 2014

@ tracker1 그것은 위치가 시간대를 알 수있는 방법을 가지고있을 때만 작동하며, 심지어 변환하는 것은 완전한 고통입니다.
Martijn 2014

3

예, 여기에 자세히 설명되어 있습니다 .
내가 사용한 접근법 (2008 년 이전)은 DB에 삽입하기 전에 .NET 비즈니스 로직에서 변환을 수행하는 것입니다.


1

GETUTCDATE () 함수를 사용하여 UTC 날짜 시간을 얻을 수 있습니다. 아마도 GETUTCDATE ()와 GETDATE () 사이의 차이를 선택하고이 차이를 사용하여 날짜를 UTC로 조정할 수 있습니다.

그러나 비즈니스 계층 (예 : .NET)에서 올바른 날짜 시간을 제어하는 ​​것이 훨씬 쉽다는 이전 메시지에 동의합니다.


12
아니! 차이는 정확한 날짜에 따라 다릅니다. 일광 절약에 따라 다릅니다.
usr

3
일광 절약을 고려하지 않습니다. 나는 이와 같은 솔루션을 얼마 동안 사용하고 있었고 큰 문제가 발생했습니다. 비교하려는 날짜가 DST에 있는지 확인해야합니다.
Jeff Davis

-1

샘플 사용법 :

SELECT
    Getdate=GETDATE()
    ,SysDateTimeOffset=SYSDATETIMEOFFSET()
    ,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0)
    ,GetutcDate=GETUTCDATE()
GO

보고:

Getdate SysDateTimeOffset   SWITCHOFFSET    GetutcDate
2013-12-06 15:54:55.373 2013-12-06 15:54:55.3765498 -08:00  2013-12-06 23:54:55.3765498 +00:00  2013-12-06 23:54:55.373
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.