Java JodaTime Hibernate支持使用错误时区保存日期时间

Java JodaTime Hibernate支持使用错误时区保存日期时间,java,hibernate,timezone,jodatime,Java,Hibernate,Timezone,Jodatime,我知道也有类似的问题,但我想弄清楚到底是什么问题 基本上,我试图在Oracle数据库中保存一个日期。我希望它存储在UTC时间。数据库中的列是时间戳,我不保存时区信息 查看JodaTime Hibernate支持类PersistentDateTime,似乎nullSafeGet()方法只是调用DateTime.toDate(),后者返回java.util.Date。这是保存在数据库中的日期 我不明白的是。。。为什么getDate()不保留现有DateTime的时区?我用UTC向它发送一个日期时间(

我知道也有类似的问题,但我想弄清楚到底是什么问题

基本上,我试图在Oracle数据库中保存一个日期。我希望它存储在UTC时间。数据库中的列是时间戳,我不保存时区信息

查看JodaTime Hibernate支持类PersistentDateTime,似乎nullSafeGet()方法只是调用DateTime.toDate(),后者返回java.util.Date。这是保存在数据库中的日期

我不明白的是。。。为什么getDate()不保留现有DateTime的时区?我用UTC向它发送一个日期时间(比如17:00),在调用getDate()时,它会切换到我的时区CET(18:00)。我希望它能节省17点,而不是18点

我意识到这(可能)是从运行Java的环境中获取时区,一种可能是使用命令行参数更改时区。但我不想那样做,而且我也不允许在生产机器上这样做

我目前的想法是实现一个类,该类扩展PersistentDateTime并重写nullSafeGet()方法,以便维护传递给它的日期时间的时区。不知道该怎么做。。。也许JodaTimeAPI中有一个方法可以很好地实现这一点

不管怎样,我只是好奇是否有其他人对这种行为感到惊讶,或者是否只有我。如果我的想法是好的,或者有人有更好的想法。更改服务器(应用程序或数据库)或其他配置不是一个选项,我需要用代码解决这个问题

编辑

为了子孙后代的利益,为了回答那些有帮助的评论,我想澄清一下我的问题到底是什么

我认为问题在于我的应用服务器和数据库服务器有不同的时区。事实证明,这不是问题所在。问题在于,应用程序服务器或JVM的时区与我在应用程序中使用的时区不同。让我解释一下

我的web应用程序管理事件。事件有开始和结束日期。这些是Oracle数据库中的时间戳列(不带时区)。此外,在应用程序中,您必须定义您使用的时区。这与应用服务器(以及随后的JVM)或db服务器正在使用的时区无关

当然,应用服务器确实有一个时区。在我的例子中是CST,中央标准时间(GMT-6)。当应用程序中使用的时区与JVM级别使用的时区不一致时,就会出现问题。在我的例子中,应用程序中定义的时区是东部标准时间(GMT-5)

发生了什么事?发生的情况是,我从web管理面板创建了一个事件,例如:

  • 开始日期:2014年1月15日09:00
  • 结束日期:2014年1月20日23:00
这些日期是使用Joda DateTime创建的,并被指定了正确的时区(使用DateTime.withZoneRetainFields()),即我在应用程序中使用的时区EST。因此,我的活动如下所示:

  • 事件名称:事件1
  • 开始日期:美国东部时间2014年1月15日09:00
  • 结束日期:美国东部时间2014年1月20日23:00
到目前为止还不错。但是,当我保存时,日期保存如下:

  • 开始日期:2014年1月15日08:00
  • 结束日期:2014年1月20日22:00
发生了什么事?发生的事情是,由于appserver/JVM在CST中运行,所以两个日期都减少了一个小时。我认为这是一个bug,但正如评论员所说,这是一个特性。JodaTime Hibernate驱动程序只调用DateTime.toDate(),该驱动程序创建一个java.util.Date,它本身没有时区,但会根据JVM使用的时区自动更改小时

我怎样才能避免这种情况?我可以使用-Duser.timezone参数启动JVM,并确保它始终与应用程序中使用的时区相同。这是一个选择

我可以做的另一件事不是避免问题,而是解决它。换句话说,在Hibernate/数据库级别,每当我加载事件时,确保开始和结束日期字段被分配给应用程序定义的时区,从而将小时数转换回应用程序中使用的时区。这样,即使它们保存为08:00和22:00,它们在应用程序中也将显示为09:00和23:00。这显然是更好的解决方案,而且更明确。但我只是不确定这些工作是否值得。我已经看到了在web上使用Hibernate实现这一点的各种方法——使用属性访问类型或自定义Hibernate用户类型。不确定它们是否正常工作,而且看起来工作量很大,非常烦人。我必须从使用DateTime改为使用日历(我想,不确定)和/或在POJO中进行特殊映射

事实上,应用程序中到处都有java.util.Dates,在许多情况下,只需执行一个新的Date()来实例化它们,而不考虑时区。这些最终都应更改为DateTime,并使用应用程序定义的时区显式实例化

但这需要做很多工作。目前,我只选择使用-Duser.timezone参数,看看它是如何运行的。同样,这不是最好的解决方案,但我认为它满足了我们目前的需要

非常感谢所有评论者“睁开我的眼睛”。j.u.Date很棘手 chrylis的注释很可能是正确的:您被java.util.Date类愚弄了。日期没有时区,但它的
toString
实现应用JVM的默认时区。因此,对于没有经验的Java程序员来说,日期对象似乎有一个时区,但实际上没有

如果chrylis和我是正确的,那么您就没有数据库问题,没有JDBC问题,没有Hibernate问题,也没有ha