JAVA-解决冬夏令时引起的时间转换错误问题

记一次踩坑记录:不喜欢看过程的铁子们直接滑到文章最后即可

背景描述:

近期做了一个跨境项目,系统用户分为国内和国外(主要是悉尼)两种,两部分的用户存在时差,并且悉尼实行冬夏令时制,由于初期开发及测试都是在国内进行,并没有发现什么问题,项目内部试运行期间,甲方提出,将所有时间统一由北京时间转换为悉尼时间,之后的一系列问题由此产生。

问题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,实际出生日期会有问题
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容