3

MySQL5.0を使用しています。日時情報を 1 つの列に格納する必要があります。DATETIMEまたはTIMESTAMP列タイプを使用することを意味します。しかし、私は夏と冬の時間変更に問題があります。

私のタイムゾーンはCETです。夏には夏時間 (CEST、GMT+2) を使用し、冬には冬時間 (CET、GMT+1) を使用します。夏時間が冬時間に変わる日 (2012 年は 10 月 28 日) には、午前 2 時の時刻が 2 回あります。この日の時間の順序は次のとおりです。

... -> 1:00 CEST -> 2:00 CEST -> 2:00 CET (= 3:00 CEST) -> 3:00 CET -> ...

したがって、timestamp/datetime '2012-10-28 02:00:00' がある場合、この時刻が夏時間または冬時間の午前 2 時を表しているかどうかを正しく言うことはできません。

私は2つの異なるJava日付を持っています:

Date d1 = new Date(1351382400000); // 2:00 CEST (summer-time)
Date d2 = new Date(1351386000000); // 2:00 CET (winter-time)

そして、標準のタイムスタンプ/日時形式 (つまり'yyyy-MM-dd HH:mm:ss') を使用してそれらをデータベースに保存すると、どちらも同じデータ「2012-10-28 02:00:00」を保存します。しかし、これらの値をデータベースから Date 変数に戻すと、2 つの同じ日付が得られます。したがって、入力日は異なりますが、出力日は同じです。関数を使用して日付値を保存
すると、同じことが起こります:と. 値はデータベース列 (DATETIME または TIMESTAMP 型) に等しい値として格納されます。したがって、これらの値を Java の Date オブジェクトに取得すると、2 つの同じ日付が再び取得されます (冬時間)。FROM_UNIXTIMEFROM_UNIXTIME(1351382400)FROM_UNIXTIME(1351386000)

タイムゾーンを MySQL に保存する方法、または DATETIME/TIMESTAMP 列内のタイムゾーン情報を処理する方法はありますか?
もちろん、unix-timestamp を使用して BIGINT 値をデータベースに格納できます。しかし、MySQL の日時型でこの問題を解決する方法があるかどうか疑問に思っています。

どんな助けやトリックも大歓迎です... :)

どうもありがとう。

本座(スポラック)

編集 #1:
タイムスタンプ値を保存してから、このタイムスタンプ値を Java の Date にフェッチしようとすると、誤った Date が再び取得されます。TIMESTAMP 列を持つ単純なテーブルがあるとしましょう。このテーブルにデータを次のように保存します。

mysql> INSERT INTO `tab` (timestamp_column) VALUES 
          (FROM_UNIXTIME(1351382400)),  // 2:00 CEST (summer-time)
          (FROM_UNIXTIME(1351386000));  // 2:00 CET (winter-time)
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

これらの行を Java Date オブジェクトにフェッチすると、2:00 CET を示す 2 つの同じ日付が取得されます。さらに、MySQL でこれらの行をフェッチすると、MySQL で再び間違った値が返されます。

mysql> SELECT UNIX_TIMESTAMP(timestamp_column) from tab;
+--------------------+
| UNIX_TIMESTAMP(ts) |
+--------------------+
|         1351386000 | 
|         1351386000 | 
+--------------------+
2 rows in set (0.00 sec)

したがって、TIMESTAMP はほとんど役に立たないように思えます。

4

3 に答える 3

6

私の見解では、最善の策は、MySQL に GMT を使用して、データベースではなくアプリケーション コードですべての現地時間の問題を処理するように指示することです。データベース内の値は常に GMT (終止符) であり、明確です。おっしゃる通り、夏時間 (夏時間) の調整により、データベース内の値が同じになり、人間にとっては 2 つの異なる時間になる場合があります。

これにより、データベースも移植可能になります。北米に移動し、(たとえば) 中部時間に設定された MySQL の使用を開始すると、データベース内の値が突然数時間移動したように見えます。サーバーの現地時間を使用していた、継承したデータベースでその問題が発生しました。米国の東海岸から西海岸に移動したとき、MySQL がマシンのゾーンを使用するように設定されているかどうかを確認することを考えていませんでした...

于 2012-11-05T15:30:26.080 に答える
3

DATETIMEYEARおよびDATETIMEすべては、カレンダーや文字盤の写真を撮るのと同じように、それぞれの日付/時刻表示を保存します。これらは、時計が設定されたタイムゾーンを記録しないため、特定の瞬間を表すものではありません。これらは、特定のローカル日付または特定のローカル時間 (つまり、タイムゾーンに関係なく) に発生するイベントに役立ちます。

TIMESTAMPUTC タイムスタンプ (UNIX エポックからの秒数) を保存し、time_zone必要に応じてセッションとの間で変換を実行します。正確で明確な瞬間を表します。これはあなたが望むものです。セッション変数を適切に設定してください( を使用SET SESSION time_zone = ...)。

詳細については、 MySQL サーバーのタイム ゾーンのサポートを参照してください。

于 2012-11-05T15:56:30.427 に答える
0

データベースに保存する前に日付をUTCに変換し、データベースから読み取るときに独自のタイムゾーンに戻すことができます。

long t = 1351382400000; // the timestamp in UTC
String insert = "INSERT INTO my_table (timestamp) VALUES (?)";
PreparedStatement stmt = db.prepareStatement(insert);
java.sql.Timestamp date = new Timestamp(t);
stmt.setTimestamp(1, date);
stmt.executeUpdate();

.....

TimeZone timezone = TimeZone.getTimeZone("MyTimeZoneId");
Calendar cal = java.util.Calendar.getInstance(timezone);
String select = "SELECT timestamp FROM my_table";
// some code omitted....
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
   java.sql.Timestamp ts = rs.getTimestamp(1);
   cal.setTimeInMillis(ts.getTime());
   System.out.println("date in db: " + cal.getTime());
}
于 2012-11-05T16:22:12.470 に答える