TSQL:現地時間をUTCに変換する方法は?(SQL Server 2008)


82

さまざまなタイムゾーンと夏時間の設定からのグローバル時間データを処理する必要があるアプリケーションを扱っています。アイデアは、すべてをUTC形式で内部的に保存し、ローカライズされたユーザーインターフェイスに対してのみ前後に変換することです。SQL Serverは、時間、国、およびタイムゾーンを指定して翻訳を処理するためのメカニズムを提供しますか?

これは一般的な問題であるに違いないので、グーグルが使用可能なものを何も表示しないことに驚いています。

ポインタはありますか?


mssql-serverをmysql-serverにリンクしています。クエリでmysqlCONVERT_TZ(time、srczone、dstzone)を実行できるかどうか疑問に思います:-)奇妙なことにこの関数がありません。Linuxに組み込まれています。
Leif Neland 2015

1
@BuschnicK以下の私の答えを参照してください。実は、他の人が見つけやすいように、受け入れてもいいと思います。
Piotr Owsiak 2016年

簡単な答え:SQL Server 2016より前にこれを行う組み込みの方法はないため、以前のバージョンではカスタムコードが必要になります。
lehiester

中程度の答え:SQL Server 2016より前のすべてのタイムオフセット機能は、絶対オフセットでのみ機能し、夏時間のためにほとんどのタイムゾーンで発生する可変オフセットはサポートされていません。クエリには、サーバーの現地時間の現在のオフセットであるものを除いて、時間オフセットにアクセスする方法がありません。これは、変換を自動化しようとしても役に立ちません。
lehiester

回答:


49

7年が経過しました...
実際には、必要なことを正確に実行するこの新しいSQL Server2016機能があります。
これはATTIME ZONEと呼ばれ、DST(夏時間)の変更を考慮して日付を指定されたタイムゾーンに変換します。
詳細はこちら:https//msdn.microsoft.com/en-us/library/mt612795.aspx


19
もはやこれに取り組んでいません-そのプロジェクトでも、SQL Serverでも、同じ会社でも、同じ国でもありません;-)ですから、それは私には役立ちませんが、この質問を見つけた人々のために賛成します今。
BuschnicK 2016

2
@BuschnicKええ、わかりましたが、私はあなたが抱えていたのと同じ問題の解決策を探してここに来たので、本当の解決策があるので、私はaswerを投稿することにしました:D
Piotr Owsiak 2017

5
質問はSQLServer 2008に関するものです。この回答を受け入れる場合は、質問を更新してください。Thx
ロバート

1
UTCに変換するには、「AT TIMEZONE」「UTC」を実行できます。
Krzyserious 2018年

1
@Piotr Owsiak:そうですが、入力時刻がUTCであると想定しています。これは、現地時間からUTCに変換する場合は無意味です... 7年が経過しましたが、これを適切に処理する価値はないと彼らは考えています。 ..
StefanSteiger19年

65

これは、現在SQLServerのホストと同じUTCオフセットを持つ日付に対して機能します。夏時間の変更は考慮されていません。YOUR_DATE変換するローカル日付に置き換えます。

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


2
おかげで、これは良い考えですが、ローカルマシンの1つのタイムゾーンでのみ機能します。ただし、任意のタイムゾーンで機能する必要があります...
BuschnicK 2010年

51
これは夏時間を考慮していません
Gabriel McAdams 2011

10
番号!違いは正確な日付によって異なります。それは夏時間に依存します。
usr

3
私の場合、1つのタイムゾーンが必要でしたが、これはうまくいきました。ありがとう。
M Thelen 2011

10
これは、今日のランニングが歴史的ではないことを知っている場合にうまく機能します。ありがとう
David Adlington 2012年

22

これらの回答のいくつかはあなたを球場に連れて行くでしょうが、夏時間のためにSqlServer2005以前の任意の日付でやろうとしていることを行うことはできません。現在のローカルUTCと現在のUTCの差を使用すると、現在のオフセットが得られます。問題の日付のオフセットがどうなるかを判断する方法が見つかりませんでした。

