SpringBoot时区转换规则

时区转换规则

前端传递时间字符串至mysql数据库,影响时区与格式的几种原因与不同参数的作用:

1. spring.jackson.time-zone

<!--spring.jackson.time-zone=Asia/Shanghai-->
spring.jackson.time-zone=GMT+7

jackson是SpringBoot中mvc默认的json序列化工具,如果要使用其他序列化工具,需要在java代码中配置。
spring.jackson.time-zone属性用于指定日期序列化为字符串和字符串反序列化日期时区。
在反序列化为时,表示字符串对应的时区,如果没有指定则默认为UTC时区。
如果字符串中包含时区,则以字符串中的时区为主
在反序列化时,根据指定时区+时间,转换为java服务器时区时间,然后存储展示在Date属性值中
在这里插入图片描述

2. Java实体中,Date类型

在java类中,当字段声明为:private Date claimDate;时。claimDate是一个没有时区信息的类型(如java.util.Date),它只表示一个瞬间,而不包含时区信息。当你打印这个日期时,它会被转换为你的系统默认时区,而不是jackson设置的时区。

3. mysql连接参数serverTimezone

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://xx.xx.xx.xx:3306/data_dev?useSSL=false&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&autoReconnect=true&rewriteBatchedStatements=true&serverTimezone=GMT%2B9
    username: XXX
    password: YYY

serverTimezone通常是客户端(如JDBC驱动)连接MySQL服务器时使用的连接参数。指的是客户端与数据库服务器端之间进行通信时,告诉客户端MySQL服务器所在的时区,以便客户端能够正确解析从服务器返回的日期和时间值。

  • 插入时,客户端会根据serverTimezone指定的时区,进行转换,转换后存储到数据库中。存储到数据库时,会根据字段是DateTime还是TimeStamp类型,进行不同处理。
    • 如果是DateTime类型,会将转换后的时间字符串直接存储到数据库中。
    • 如果是TimeStamp类型,会将转换后的时间字符串再根据time_zone进行再次的转换,然后再存储到数据库中。
  • 查询时,同样会根据serverTimezone指定的时区,进行转换,转换为java服务器所处时区,然后展示到java对应字段中。
    • 如果是DateTime类型,会以serverTimezone指定的时区为该字段的时区,将该时区字段转换为java服务器所处时区的时间,存储在java字段中。
    • 如果是TimeStamp类型,会根据time_zone时区转换为serverTimezone时区,然后再转换为java服务器所处时区的时间,存储在java字段中。

4. MySQL中的时区time_zone

system_time_zone     CST
time_zone          +10:00

-- 查看当前会话的time_zone设置  
SHOW VARIABLES LIKE 'time_zone';  
  
-- 设置当前会话的time_zone  
SET time_zone = '+10:00';

time_zone是MySQL服务器的系统变量,用于设置当前会话的时区。这个设置会影响MySQL服务器如何解释和显示日期和时间值。time_zone影响的是数据库层面的数据展示与存储。
它决定了在会话中使用的日期和时间函数(如NOW(), CURDATE(), CURTIME()等)返回值的时区。
time_zone是一个会话级别的变量,因此每个会话都可以有自己的时区设置。

  • 如果是DateTime类型,会将字符串直接存储到数据库中,默认时区是time_zone
  • 如果是TimeStamp类型,MySQL会根据当前系统的时区将Timestamp类型的值转换为UTC时间进行存储。在读取时,MySQL会根据当前时区将UTC时间再转换回相应的时间。

time_zone是MySQL服务器的系统变量,用于设置当前会话的时区;
serverTimezone是客户端连接参数,用于指定MySQL服务器的时区。
在开发时,建议将serverTimezone时区与time_zone时区保持一致,避免造成时区错乱。

5. MySQL中的Date、DateTime、TimeStamp区别

- Date
	- 存储格式是:YYYY-MM-DD字符串
	- 与时区`time_zone`无关
- Time
	- 只存储时间部分(时、分、秒),
	- 与时区无关
- DateTime
	- 存储格式是:YYYY-MM-DD HH:MM:SS字符串,范围从1000-01-01 00:00:009999-12-31 23:59:59
	- 与时区无关
- TimeStamp
	- 存储格式是:32位整数存储的UNIX时间戳。展现形式YYYY-MM-DD HH:MM:SS,范围从1970-01-01 00:00:01 UTC2038-01-19 03:14:07 UTC- 与时区有关,更换`time_zone`后,返回值会不同。存储时,MySQL会自动将日期和时间从当前时区转换为UTC进行存储;检索时,再从UTC转换回当前时区。

在选择使用哪种类型时,应根据具体的应用场景和需求来决定。如果需要存储时区相关的日期和时间信息,或者需要自动更新和记录时间戳,那么TIMESTAMP可能是更好的选择。而如果只需要日期信息或者具体的日期和时间(不考虑时区),那么可以选择DATE或DATETIME。

6、MyBatis中的JdbcType对时间影响

  • 数据库中的字段类型

claim_date	DATETIME
或者
claim_date	TIMESTAMP
都适用下面的情况
  • 前端传递参数

