前后端数据序列化和反序列化相关问题之日期和时间的处理

本文探讨了前后端处理时间时遇到的格式不一致问题,包括前端自定义转换工具、后端日期类的情况以及SpringBoot中的时间转换、序列化和反序列化。针对不同场景,提出了全局配置解决方案,确保统一处理字符串格式时间、时间戳以及不同的日期时间类。
摘要由CSDN通过智能技术生成

关键词:SpringBoot,jackson,@JsonFormat,@DateTimeFormat,LocalDateTime,LocalDate,LocalTime,Date

前言

前后端处理时间的过程转中,可能会遇到因前后端传递与解析时间格式不一致导致的各种问题,比如:

1. 前端往后端的方向:

  • 前端传字符串格式时间,后端用某一种时间类接收时报转换类型错误,无法从String转到某一种时间类

  • 前端传字符串时间戳,后端用某一种时间类接收时报转换类型错误,无法从String转到某一种时间类

前端往后端传json字符串,时间以时间戳方式传递,后端无法反序列化时间到某一种时间类

2. 后端往前端方向:

  • 后端往前端传字符串格式时间,前端可能需要自定义时间格式,接收时间格式字符串显然有一定的局限性

前端的日期类是Date,通过new Date(),可以接收时间戳和字符串时间(包含日期的时间概念),可以同过自定义工具输出自定义的时间格式。

前端自定义转换工具:

//来源基本值的拼接
var date = new Date(时间戳); //获取一个时间对象
​
/**
​
  1. 下面是获取时间日期的方法,需要什么样的格式自己拼接起来就好了
  2. 更多好用的方法可以在这查到 -> http://www.w3school.com.cn/jsref/jsref_obj_date.asp
     */
     date.getFullYear();  // 获取完整的年份(4位,1970)
     date.getMonth();  // 获取月份(0-11,0代表1月,用的时候记得加上1)
     date.getDate();  // 获取日(1-31)
     date.getTime();  // 获取时间(从1970.1.1开始的毫秒数)
     date.getHours();  // 获取小时数(0-23)
     date.getMinutes();  // 获取分钟数(0-59)
     date.getSeconds();  // 获取秒数(0-59)
​
// 再自定义方法进行拼接,如输出成 2022-03-23 13:45:56

1. 将时间戳转换成日期格式yyyy-MM-dd HH:mm:ss

// 时间戳转yy-MM-dd HH:mm:ss
TimeToStrDate(time_number) {
  var dd = new Date(time); // 13位时间戳
  var y = dd.getFullYear();
  var m = (dd.getMonth() + 1) < 10 ? '0' + (dd.getMonth() + 1) : (dd.getMonth() + 1);//获取当前月份的日期,不足10补0
  var d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate(); //获取当前几号,不足10补0
  var h = dd.getHours() < 10 ? '0' + dd.getHours() : dd.getHours();
  var n = dd.getMinutes() <10 ? '0' + dd.getMinutes() : dd.getMinutes();
  var s = dd.getSeconds() <10 ? '0' + dd.getSeconds() : dd.getSeconds();
  return y + '-' + m + '-' + d + ' ' + h + ':' + n + ':' + s;
}
​

例子

// 使用自定义的方法TimeToStrDate转换时间戳成字符串日期格式 yyyy-MM-dd HH:mm:ss
TimeToStrDate(1648055956520);
//'2022-03-24 01:19:16'

2. date格式转yy-MM-dd HH:mm:ss格式

// date格式转成yy-MM-dd HH:mm:ss
DateToStr(dd) {
  var y = dd.getFullYear();
  var m = (dd.getMonth() + 1) < 10 ? '0' + (dd.getMonth() + 1) : (dd.getMonth() + 1);//获取当前月份的日期,不足10补0
  var d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate(); //获取当前几号,不足10补0
  var h = dd.getHours() < 10 ? '0' + dd.getHours() : dd.getHours();
  var n = dd.getMinutes() <10 ? '0' + dd.getMinutes() : dd.getMinutes();
  var s = dd.getSeconds() <10 ? '0' + dd.getSeconds() : dd.getSeconds();
  return y + '-' + m + '-' + d + ' ' + h + ':' + n + ':' + s;
}
​
//如: Mon Nov 11 2019 20:15:12 GMT+0800 (中国标准时间) -> 2019-11-11 20:15:12

后端日期类情况

后端的日期类以数据库和后端语言的时间类来说,分别是:

数据库的时间类情形:

以MySQL数据库为例:

YEARTIMEDATEDTAETIMETIMESTAMP

类型名称 日期格式 日期范围 存储需求
YEAR YYYY 1901 ~ 2155 1 个字节
TIME HH:MM:SS -838:59:59 ~ 838:59:59 3 个字节
DATE YYYY-MM-DD 1000-01-01 ~ 9999-12-3 3 个字节
DATETIME YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 8 个字节
TIMESTAMP YYYY-MM-DD HH:MM:SS 1980-01-01 00:00:01 UTC ~ 2040-01-19 03:14:07 UTC 4 个字节

参考链接:

MySQL DTAETIME、TIMESTAMP、DATE、TIME、YEAR(日期和时间类型)

Java语言的时间类型有:

常用的有:

java.util包中的Date类,转换是需要注意时区设置

java8之后java.time包中的新时间类:LocalDateTime,LocalDate,LocalTime

也就是说:Java有两套日期和时间的API:

  • 旧的Date、Calendar和TimeZone;

  • 新的LocalDateTime、ZonedDateTime、ZoneId等。推荐使用新的API

参考链接:

廖雪峰官网java教程部分内容链接:日期与时间

综合各种考虑,具体问题具体分析,需求不同,选用的格式不同。

选用:

一般数据库选timestamp和datetime和date

java选择LocalDateTime,LocalDate,LocalTime,适当考虑Date

前后端为了统一起见,一般统一传时间戳,或统一传字符串格式时间

SpringBoot中时间转换和序列化及反序列化

在SpringBoot中:

  • 加注在类字段上的@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss"),只能作用与当前类的加注字段上,用于转换前端传来的字符串格式的字符串时间格式到某种时间类上。该注解也只能转换前端传来的非时间戳时间参数信息。

  • 加注在类字段上的@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8", shape = JsonFormat.Shape.STRING)注解,只能序列化和反序列化前端传来的非时间戳时间信息,在返回给前端json序列化和j解析前端传来的json数据反序列化成对象时起作用。

显然,遇到其他情形,局限性就显现出来了,怎么办呢?

嗯,办法还是有的,查看源码后,通过SpringBoot添加全局转换时间和序列化与反序列化的自定义配置,解决此问题。

我们来分情况,从序列化反序列化、时间转换两方面来解决。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值