前端传递时间字符串至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:00到9999-12-31 23:59:59
- 与时区无关
- TimeStamp
- 存储格式是:32位整数存储的UNIX时间戳。展现形式YYYY-MM-DD HH:MM:SS,范围从1970-01-01 00:00:01 UTC到2038-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"
}
<!-- 更新数据 -->
<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")中,带时区的格式指定字符串时区
,如果不指定默认是服务器时区
- 没有time_zone属性,但是
- @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小时的时区。