我正在尝试使用休眠在 Oracle 中保存两个日期。两个日期在莫斯科时区具有相同的时间戳:2005-10-30T02:00+03:00[Europe/Moscow] 和 2005-10-30T02:00+04:00[Europe/Moscow](“Sun Oct 30 02:00:00 MSK 2005”和“Sun Oct 30 02:00:00 MSD 2005”)。这些日期在时间上相隔一小时,并且与冬/夏时间的转换有关。
我在 Oracle 中创建了表:
create table TMP
(
ID LONG,
TS TIMESTAMP,
TSLTZ TIMESTAMP WITH LOCAL TIME ZONE,
TSTZ TIMESTAMP WITH TIME ZONE
);
和我模块中的实体:
@Entity
@Table(name = "tmp")
public class DateTimeOracle {
private Long id;
private ZonedDateTime ts;
private ZonedDateTime tsltz;
private ZonedDateTime tstz;
@Id
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public ZonedDateTime getTs() {
return ts;
}
public ZonedDateTime setTs(ZonedDateTime ts) {
this.ts = ts;
}
public ZonedDateTime getTsltz() {
return tsltz;
}
public ZonedDateTime setTsltz(ZonedDateTime tsltz) {
this.tsltz = tsltz;
}
public ZonedDateTime getTstz() {
return tstz;
}
public ZonedDateTime setTstz1(ZonedDateTime tstz) {
this.tstz = tstz;
}
}
在实体中,所有字段都由单个日期初始化。保存后,Oracle 中的两个日期具有相同的值,如下所示:
ts = 2005-10-30 02:00:00.000000
TSLTZ = 2005-10-29 23:00:00.000000
TSTZ = 2005-10-30 02:00:00.000000 +04:00
为什么 oracle 对不同的日期(包括偏移量 +04:00)保持相同的值?有没有什么办法解决这一问题?
PS Postgres 正确存储日期。一个偏移量为 +03:00,另一个偏移量为 +04:00(分别为 2005-10-29 23:00:00.000000 和 2005-10-29 22:00:00.000000)。
更新
这就是我创建日期的方式:
Date dt2 = new Date(1130623200000L); //2005-10-29 23:00:00 +04:00
Date dt3 = new Date(1130626800000L); //2005-10-29 23:00:00 +03:00
ZonedDateTime zdt2 = ZonedDateTime.ofInstant(dt2.toInstant(), ZoneId.systemDefault()); // My zone is MSK
ZonedDateTime zdt3 = ZonedDateTime.ofInstant(dt3.toInstant(), ZoneId.systemDefault()); // My zone is MSK
OffsetDateTime odt2 = zdt2.toOffsetDateTime();
OffsetDateTime odt3 = zdt3.toOffsetDateTime();
如果我不使用 Hibernate 并直接使用 jdbc,情况不会改变。
Connection conn = DriverManager.getConnection("<oracle_url>",
"<username>", "<password>");
PreparedStatement pstmt = conn.prepareStatement("insert into tmp (id, TSTZ1, TSTZ2) values (200, ?, ?)", Statement.RETURN_GENERATED_KEYS);
pstmt.setDate(1, new java.sql.Date(dt2.getTime()));
pstmt.setDate(2, new java.sql.Date(dt3.getTime()));
int z1 = pstmt.executeUpdate();
pstmt.close();
conn.close();
更新2
如果我通过 jdbc 驱动程序将 OffsetDateTime 保存在带有本地时区的时间戳或带有时区的时间戳中,那么一切都很好。
PreparedStatement pstmt = conn.prepareStatement("insert into tmp (TSLTZ1, TSLTZ2, TSTZ1, TSTZ2) values (?, ?, ?, ?)");
pstmt.setObject(1, odt2);
pstmt.setObject(2, odt3);
pstmt.setObject(3, odt2);
pstmt.setObject(4, odt3);
我在数据库中看到:
2005-10-29 22:00:00.000000 2005-10-29 23:00:00.000000 2005-10-30 02:00:00.000000 +04:00 2005-10-30 02:00:00.000000 +03:00
但是,如果我保存 ZonedDateTime,则带有本地时区的时间戳中的值是正确的,但带有时区的时间戳中的值不正确。
PreparedStatement pstmt = conn.prepareStatement("insert into tmp (TSLTZ1, TSLTZ2, TSTZ1, TSTZ2) values (?, ?, ?, ?)");
pstmt.setObject(1, zdt2);
pstmt.setObject(2, zdt3);
pstmt.setObject(3, zdt2);
pstmt.setObject(4, zdt3);
在数据库中我看到:
2005-10-29 22:00:00.000000 2005-10-29 23:00:00.000000 2005-10-30 02:00:00.000000 +04:00 2005-10-30 02:00:00.000000 +04:00
最后两个值不正确。