何が起こるかを正確に把握するために、いくつかのテスト用JDBCコードをまとめました。結果は面白かった。 Oracleには、密接に関連する3つのデータ型、TIMESTAMP
,TIMESTAMP WITH TIME ZONE
およびTIMESTAMP WITH LOCAL TIME ZONE
があります。私はまったく同じコードをとり、 "America/New_York"タイムゾーンとUTCで実行する2つの異なるボックスから実行しました。両方ともUTCで動作する同じデータベースにアクセスします。私はOracle 11.2.0.2.0ドライバを使用していました。
TIMESTAMP
の列は、Javaコードを実行しているマシンのローカル時刻に設定されていました。タイムゾーン変換は行われませんでした。
TIMESTAMP WITH TIME ZONE
列は、JDBCクライアントがでたどんな時間帯までの時間を翻訳した。TIMESTAMP WITH LOCAL TIME ZONE
列はまた、JDBCクライアントがしていたものは何でもタイムゾーンに時間を翻訳
- 。少し古いです
This articleを、あなたがインデックスやパーティションのようなことをしたいのであれば、TIMESTAMP WITH TIME ZONE
はかなり役に立たないことを示しています。しかし、それはTIMESTAMP WITH LOCAL TIME ZONE
のように非常に便利かもしれないようです。 (サーバーのタイムゾーンを変更するとどうなるかわかりませんが、JDBCクライアントのローカルタイムゾーンについてはインテリジェントなようです)。私は、これらのデータ型を使って、索引付けの動作などをテストする機会はありませんでした。
あなたの環境でテストを再現したい場合は、下のサンプルクラスに貼り付けてください。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Date;
// create table x_tst_ts_tab(
// os_name varchar(256)
// ts timestamp,
// ts_with_tz timestamp with time zone,
// ts_with_local_tz timestamp with local time zone
//)
class TSTest {
public static final void main(String[] argv) throws Exception {
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(
"your_connection_string",
"your_user_name",
"your_password");
try {
// Insert some data
Date nowDate = new Date();
Timestamp nowTimestamp = new Timestamp(nowDate.getTime());
PreparedStatement insertStmt = conn.prepareStatement(
"INSERT INTO x_tst_ts_tab"
+ " (os_name, ts, ts_with_tz, ts_with_local_tz)"
+ " VALUES (?, ?, ?, ?)");
try {
insertStmt.setString(1, System.getProperty("os.name"));
insertStmt.setTimestamp(2, nowTimestamp);
insertStmt.setTimestamp(3, nowTimestamp);
insertStmt.setTimestamp(4, nowTimestamp);
insertStmt.executeUpdate();
} finally {
try {
insertStmt.close();
} catch (Throwable t) {
// do nothing
}
}
System.out.println("os_name, ts, ts_with_tz, ts_with_local_tz");
// Read back everything in the DB
PreparedStatement selectStmt = conn.prepareStatement(
"SELECT os_name, ts, ts_with_tz, ts_with_local_tz"
+ " FROM dom_fraud_beacon.x_tst_ts_tab");
ResultSet result = null;
try {
result = selectStmt.executeQuery();
while (result.next()) {
System.out.println(
String.format("%s,%s,%s,%s",
result.getString(1),
result.getTimestamp(2).toString(),
result.getTimestamp(3).toString(),
result.getTimestamp(4).toString()
));
}
} finally {
try {
result.close();
} catch (Throwable t) {
// do nothing
} finally {
try {
selectStmt.close();
} catch (Throwable t) {
// do nothing
}
}
}
} finally {
try {
conn.close();
} catch (Throwable t) {
// do nothing
}
}
}
}
なぜデータベースが中央で行うことができるときにフロントエンドでそれをやっていますか? – Tim
私はJDBCドライバが何をしているのか理解しようとしています。私のログでは、ローカル時間を表す文字列をOracleに送信しているようです。これは私を悩ます。 – drinian
[このドキュメント](http://docs.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame10.html)では、JDBCドライバによって送信されるものが正規化されていないことが示唆されています(つまりUTC)のタイムスタンプではなく、ローカルのタイムゾーンタイムスタンプ(ランダムに呼び出すもの)とサーバーは、ドライバを持つサーバーのタイムゾーンを使用して日付を計算することになっています。これはあなたの所見と一致しています。はい、これは気になります。 –