Problem: Right time in app server, wrong in database.
I am in China, Time Zone is UTC+8
I use hibernate. Entity definition as following (language: Scala)
class CargoJournal {
@Type(`type`="org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
var deliverTime: LocalDateTime = _
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable=false)
var logDate:Date = _
}
I open the hibernate log, see following in my app server. Current time is 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
In my database server:
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 |
+----------------------------------------------------------------+
So the mysql time zone is right. UTC+8
After select from 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 |
+---------------------+---------------------+
The log_date is wrong!
解决方案
What are types of columns in MySQL? I suspect it's DATETIME. This type doesn't store "moment in time", it stores "hour on the clock", so can mean different moment in different time zones.
When MySQL driver writes java.util.Date to DATETIME column, it has to choose some time zone to write "hour on clock", because the same java.util.Date can mean different hour in different time zones. It stores hour as in MySQL server local time zone.
LocalDateTime does not have this problem, because it is like DATETIME. It represents hour on a clock, not moment in time, thus year/month/day-hour/minute/second are just stored in database. Notice in hibernate log LocalDateTime is given as is, while there is timezone ("CST") next to Date.
Generally, it's good practice to store time always in UTC, so use DateTime, not Date nor LocalDateTime. DateTime with jadira converter always stores/reads DATETIME as UTC.