记一次踩坑记录:不喜欢看过程的铁子们直接滑到文章最后即可
背景描述:
近期做了一个跨境项目,系统用户分为国内和国外(主要是悉尼)两种,两部分的用户存在时差,并且悉尼实行冬夏令时制,由于初期开发及测试都是在国内进行,并没有发现什么问题,项目内部试运行期间,甲方提出,将所有时间统一由北京时间转换为悉尼时间,之后的一系列问题由此产生。
问题1:new Date获取的是北京时间
- 原因:服务器为云服务器,架在香港,java中new Date时,默认为服务器的本地时间,即北京时间。
- 解决:服务器修改时区为悉尼时区,之后new Date自动为悉尼时间,并且自动计算令时。
timedatectl set-timezone Australia/Sydney
问题2:数据库存的时间与查出来的时间不一致
- 原因:数据库链接属性中默认为北京时间
- 解决:将数据库链接属性的serverTimezone改为悉尼时区
jdbc:mysql://host:prot/db?characterEncoding=UTF-8&useUnicode=true&serverTimezone=Australia/Sydney
问题3:客户端传入的时间不一致,需统一转换为悉尼时间
- 原因:客户端的时间分为国内和悉尼两种,需转换
- 解决:使用@JsonFormat注解指定客户端传入的时区
@JsonFormat(timezone = "GMT+10", pattern = "dd/MM/yyyy")
private Date startTime;
问题4:存入数据库的时间会比实际时间早
- 原因:悉尼实行冬夏令时,例如北京时间为12点整,悉尼时间夏天为15点,冬天时间为13点,而GMT+10并不会考虑令时问题,所以是直接以北京时间加两个小时计算的,实际会存在误差
- 解决:JsonFormat指定时区为Australia/Sydney
@JsonFormat(timezone = "Australia/Sydney", pattern = "dd/MM/yyyy")
private Date startTime;
总结:
- @JsonFormat注解只是声明了客户端传入的时间要以哪个时区来计算,并不会影响new Date的结果,所以存入数据库时,要以服务器的时区为准,如果服务器时区与最终需要展示的时区并不一致,需要修改服务器时区
- GMT+10与Australia/Sydney存在区别,世界上使用GMT+10的国家和地区并不全部实行冬夏令时,所以需要指定为Australia/Sydney,才会计算令时。
- 中国历史上也曾实行夏令时,1990年之前出生的人,如果不使用Asia/Shanghai,实际出生日期会有问题