2

モバイルアプリケーションを開発しています。アプリケーション呼び出しから、モード (?mode=xx) に基づいてさまざまなクエリを実行する Web サービスが呼び出されます。

これらのクエリの一部では、DATE(NOW()) などの日付関数を使用しています。

MySQL データベースに保存されているデータは、GMT-7 (カナダ山岳時間) で保存されています。

この Web サービスのドメイン/ホストをまだ登録していませんが、登録すると、トロントなどの別の都市 (GMT-5 - 2 時間先) でホストされていると言えます。次に、カナダ山地時間の午後 10 時 5 分に、ユーザーがアプリケーションを使用して、次のようなクエリを持つ Web 要求呼び出しを送信します。

SELECT DATE(NOW()) 

サーバーはトロントでホストされているため、ユーザーがいる場所が前日であり、アプリケーションが現在の日付に基づいてデータを表示している場合でも、明日の日付が返されます。

誰でもこれについて何か考えがありますか?

編集:

SYSTEM
2015-01-29 16:19:48
2015-01-29 23:19:48

クエリ select @@time_zone, now(), utc_timestamp() を実行した結果です

クエリは、日付 (yyyy-mm-dd) と時刻 (hh:mm:ss) の列タイプを扱います。

4

1 に答える 1

4

この時間診断クエリを MySQL サーバーで実行しました。

select @@time_zone, now(), utc_timestamp()

サーバー マシンのシステム タイム ゾーン設定が「Canada/Mountain」であり、MySQL サーバー ソフトウェアに独自のタイム ゾーン設定がないことは、現地時間と utc 時間から明らかです。

テーブルをピックアップして、変更せずに近くのタイムゾーンのサーバーに移動すると、ソフトウェアを常に更新してコマンドを発行できます

set time_zone = 'Canada/Mountain';

ソフトウェアから接続した直後。これにより、新しい MySQL 接続が現在の接続と同じように動作するようになります。MySQL サーバーを所有している場合は、このページの指示に従ってデフォルトのタイム ゾーンを設定できます。 http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html

さて、これが時間データ型に関する話です。 DATETIME、およびDATETIMEはすべてタイムゾーンを無視します。日付/時刻の値を保存すると、タイムゾーンの設定を変更しても同じ値が返されます。

TIMESTAMPデータ型はタイムゾーンに依存します。これらのデータ項目は常にUTC (Z、時間、以前はグリニッジ標準時) として保存されます。それらは保存時に常に UTC に変換され、取得時に常に元に変換されます。

現在の日付と時刻 (およびフレンド)を取得するための組み込み関数は、タイムゾーンに依存します。それらは現地時間で値を生成します。例外は、 UTC 時間で値を生成する 3 つの関数です。NOW()UTC_

多くの MySQL マルチタイム ゾーン アプリケーションは、次の操作規律を使用します。

  1. 各ユーザーに好みのタイム ゾーンを尋ねるか、ユーザーに関するその他の個人データから割り出します。(電話には、ネットワークからこの情報がプロビジョニングされています。)ユーザーに代わって、 zoneinfo に適したタイム ゾーン記述子 ('America/New_York'、'Canada/Mountain'、'Europe/Vienna' など) としてそれを保存します。
  2. set time_zoneユーザーに代わって MySQL セッションを確立したら、上記のようなクエリを使用してユーザーのタイム ゾーンを設定します。これは、手術直後に行う必要がありますconnect
  3. ユーザーの日付と時刻をTIMESTAMPデータ型に格納します。保存時に UTC に変換されます。
  4. 必要に応じて取得します。それらは現地時間に変換されます。

アイデアは、ユーザーのタイムゾーンがコンテキストの一部であるということです。ユーザー A がバンクーバーにいて、ユーザー B がハリファックスにいて、何らかの理由でユーザー B がユーザー A の時刻データを表示すると、ほぼ自動的に大西洋時間で B に表示されるため、これはうまく機能します。

また、夏時間から標準時間への変化という世界的な気まぐれを透過的に処理できるという点でも優れています。昨年夏のタイムスタンプは、昨年夏の現地時間で表示されます。

グローバルに使用するサーバーの管理者の多くは、システム サーバー時間または MySQL のデフォルト タイム ゾーンを UTC に設定しています。(あなたのものはそうではありません。)

これらすべてを処理する別の方法は、あなたが始めた方法です。タイム ゾーンを選択し、そのタイム ゾーンに関するタイムスタンプを保存します。その場合、夏時間と標準時間を交互に切り替えないタイムゾーンを選択することをお勧めします。次に、時刻をデータベースに格納するときに、明示性を変換します。次のようにして、オタワのユーザーからの時間を保存します。

INSERT INTO tbl (appt) VALUES ( 'whatever-time' - INTERVAL 120 MINUTE)

同じ方法で値を取得します。これはエラーが発生しやすいですが、機能させることができます。

最後に、自分で変換を行うことができます。任意のタイムゾーンと UTC の間に何分のオフセットがあるかを知りたい場合は、次の 2 つのクエリを試してください。

set time_zone = 'Canada/Atlantic';
select timestampdiff(minute, utc_timestamp(), now());

この時期には -240、つまり -4:00 が返されます。一部の国では 30 分または 15 分のタイムゾーン オフセットがあるため、時間ではなく分を使用する必要があります。

最後に、気をつけてください。TIMESTAMPデータ型は 1970 年より前の時間を表していません。また、私の MariaDB 10.0 インスタンスでは、2038-01-19T03:14:07 UTC の直後に時刻が 32 ビットからロールオーバーすると、バケット内で地獄に落ちたように見えます。

于 2015-01-30T00:12:41.013 に答える