Tôi đã tập hợp một số mã JDBC thử nghiệm để tìm ra chính xác điều gì sẽ xảy ra. Kết quả thật thú vị. Oracle có ba kiểu dữ liệu liên quan chặt chẽ:TIMESTAMP
, TIMESTAMP WITH TIME ZONE
và TIMESTAMP WITH LOCAL TIME ZONE
. Tôi đã lấy cùng một mã chính xác và chạy nó từ hai hộp khác nhau, một ở múi giờ "America / New_York" và một chạy trên UTC. Cả hai đều truy cập vào cùng một cơ sở dữ liệu, chạy trong UTC. Tôi đang sử dụng trình điều khiển Oracle 11.2.0.2.0.
-
TIMESTAMP
cột được đặt thành bất kỳ thời gian cục bộ trên máy thực thi mã Java. Không có bản dịch múi giờ nào được thực hiện. -
TIMESTAMP WITH TIME ZONE
cột đã dịch thời gian sang bất kỳ múi giờ nào mà ứng dụng khách JDBC đang ở. -
TIMESTAMP WITH LOCAL TIME ZONE
cột cũng dịch thời gian sang bất kỳ múi giờ nào mà ứng dụng khách JDBC đang ở.
Bài viết này
, cũ hơn một chút, cho biết rằng TIMESTAMP WITH TIME ZONE
khá là vô dụng nếu bạn muốn làm bất cứ điều gì như chỉ mục hoặc phân vùng. Tuy nhiên, có vẻ như TIMESTAMP WITH LOCAL TIME ZONE
có thể cực kỳ hữu ích. (Không chắc điều gì sẽ xảy ra nếu bạn thay đổi múi giờ của máy chủ, nhưng nó có vẻ thông minh về múi giờ địa phương của ứng dụng khách JDBC). Tôi chưa có cơ hội kiểm tra hành vi lập chỉ mục, v.v. với các kiểu dữ liệu này.
Dán trong lớp mẫu của tôi bên dưới nếu bạn muốn tái tạo các bài kiểm tra của tôi trong môi trường của bạn.
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
}
}
}
}