Java JDBC在将日期插入Oracle DB之前是否会调整日期?我如何防止这种情况?
假设我们有以下创建日期的代码:Java JDBC在将日期插入Oracle DB之前是否会调整日期?我如何防止这种情况?,java,jdbc,oracle11g,ojdbc,Java,Jdbc,Oracle11g,Ojdbc,假设我们有以下创建日期的代码: SimpleDateFormat sdf = new SimpleDateFormat( "dd/MM/yyyy" ); sdf.setTimeZone( TimeZone.getTimeZone( "UTC" ) ); // we know the date being parsed is UTC Date bizDate = sdf.parse( "12/12/2015" ); // milliseconds: 1449878400000 log.info(
SimpleDateFormat sdf = new SimpleDateFormat( "dd/MM/yyyy" );
sdf.setTimeZone( TimeZone.getTimeZone( "UTC" ) ); // we know the date being parsed is UTC
Date bizDate = sdf.parse( "12/12/2015" ); // milliseconds: 1449878400000
log.info( "ms: {}", bizDate.getTime() );
log.info( "date: {}", bizDate );
... // save to db
如果该代码在UTC的JVM上运行,在UTC的Oracle DB上运行,我会得到:
JVM参数:-Duser.timezone=UTC
millisecond: 1449878400000
date: Sat Dec 12 00:00:00 UTC 2015
in oracle db: 2015-Dec-12 00:00:00 // zero time
对于未设置为UTC(如SGT)的JVM,我得到:
JVM参数:无(默认时区为SGT或UTC+8:00)
请注意,它们都有相同的毫秒,但在数据库中插入的毫秒不同
我的问题是:
我已将SimpleDataFormat的时区设置为UTC,因为我希望将解析的日期视为UTC(或根据需要视为其他时区)。如果没有这样的要求,就不会有问题。现在,我似乎需要在插入之前调整日期以反转JDBC所做的操作。问题在于Java
Date
对象不存储时区。该值始终以UTC为单位,并在给定的时区(通常是JVM的默认时区)中进行解析和格式化
OracleDATE
列也不带时区存储,但应表示用户看到的日期。在99.99%的情况下,这意味着JVM默认时区中的日期
因此,JDBC驱动程序获取时间戳
/日期
值(UTC),将其转换为默认时区,并将其保存到数据库中
您正在使用该方法。要控制时区,请使用以下方法。引用javadoc:
使用给定的Calendar
对象,将指定参数设置为给定的java.sql.Timestamp
值。驱动程序使用日历
对象构造一个SQL时间戳
值,然后驱动程序将该值发送到数据库使用日历
对象,驱动程序可以计算时间戳,同时考虑自定义时区。如果未指定日历
对象,则驱动程序将使用默认时区,即运行应用程序的虚拟机的时区
我知道Oracle DATE没有时区。时区只是表示元数据。日期可能有不同的时区,但它们的基本毫秒是相同的。问题是,为什么JDBC驱动程序需要将其调整为本地时区,从而在保存到DB中时有效地改变其基本毫秒数?或者换一种方式,我可以要求驱动程序不要“计算时间戳”吗因为我想存储毫秒,因为我知道我在做什么?因为Oracle中的
DATE
不是存储在UTC中,而是存储在数据库时区中,所以必须转换UTC值。只要JVM时区和数据库时区相同,就没有问题。有关Oracle时区支持的更多信息,请阅读本文:是的,如我所说,使用3参数版本,并在日历
对象中指定时区。在您的情况下,这将是UTC时区。你显然不知道自己在做什么,否则就不会有这些问题。在我的例子中,Oracle DB的时区设置为UTC,当JVM的时区与DB的时区不同时,我会遇到问题。代码将在不同时区的多个JVM上运行。
millisecond: 1449878400000
date: Sat Dec 12 08:00:00 SGT 2015
in oracle db: 2015-Dec-12 08:00:00 // plus 8 hours