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)

请注意,它们都有相同的毫秒,但在数据库中插入的毫秒不同

我的问题是:

  • JDBC标准是否说它在插入日期对象之前会调整日期对象?请举出你的消息来源

  • 如果JDBC在JVM的时区没有设置为UTC时,在将日期对象插入数据库之前确实调整了日期对象,那么为什么要这样设计呢?我觉得这让人更困惑。我希望它能按原样插入。想象一下,如果您使用毫秒创建一个日期(例如新日期(1449878400000L)),它将以不同的方式存储,并且您没有关于JVM时区的信息,您的代码将在其中运行。或者设想您的代码将在设置为不同时区的多个JVM上运行

  • 当JVM的时区设置为UTC以外的任何值时,如何防止JDBC调整日期?我正在使用ibatis,我可能无法直接访问准备的报表


  • 我已将SimpleDataFormat的时区设置为UTC,因为我希望将解析的日期视为UTC(或根据需要视为其他时区)。如果没有这样的要求,就不会有问题。现在,我似乎需要在插入之前调整日期以反转JDBC所做的操作。

    问题在于Java
    Date
    对象不存储时区。该值始终以UTC为单位,并在给定的时区(通常是JVM的默认时区)中进行解析和格式化

    Oracle
    DATE
    列也不带时区存储,但应表示用户看到的日期。在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