Date
类中没有存储任何时区信息,它只存储自1970年1月1日00:00:00 GMT以来的毫秒数。问题在于,我正在使用安装在UTC时区服务器上的MySql,并且仅在UTC中存储
DateTime
。如果我执行select查询,则会得到此日期2014-01-17 16:15:49
。通过使用http://www.epochconverter.com/,我可以得到以下结果:
Epoch timestamp: 1389975349
Timestamp in milliseconds: 1389975349000
Human time (GMT): Fri, 17 Jan 2014 16:15:49 GMT
Human time (your time zone): Friday, January 17, 2014 9:45:49 PM
现在是Hibernate的部分。我正在一台以IST作为系统时区的机器上运行我的Java Web应用程序。我使用ID进行了简单的对象获取,并获取了createdDate
属性,它是一个Date
对象。我编写了一个简单的代码来理解它的输出,以下是代码:
Date dt = c.getCreatedDate();
System.out.println(dt.getTime());
System.out.println(dt);
DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm a z");
df.setTimeZone(TimeZone.getTimeZone("IST"));
System.out.println(df.format(dt));
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(df.format(dt));
以下是此操作的输出内容:
1389955549000
2014-01-17 16:15:49.0
17/01/2014 04:15 PM IST
17/01/2014 10:45 AM UTC
如果您将1389955549000
输入到http://www.epochconverter.com/中,则会得到以下输出:
GMT: Fri, 17 Jan 2014 10:45:49 GMT
Your time zone: Friday, January 17, 2014 4:15:49 PM GMT+5.5
这不是预期的输出,对吧。它给我返回的是毫秒数,而且比UTC时间晚了5:30,所以如果我想获取IST时区的时间,实际上得到的是UTC时间。
有人知道我错在哪里吗?
--------------------------我如何解决它----------------------------
根据Ako和Basil Bourque的建议:
Hibernate在从数据库中提取日期/时间字段时会考虑系统时区。如果你已经在数据库中存储了UTC的DateTime
,但是你的系统时间或至少你的Java应用程序时区是另一个时区(例如,IST-印度标准时间),那么Hibernate认为在数据库中存储的DateTime
也是IST时区的,这就导致了整个问题。
像Basil建议的那样,在不同的服务器上使用相同的时区。应该优先选择UTC。我应用的修复方法是添加以下代码:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
在ServletContextListener
中,我将我的应用程序时区设置为UTC,现在Hibernate按预期获取和存储日期。
setDate(int,java.sql.Date,java.util.Calendar)
:驱动程序使用Calendar对象构造SQL DATE值,然后将其发送到数据库。 使用Calendar对象,驱动程序可以计算考虑自定义时区的日期。 如果未指定Calendar对象,则驱动程序将使用默认时区,即运行应用程序的虚拟机的时区。 - ako