时区问题

4 篇文章 0 订阅
1 篇文章 0 订阅

时区问题

前提认知

日期的显示与接收

简单来说,时间是long数字,加上时区才有意义。

时区问题(数据库的默认时区问题,数据库连接配置,前台显示的时区问题(jackson的配置),date转string的时区问题(系统的时区设置)
https://www.cnblogs.com/suiyueshentou/p/7798340.html

这个时区问题,主要出现的问题是,时区设置的问题,时区可以设置的地方有点多。

你有没有想过,为什么new date(),不同的地区,时间显示不同,其实也很简单,new date()里面拿到的其实就是1970年到现在的毫秒数,
而我们获取时间,显示都是毫秒转化过来,时区也不过是规定了转化的规则,这个new date的毫秒数是没被改变的,

那默认的时区从哪里读取的呢,从系统变量里读取的,也就是说你的new date()如果没错的话,大家的值都是一样的,但是因为设置的时区不同,导致显示不同。

第一点:数据库的时区,数据库的date类型,其实也是一个long类型的数字,然后转化成日期

但是数据库有个默认时区设置,然后让你连接到数据库可以查看数据库的时间

第二点:连接设置的时区,有些系统,说我存储到你的数据库的时区设置,我不用你的,你用我的,那你可以在你的连接上加上时区。

jdbc:mysql://192.168.0.206:3307/skf_ito?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&allowPublicKeyRetrieval=true&verifyServerCertificate=false&useSSL=false&serverTimezone=GMT%2B8&allowMultiQueries=true

这个意思就是说,我存数据库的时区是这样的。你爱怎么显示怎么显示,但是我传给你的date数据,是这个时区的

所以如果你的数据库时区是GMT的,然后你的连接是GMT+8的,那么你就会很奇怪,我传给数据库的时间是12-20 8:00 然后我用命令行去看发现,数据成12-20 00:00.但是我代码里的时间确是12-20 8:00.别担心,这个才是正常的。

第三点,序列化的时候的时区

在传输的时候,你序列化的时候,如果指定时区的时区不一致

你可能就发现差了几个小时。

这个也很好理解,你序列化后给我,可能就是long的数据,但是我要解析啊,long数字不能代表一个时间,你不指定,那我用我系统时区了啊。

但是如果两个系统时间不一致呢,那问题就来了。

第三点,date 转string的时区问题

我date只是long的数字,只有加上时间,我才知道你这个date指的是哪天,我才能给你string。

之前没指定也可以转化,都是系统变量的锅,帮你做了。

所以,stirng转date和date转string都是要指定时区的。

改变系统变量的时区,

要么linux设置时区(百度linux修改时区,linux里date命令可以看时间,看自己的时区)

要么jar包启动时候传入时区(sudo nohup java -Xms256m -Xmx512m -jar -Duser.timezone=GMT+08 $project --spring.profiles.active=test server.port= p o r t > > port >> port>>log_dir/$logname &)

数据库存入的时间这个读取的是jvm的时区设置,
解决方法是要么设置jvm的时区,也就是启动的时候设置时区,或者代码里固定写死启动的时候时区设置为哪个,

第二个问题是json显示的问题,数据库存的是date的类型,然后vo类也是date类的话,json没有date的类型数据,要转字符串,规则是什么?dae转json的话,spring会有默认的jason的设置时区,我们可以在yml设置时区。
https://www.cnblogs.com/konghou/p/4118770.html
https://www.cnblogs.com/suiyueshentou/p/7798340.html
https://blog.csdn.net/jiahao1186/article/details/97892583
https://blog.csdn.net/qq_42031483/article/details/100625564

问题排错

这天,发现一个bug,具体是这样的。服务A要传信息给服务B.然后发现服务A的时间到了服务B是时间差了一天。这是咋回事。

服务A读取用户输入的时间,存储到数据库,然后转信息的时候,读取数据库的时间,转json给服务b。服务b存储到数据库,然后显示到前台。

先看数据库

发现服务A用的数据库连接配置是GMT+8,然后服务B的数据库连接配置是GMT。

再看序列化传输

@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date opiDate;

服务A和服务B都没指定。

再看显示的时区指定


@JsonFormat(pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date opiDate;

服务B没指定

思考

服务A的数据是取一天,yyyy-MM-dd,所以他的时间存储到数据库可能就是12-20 00:00 ,然后他数据库连接的时区是GMT+8。

但是序列化传递给服务B的时候,没指定时区,那就是默认的时区。

这个时候也没问题,服务A传递给服务B的是,GMT+8 的12-20 00:00。

服务B序列化解析,得到时间,哦,时间是12-20 00:00.但是时区呢,不管了,就用我的GMT吧。

那就是GMT 12-19 16:00 .

但是我要的格式是yyyy-MM-dd。那你就是GMT 12-19 00:00

但是我的数据库连接是GMT,那你存到数据库的时间就是 GMT 的12-19 00:00

我读出来,也是GMT 的12-19 00:00

显示到前端(date转String),也用我默认的GMT的吧,12-19.

就这样,华丽丽的用户输入12-20 ,然后服务B就变成了12-19。

解决方案

指定序列化传输的时候的时区。

dto里的字段。

/** opi精准交期 只有货期查询转报价单的时候存在**/
@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date opiDate;

服务A指定序列化的时区,服务B反序列化的时候,也指定时区

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值