接口查询时间与数据库不一致

问题

查询服务器中某 jar 包中的接口数据,得到其时间与数据库中的不一致,但是看 mybatis-plus 打印的日志时得知从数据库中查询的数据与数据库中是一致的。

原因

分析问题得知 mybatis-plus 打印出从数据库中查询的数据与数据库一致,表示问题应该是出现在服务器中。
已知数据库中存储的时间字段类型为datetime,在代码中该字段为java.util.Date类型,所以在查询成功后数据库中的datetime类型将转换为java.util.DateDate类型,eg:Thu Dec 26 07:54:41 CST 2024、Wed Dec 25 17:55:31 CST 2024。这是我们可以查看服务器中的时间以及时区。

datetime与java.util.Date

格式转换

  • MySQL datetime格式:MySQL中的datetime类型表示日期和时间的组合,格式为YYYY-MM-DD HH:MM:SS
  • Java Date类型:Java中的Date类型表示特定的瞬间,可以精确到毫秒。它本身不存储格式信息,格式通常是在将Date对象转换为字符串时通过SimpleDateFormat等类来指定的。

在转换过程中,MySQL的datetime数据通过JDBC驱动程序被读取为java.sql.Timestamp对象,该对象实际上是一个扩展了java.util.Date的类,增加了纳秒精度以及时区信息(尽管MySQL的datetime类型本身不存储时区信息)。然后,可以将Timestamp对象转换为Date对象,或者直接使用Timestamp对象(因为Timestamp是Date的子类)。

时区信息

  • MySQL层面:MySQL的datetime类型不存储时区信息。它表示的是UTC时间加上或减去一个固定的偏移量(这个偏移量在数据库服务器层面设置,但通常不影响datetime字段的存储和检索)。然而,在实际应用中,通常假设datetime字段表示的是数据库服务器所在时区的本地时间。
  • JDBC层面:当通过JDBC从MySQL检索datetime字段时,驱动程序通常会将检索到的值转换为Java的Timestamp对象。由于Timestamp内部使用UTC时间戳来表示时间,因此它不受数据库服务器时区设置的影响。但是,当将Timestamp对象转换为字符串或与其他时区相关的日期时间对象进行比较时,需要考虑时区信息。
  • Java层面:在Java中处理日期和时间时,可以使用TimeZone和SimpleDateFormat等类来指定时区。但是,在将MySQL的datetime字段转换为Java的Date或Timestamp对象时,通常不需要显式指定时区(因为datetime字段本身不存储时区信息)。然而,在将Date或Timestamp对象转换为字符串或进行其他时区相关的操作时,必须考虑时区信息。

实际转换过程

  • 从MySQL检索datetime字段:使用JDBC驱动程序连接到MySQL数据库,并执行SQL查询以检索datetime字段的值。检索到的值将被封装在java.sql.Timestamp对象中。
  • 转换为Java Date类型:如果需要,可以将Timestamp对象转换为java.util.Date对象(尽管这通常是不必要的,因为Timestamp是Date的子类)。
  • 处理时区信息:在处理日期和时间时,注意时区的影响。如果需要,可以使用Java的TimeZone和SimpleDateFormat等类来指定时区并进行相应的转换。

解决

查看当前时间以及时区:

date
Thu Dec 26 11:09:08 CST 2024

# 如若时间不正确,使用以下命令行修改时间
date -s "2024-xx-xx xx:xx:xx"

确保将数据存储进数据库时使用的是同一时区,如若不一致则修改时区方法如下:

sudo timedatectl set-timezone Asia/Shanghai		# 修改为CST

注意!!!修改成功之后一定要重启 jar 包,重启该接口所在的 jar 包,再次访问该接口即可显示正确时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值