web-dev-qa-db-ja.com

SQL Serverでのタイムゾーンからタイムゾーンへの日時変換

データベーステーブルにUNIXタイムスタンプの列があります。これは、クウェートタイムゾーンにあるシステムから取得したものです。

データベースサーバーのタイムゾーンはEastern Time US & Canada。次に、SQLクエリを使用して、UNIXタイムスタンプをクウェートタイムゾーンの日付値に変換する必要があります。

このUNIXタイムスタンプをクウェートタイムゾーンの日付値に変換する方法を教えてください。

14
Ashish Rathore

Unixタイムスタンプは、1970年1月1日UTCからの秒数の整数です。

データベースにこの数値の整数列があると仮定すると、データベースサーバーのタイムゾーンは無関係です。

最初にタイムスタンプをdatetimeタイプに変換します。

SELECT DATEADD(second, yourTimeStamp, '1970-01-01')

これは、タイムスタンプに対応するUTC datetimeになります。

次に、この値をターゲットタイムゾーンに調整する方法を知る必要があります。世界の大部分では、夏時間のために、1つのゾーンに複数のオフセットを設定できます。

残念ながら、SQL Serverには作業時間帯を直接処理する機能がありません。たとえば、米国太平洋時間を使用している場合、7時間を減算するのか8時間を減算するのかを知る方法はありません。他のデータベース(Oracle、Postgres、MySqlなど)にはこれを処理する方法が組み込まれていますが、残念ながらSQL Serverにはありません。したがって、汎用ソリューションを探している場合は、次のいずれかを実行する必要があります。

  • タイムゾーンデータをテーブルにインポートし、タイムゾーンルールの変更に合わせてそのテーブルを維持します。特定の日付のオフセットを解決するために、そのテーブルを多数のカスタムロジックで使用します。

  • 使用する xp_regreadタイムゾーンデータを含むWindowsレジストリキーを取得し、特定の日付のオフセットを解決するカスタムロジックの束を再度使用します。もちろん、 xp_regreadは悪いことであり、特定の権限を付与する必要があり、サポートも文書化もされていません。

  • .NetでTimeZoneInfoクラスを使用するSQLCLR関数を記述します。残念ながら、これは 「安全でない」SQLCLRアセンブリが必要 であり、悪いことが起こる可能性があります。

私見、これらのアプローチはどれも非常に良いものではなく、これをSQLで直接行う良い解決策はありません。最良の解決策は、UTC値(元の整数、またはUTCのdatetime)を呼び出しているアプリケーションコードに返し、代わりにタイムゾーン変換を行うことです(たとえば、TimeZoneInfo .Netまたは他のプラットフォームの同様のメカニズム)。

ただし、クウェートは夏時間に変更されないゾーンにいる(そして常に移動している)という点で幸運です。常にUTC + 03:00でした。したがって、単純に3時間を追加して結果を返すことができます。

SELECT DATEADD(hour, 3, DATEADD(second, yourTimeStamp, '1970-01-01'))

ただし、これはどのタイムゾーンでも機能する汎用ソリューションではないことを認識してください。

必要に応じて、datetimeoffsetなど、他のSQLデータ型のいずれかを返すこともできますが、これは値を見る人に対して3時間のオフセットがあることを反映するのに役立ちます。変換プロセスがこれ以上異なることはありません。


更新された回答

SQL Serverのタイムゾーンをサポートするプロジェクトを作成しました。インストールできます ここから 。その後、次のように単純に変換できます。

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'Asia/Kuwait')

IANA tzデータベースの任意のタイムゾーン を使用できます。これには、夏時間を使用するものも含まれます。

上記で示したメソッドを使用して、Unixタイムスタンプから変換できます。両方をまとめる:

SELECT Tzdb.UtcToLocal(DATEADD(second, yourTimeStamp, '1970-01-01'), 'Asia/Kuwait')

再度更新

SQL Server 2016では、 AT TIME ZONE ステートメント。これは、Azure SQL Database(v12)でも利用できます。

SELECT DATEADD(second, yourTimeStamp, '1970-01-01') AT TIME ZONE 'Arab Standard Time'

この発表のその他の例

27