そうは言っても、SqlServer 2008がその問題に対処する可能性のあるいくつかの新しい日付関数を提供することは知っていますが、以前のバージョンを使用している人は制限に注意する必要があります。

私たちのアプローチは、UTCを永続化し、変換の精度をより細かく制御できるクライアント側で変換を実行することです。


16

SQL Server2016以降およびAzureSQL Databaseの場合は、組み込みAT TIME ZONEステートメントを使用します。

SQL Serverの古いエディションの場合、ここにリストされているように、SQL Serverタイムゾーンサポートプロジェクトを使用して、IANA標準タイムゾーン間で変換できます

UTCからローカルへは次のようになります。

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
なんてこった...マットのこのプロジェクトは素晴らしく、CLRを必要としません。マットはこの+100の功績に値します
buckley 2016

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

ロブ


6
SWITCHOFFSETは夏時間を考慮しないため、特定の状況でのみ役立ちます。
robocat 2013年

2
いいえ。しかし、問題は、要求されたタイムゾーンへの切り替えを処理できるかどうかでした。
ロブファーリー2013年

「異なるタイムゾーンと夏時間の設定」という質問から。私たちも現地時間の解決策を探しています。あなたの提案は夏時間の問題を解決しませんか?
robocat 2013年

クライアントでタイムゾーンを検出し、指定されたタイムゾーンでデータベースを返す必要がある場合は、SWITCHOFFSET関数が非常に便利です。
ロブファーリー2013

3
@RobFarleyクライアントでタイムゾーンを検出し、SWITCHOFFSETを使用すると、問題が発生する可能性があります。変換する日時に夏時間が適用されているかどうかを知る必要があります。タイムゾーンを検出し、現在のオフセットをUTCに適用するだけで、1時間遅れることがあります。これは、すべてのコンバージョンが同じ国にある単純なケースです。すべての国が同じ日に夏時間に切り替えたり、夏時間から切り替えたりするわけではありません。SWITCHOFFSETは、現地時間を保存し、同じ国内の元のゾーンとターゲットゾーンの違いを知っている場合にうまく機能します。
jamieSee 2015年

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通話を連鎖させることができますが 、変換にはFromToで十分であり、必要なものはほとんどです
KarthikeyanMlp 2018年

4

私は、ローカルイベント(例:会議/パーティーなど、美術館での午後12時から午後3時)に関係のないすべての日時ストレージに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日付のローカル日時への解析を処理します。

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 2013

注意として、私はあなたがすることをまったく逆に行います。ローカルイベントに関連付けられているDateTimeの場合、DateTimeOffsetを保存します。ローカルイベントに関連付けられていないDateTimeの場合、DateTimeをUTCで保存します。前者には2つの関連データポイントがあり(現地時間はいつですか、現地時間は何ですか)、後者は1つだけです(いつ
ですか

@Martijnしかし、タイムゾーンはあなたに場所を与えません、そしてあなたはとにかく別々に保存しなければなりません。
トラッカー1 2014

@ tracker1これは、場所にタイムゾーンを知る方法がある場合にのみ機能し、それでも変換するのは完全に面倒です。
martijn 2014

3

はい、ここで詳しく説明されているように、ある程度です
私が使用したアプローチ(2008年以前)は、DBに挿入する前に.NETビジネスロジックで変換を行うことです。


1

GETUTCDATE()関数を使用してUTC日時を取得できます。おそらく、GETUTCDATE()とGETDATE()の差を選択し、この差を使用して日付をUTCに調整できます。

しかし、私は前のメッセージに同意します。ビジネス層(たとえば、.NET)で正しい日時を制御する方がはるかに簡単です。


12
番号!違いは正確な日付によって異なります。それは夏時間に依存します。
usr

3
夏時間を考慮していません。私はしばらくの間このような解決策を使用していました、そしてそれは大きな問題を引き起こしました。比較する日付がDSTにあるかどうかを判断する必要があります。
ジェフデイビス

-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.