SQL ServerでTimeZoneを適切に処理する方法は?


34

私のローカル開発サーバーは中東にありますが、本番サーバーは英国にあります。

ユーザーにタイムゾーンで日付を表示する必要があります。たとえば、ユーザーがサウジアラビアにいる場合、サウジアラビアの形式に従って時間を表示する必要があります。

TimeZoneという新しいデータベーステーブルを作成し、UTCで時間を保存する必要がありますか?


SQL 2005でUTCとローカル(PST)時間の間で日付を効果的に変換するhttp://stackoverflow.com/questions/24797/effectively-converting-dates-between-utc-and-local-ie-pst-time-in- sql-2005
mehdi

これはWebアプリケーションですか、デスクトップアプリケーションですか、それとも...?必要なものはクライアント側に依存するため、これを実装する方法はクライアント配信メカニズムによって大きく異なります。
ジョンセイゲル

このWebとネイティブモバイル。はい、これは異なるクライアントに異なる影響を与えます。
user960567

1
あなたの質問はデータベースそのものに関するものではなく、アプリケーション開発にも関係しているようです。このスタックオーバーフローの質問は、あなたにとって必読です:夏時間とタイムゾーンのベストプラクティス
ガン

回答:


48

残念ながら、これに対する簡単な修正はありません。アプリケーションの国際化は、日付/時刻の比較や出力のフォーマットなど、さまざまな分野の核心に実際に取り組むため、最初の設計の議論の一部である必要があります。

とにかく、Doing It Rightを追跡するためには、タイムゾーン情報を時間と共に保存することが不可欠です。つまり、(a)タイムゾーンのその時点でのUTCオフセット(注1)を含めるか、(b)これらの値を挿入するすべてのロジックが特定の固定オフセットに最初に変換されることなく、日付/時刻20130407 14:50無意味であることを認識します(ほとんどの場合0)。これらのいずれもなければ、与えられた2つの時間値は比較できず、データは破損しています。(後者の方法は、火で遊んでいます(注2)ところで、しないでください。)

SQL Server 2008+では、datetimeoffsetデータ型を使用して、オフセットを時間とともに直接保存できます。(完全を期すため、2005年以前は、2番目の列を追加して、その時点でのUTCオフセット値(分単位)を格納します。)

これらのプラットフォームには通常、ユーザーの地域設定に基づいて、日付/時刻+タイムゾーンをローカル時刻に自動的に変換してから出力用にフォーマットするメカニズムが備わっているため、デスクトップタイプのアプリケーションが簡単になります。

本質的に切断されたアーキテクチャであるWebの場合、バックエンドデータが適切に設定されていても、変換やフォーマットを実行できるようにクライアントに関する情報が必要なため、より複雑です。これは通常、ユーザー設定(アプリケーションが出力前に物事を変換/フォーマット)するか、全員に対して同じ固定フォーマットとタイムゾーンオフセットで物事を表示することで行われます(これはStack Exchangeプラットフォームが現在行っていることです)。

バックエンドデータが適切にセットアップされていないと、非常に迅速に複雑でハッキングされることがわかります。最終的にはより多くの問題が発生するため、これらのパスを下ることはお勧めしません。

注1:

タイムゾーンのUTCオフセットは固定されていません。ゾーンのUTCオフセットがプラスまたはマイナス1時間変動する夏時間を考慮してください。また、ゾーンの夏時間は定期的に異なります。だから、使用してdatetimeoffset(またはの複合local timeUTC offset at that time)最大の情報の回復に結果。

注2:

データ入力を制御することです。入ってくる値を検証する確実な方法はありませんが、計算を伴わない単純な標準を実施することをお勧めします。パブリックAPIがオフセットを含むデータ型を予期している場合、その要件は呼び出し元に明確になります。

そうでない場合、呼び出し元はドキュメントに依存する必要があります(ドキュメントを読む場合)、または計算が正しく行われないなど。または、ここの場合のように、別々のサーバー上のWeb /データベースだけでさえも)。

とにかくオフセットを保存すると、1石で2羽の鳥が死にます。そして、それが必要でなくても、必要であれば後で利用可能になります。確かに、より多くのストレージを使用しますが、そもそも記録しないとデータが失われるため、トレードオフの価値があると思います。


3
:私はそれを理解したようにオフセット時間は夏時間の意識のようなのDateTimeOffset失う情報に保存されている...詳細...タイムゾーンと同じではありませんstackoverflow.com/tags/timezone/info
ピーターMcEvoyさん

1
@PeterMcEvoy DSTはここでは関係ありません。datetimeoffset「これは、問題が発生したときのユーザー/コンピューターのローカル時間」を意味します-指定されたUTCオフセットが常に存在するため、DSTが有効であったかどうかを知る必要はありません(datetimeoffset値内に埋め込まれます)。

