在app中的日期时间但在mysql [时区]错误

时间:2012-09-13 03:46:37

标签: java mysql hibernate convert-tz

问题:在应用服务器中的正确时间,在数据库中出错。

我在中国,时区是UTC + 8 我用hibernate。实体定义如下(语言:Scala)

class CargoJournal {
    @Type(`type`="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
    var deliverTime: LocalDateTime = _

    @Temporal(TemporalType.TIMESTAMP)
    @Column(nullable=false)
    var logDate:Date = _
}

我打开hibernate日志,在我的app服务器中看到以下内容。当前时间是Thu Sep 13 11:08:44 CST 2012

insert into wms_history_cargo_journal (deliver_time, log_date)
binding parameter [1] as [TIMESTAMP] - 2012-09-13 11:08:44.25
binding parameter [2] as [TIMESTAMP] - Thu Sep 13 11:08:44 CST 2012

在我的数据库服务器中:

mysql> select timediff(now(),convert_tz(now(),@@session.time_zone,'+00:00'));
+----------------------------------------------------------------+
| timediff(now(),convert_tz(now(),@@session.time_zone,'+00:00')) |
+----------------------------------------------------------------+
| 08:00:00                                                       |
+----------------------------------------------------------------+

所以mysql时区是对的。 UTC + 8

从mysql中选择后:

mysql> SELECT deliver_time, log_date FROM wms_history_cargo_journal;
+---------------------+---------------------+
| deliver_time        | log_date            |
+---------------------+---------------------+
| 2012-09-13 11:08:44 | 2012-09-13 03:08:44 |
+---------------------+---------------------+

log_date错了!

1 个答案:

答案 0 :(得分:1)

MySQL中有哪些类型的列?我怀疑它是DATETIME。这种类型不存储“时刻”,它存储“时钟上的小时”,因此可以表示不同时区的不同时刻。

当MySQL驱动程序将java.util.Date写入DATETIME列时,它必须选择一些时区来写“时钟上的小时”,因为相同的java.util.Date可能意味着不同时区的不同小时。它将小时存储在MySQL服务器本地时区中。

LocalDateTime没有这个问题,因为它就像DATETIME。它表示时钟上的小时,而不是时刻,因此年/月/日 - 小时/分钟/秒仅存储在数据库中。请注意,在hibernate日志中,LocalDateTime按原样给出,而Date旁边有时区(“CST”)。

通常,最好将时间存储在UTC中,因此请使用DateTime,而不是Date和LocalDateTime。使用jadira转换器的DateTime始终将DATETIME存储/读取为UTC。