MySQL对时间的存储
MySQL用于存储时间的类型,以datetime和timestamp为代表。
datetime可以视为以字符串类型进行存储,包含年月日时分秒信息,但不包含时区。
如果调用 UNIX_TIMESTAMP 函数,先将日期字符串按当前会话的time_zone,转为UTC时间,再转为时间戳。因此,如果改变会话的time_zone,得到的时间戳就会发生变化。
使用JDBC的getTimestamp方法得到的时间戳,也会随会话的时区变化而变化。
如果使用datetime存储时间,则serverTimezone被视为该类型时间的时区,这意味着他的时区信息被记录在了连接参数中。如果数据库迁移,数据库服务器时区发生变化,则要保持serverTimezone不变。但这样会导致参数中的时区与数据库实际的时区不一致,看上去别扭。
timestamp可以视为以一个整数时间戳进行存储,是一个“绝对时间”,可以看做包含时区信息。
查询结果是先把时间戳转换为UTC时间,再转为对应时区的时间,然后将这个时间显示出来。因此,如果改变会话的time_zone,UNIX_TIMESTAMP 函数的值不会变,但是查询出来的以yyyy-MM-dd HH:mm:ss格式显示的时间会发生变化。
而JDBC的getTimestamp方法参数为timestamp类型的字段时比较奇怪,时间戳理应不变,但实测会随会话时区发生变化,无法理解。
调试发现,传来的数据似乎是yyyy-MM-dd HH:mm:ss格式而不是一个整数。也就是说,原本的时间戳被转为会话时区的时间。此时的Timezone就视为客户端的时区。
综上所述,如果是跨时区的业务,时间类型应该选用timestamp,serverTimezone设为客户端所在时区。