12

SQL Serverでのタイムゾーン変換のための包括的なソリューションを開発しました。GitHubでのSQL Serverタイムゾーンサポートを参照してください。

夏時間を含む、タイムゾーン間の変換とUTCとの間の変換を適切に処理します。

これは、adssの回答で説明されている「T-SQL Toolbox」ソリューションに概念的に似ていますが、Microsoftの代わりに、より一般的なIANA / Olson / TZDBタイムゾーンを使用し、データの新しいリリースとして維持されるユーティリティを含みますTZDBが登場します。

使用例(OPに回答するため):

SELECT Tzdb.UtcToLocal(sysutcdatetime(), 'Asia/Riyadh') as CurrentTimeInSaudiArabia

追加のAPIと詳細な説明については、GitHubのreadmeを参照してください。

また、これはUDFベースのソリューションであるため、パフォーマンスを主な目的として設計されていないことに注意してください。この機能がSQL Serverに組み込まれているCONVERT_TZと、OracleおよびMySQLに関数がどのように存在するかと同様に、さらに良いでしょう。


6

SQL Serverは2005年以降、内部タイムゾーンがUTCで保存されるように変更を加えました。これは主に、ジオレプリケーションとログ配布を伴うHAプロジェクターが原因であり、ログ配布時間が異なるタイムゾーンで保存されているため、古い方法では復元できませんでした。

したがって、すべてをUTC時間で内部的に保存することにより、SQL Serverはグローバルに機能します。これは、Outlookなどの他のMS製品も日付/時刻を内部的にUTCとして保存し、修正が必要なオフセットを作成するため、夏時間をWindowsで扱うのが苦痛な理由の1つです。

私は世界中に何千ものサーバー(ただし、MS SQL Serverではなく、あらゆる種類のサーバー)が分散している会社で働いています。非常に迅速に。


5

SQL Serverで日時とタイムゾーンの処理に苦労している人を支援するために、codeplexで「T-SQL Toolbox」プロジェクトを開発および公開しました。オープンソースであり、完全に無料で使用できます。

簡単な追加の構成テーブルを備えたプレーンなT-SQLを使用して、簡単な日時変換UDFを提供します。

この例では、次のサンプルを使用できます。

SELECT [DateTimeUtil].[UDF_ConvertLocalToLocalByTimezoneIdentifier] (
    'GMT Standard Time', -- the original timezone in which your datetime is stored
    'Middle East Standard Time', -- the target timezone for your user
    '2014-03-30 01:55:00' -- the original datetime you want to convert
)

これにより、ユーザーの変換された日時値が返されます。

サポートされているすべてのタイムゾーンのリストは、T-SQL Toolboxデータベース内でも提供される「DateTimeUtil.Timezone」テーブルにあります。


このようなツールキットは、開発者にとって大きな助けになると思われます。ただし、スカラー関数は、クエリオプティマイザーにとってブラックボックスです。関数を列に適用すると、言及している構成テーブルは、結果セットに行がある数だけヒットします(SELECT句でのみ関数を使用すると仮定します)。これは、パフォーマンスの観点からは素晴らしい見方ではないようです。ただし、ツールキットを実際にテストしたことはありませんので、確かに言うことはできません。これは、私が知っていることに基づいた一般的な懸念事項です。
アンドリーM

アンドリー、確かに、あなたはパフォーマンスの観点から正しいです。UDFクエリテーブルは、大量のデータ操作用ではなく、簡単に使用できるように設計されています。それにもかかわらず、彼らは私のマシン上で最大約100.000のレコードを実行します。
広告

2
ユースケースでより多くのレコードを処理する必要があり、パフォーマンスが重要な場合は、事前に計算されたデータを永続化することを検討する必要があります。ただし、それでも、これらのUDFは、必要なtimzonesでデータ時間値を保持するのに役立つ場合があります。
広告

私の観点からすると、この問題はパフォーマンスに関するものではなく、単に基本的な機能を取得することに関するものです。クエリから正確な情報を返すことができることが最初です。一時テーブルを作成して物事をキャッシュし、クエリでそれを参照するか、パフォーマンスを改善するためにそれをどのように処理するかが副次的になります。
アクションダン

1

私は明らかなものを見逃しているかもしれませんが、ユーザーのタイムゾーンと言語形式を使用して日付を表示するだけであれば、最も簡単な方法は常に日付をデータベースにUTCで保存し、クライアントアプリケーションがUTCからローカルに変換することですタイムゾーンとユーザーの地域設定を使用して、それに応じて日付をフォーマットします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.