我有一个Oracle数据库,它的时区与服务器的时区不同。服务器本身具有不同的时区。
我尝试了几种数据类型:DATE、TIMESTAMP、TIMESTAMPWIThTIMEZONE、TIMESTAmpWIThLOCALTIMEZONE,当与JDBC一起使用时,它们都有不同的问题。请参阅以下问题(我的服务器位于IDT时区,数据库位于PST时域)。
在多时区架构中,哪种日期数据类型正确
要创建具有不同日期类型的表:
create table ALIK_TZ (
D date default sysdate,
t timestamp default systimestamp,
tz timestamp with time zone default systimestamp,
ltz timestamp with local time zone default systimestamp
);
插入值:
insert into ALIK_TZ (d) values (default);
查询:
select to_char(d, 'DD-MON-YYYY HH24:MI:SS') D_SECS, ALIK_TZ.* from ALIK_TZ;
结果:
"D_SECS" "D" "T" "TZ" "LTZ"
"01-JUN-2016 06:14:04" 01-JUN-16 01-JUN-16 06.14.04.920000000 AM 01-JUN-16 06.14.04.920000000 AM -07:00 01-JUN-16 04.14.04.920000000 PM
"01-JUN-2016 06:20:54" 01-JUN-16 01-JUN-16 06.20.54.181000000 AM 01-JUN-16 06.20.54.181000000 AM -07:00 01-JUN-16 04.20.54.181000000 PM
使用JDBC进行查询:
preparedStatement = conn.prepareStatement("select * from ALIK_TZ");
resultSet = preparedStatement.executeQuery();
getObject
:的结果
D->java.sql.Timestamp(01-JUN-2016 06:14:04)
T->java.sql.Timestamp(2016-06-01 06:14:04.92)
TZ->oracle.sql.TIMESTAMPTZ
LTZ->oracle.sql.TIMESTAMPTZ
正如您所看到的,我不能使用D或t,因为我需要时区中的结果。
关于TZ,如果我使用ResultSet.getTimestamp(4),它将返回java.sql.Timestamp(2016-06-01 16:14:04.92)-在正确的时区中!!!但缺点是我不能在TIMESTAMP WITH TIME ZONE上使用索引。
关于LTZ,我甚至不能使用ResultSet.getTimestamp()
。我需要递一份日历。执行resultSet.getTimestamp(5, Calendar.getInstance())
返回java.sql.Timestamp(2016-06-01 13:14:04.92)-错误的时区(UTC而不是IDT)。
所以我似乎找不到与JDBC一起使用的完美日期-时间数据类型。想法
*顺便说一句,可以使用longs(从1970 UTC开始的millis),但在查看数据库中的数据时非常麻烦。
我个人建议在数据库端使用TIMESTAMP WITH TIME ZONE
,在Java端使用java.time.ZonedDateTime
。这使您独立于任何服务器和客户端设置,并允许稍后转换到任何时区,如果您决定这样做的话
唯一的问题是,当您计算和存储未来的日期时,特定时区的时区规则会发生变化。然而,如果你足够早地发现这一点,这是可以纠正的。