{
    "id":"ecacb1048c6f163bd58b3e541676e080",
    "statusId":"1",
    "claimPerson":"lixuemei",
    "claimDate":"2024-06-19T09:12:02.950Z"
}
  • MyBatis文件

	<!-- 更新数据 -->
    <update id="claim" parameterType="com.xx.xx.xx">
        UPDATE lc_proceeds_certificate
        SET
        `claim_person` = #{claimPerson,jdbcType=VARCHAR},
        `claim_date` = #{claimDate,jdbcType=TIMESTAMP},
        <!-- `claim_date` = #{claimDate,jdbcType=DATE},-->
        `status_id` = #{statusId,jdbcType=VARCHAR}
        WHERE `id` = #{id}
    </update>

jdbcType 的主要作用是为了确保Java对象能够正确地被转换为JDBC所期望的类型,并发送给数据库,或者从数据库接收到的数据能够正确地被转换为Java对象。

在执行SQL时MyBatis会自动通过对象中的属性给SQL中参数赋值,它会自动将Java类型转换成数据库的类型。而一旦传入的是null它就无法准确判断这个类型应该是什么,就有可能将类型转换错误,从而报错。
要解决这个问题,需要针对这些可能为空的字段,手动指定其转换时用到的类型。

在MyBatis中对时间类型字段,设置不同的jdbcType会造成时间不同,
如:jdbcType=DATE则存储到数据库中的格式为年-月-日 00:00:00(2024-06-19 00:00:00);
jdbcType=TIMESTAMP则存储到数据库中的格式为年-月-日 时:分:秒(2024-06-19 17:12:02)

7. @JsonFormat、@DateTimeFormat、@JSONField区别

  • @JsonFormat
    • Jackson 库
    • SpringBoot中mvc默认的序列化工具
    • 定义 JSON 序列化/反序列化时的日期/时间格式。只对JSON起作用
    • 注解中如果不指定时区,默认使用时间字符串中的时区标识,或者使用spring.jackson.time-zone中配置的时区,如果都没有默认是UTC
    • SpringBoot中默认使用的序列化工具是Jackson,如果需要替换为FastJson需要自己手动修改配置。
  • @DateTimeFormat
    • Spring 框架
    • 用于 Spring MVC 的表单绑定,将时间字符串转换为Date类型。只处理表单formData等非JSON参数,对JSON不起作用。
    • 主要用于前端向后端传递参数时,指定格式
    • 不能设置时区,只是简单的将字符串转换为时间,时区为服务器所在时区,不进行时区转换
      • 没有time_zone属性,但是可以通过@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ssZ")中,带时区的格式指定字符串时区,如果不指定默认是服务器时区
  • @JSONField
    • FastJson库
    • 定义 JSON 序列化/反序列化时的日期/时间格式。只对JSON起作用
    • 没有time_zone属性,但是可以通过@JSONField(format = "yyyy-MM-dd HH:mm:ssZ")中,带时区的格式指定字符串时区,如果不指定默认是服务器时区
    • SpringBoot中默认使用的序列化工具是Jackson,如果需要替换为FastJson需要自己手动修改配置。

在使用时,可以将@JsonFormat与@DateTimeFormat搭配使用:

  • 因为前端传递到后端的参数,有可能是json形式也有可能是表单形式,所以针对不同形式需要不同的注解;
  • 在结果返回时,也就是后端传递结果到前端时,一般都返回json形式,那么需要使用@JsonFormat

所以在需要格式化时间字符串时可以结合使用,但是如果涉及到时区转换时,必须用到@JsonFormat。

8. java中date、LocalDateTime 区别

  • java.util.Date
    java.util.Date 类是Java中表示特定时刻的类,保存的信息是自1970年1月1日00:00:00 GMT(格林威治标准时间)以来的毫秒数。这个毫秒数是一个绝对时间,与时区无关。也就是说,无论在哪个时区,同一个Date对象内部的毫秒数都是相同的。
    虽然Date对象本身不包含时区信息,但当将Date对象使用toString()方法将其转换为字符串表示时,它通常会使用系统默认的时区来格式化日期和时间。这就是为什么在不同时区的机器上,同一个Date对象可能会输出不同的日期和时间字符串。
  • LocalDateTime
    LocalDateTime关注的是日期和时间的本地表示,不考虑时区,即不进行时区的转换,会根据字符串转换为对应的LocalDateTime类型,然后直接保存到java以及数据库中,忽略时区

9. ISO时间格式

  • 日期格式:
    yyyy-MM-dd
  • 时间格式:
    HH:mm:ss
  • 日期+时间格式:
    yyyy-MM-ddTHH:mm:ss
    T是日期和时间之间的分隔符。
  • 日期+时间+时区格式:
    yyyy-MM-ddTHH:mm:ssZ
    yyyy-MM-ddTHH:mm:ss+08:00
    使用Z表示协调世界时(UTC)。
    使用±hh:mm格式表示与UTC的偏移,如+08:00表示比UTC快8小时的时区,-05:00表示比UTC慢5小时的时区。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值