时间类型不一致的问题 前端得到后端的时间数据相差了16个小时 存放进数据库的时间发现与当前系统时间相差了8个小时
这些问题都是时区的问题 对于Java中时区有4个 UTC GMT CSA Asia/shanghai 要知道UTC GMT 和东8区都是有8个小时的时差的。
首先,存放入数据库的时间与当前系统时间相差8个小时,是因为MySQL这些中间件大多默认的是UTC,然后再Java中用new Date(),获取的时间是由当前系统决定的,所以有8个小时的时差,解决方案就是去修改中间件的时区,这里提供的方法是修改配置信息,这里用的是docker容器,且使用了数据卷,所以直接进入mysql的数据卷,在_data目录下新建一个目录,目录名可以随便取,但是后缀必须是.cnf。
接着,由于后端在返回给前端数据时一般用到序列化,然而直接用springboot的默认序列化,采用的也是UTC,所以也有8个时差,加起来前端就16个小时的时差,所以要解决springboot的序列化问题,有三种方式:第一种加注解@JsonFormat 用里面的2个属性值 timezone=GWT+8 这里必须是GWT+8 不能写UTC+8,这是规定,不然识别不了,虽然这2者在数值上差不多;第二种方式是在配置文件里面写,提高复用性,第三种方式就是自定义序列化器 实现这个接口。
package com.atguigu.tingshu.common.config.date;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.SimpleFormatter;
/**
* ClassName: CustomerDateHandler
* Package: com.atguigu.tingshu.common.config.date
* Description:
*
* @Author 陈宇侨
* @Create 2025/5/11 15:05
* @Version 1.0
*/
@Component
public class CustomerDateHandler implements Jackson2ObjectMapperBuilderCustomizer {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
//1.创建时间模版对象
JavaTimeModule javaTimeModule = new JavaTimeModule();
//2.对时间格式进行序列化
javaTimeModule.addSerializer(Date.class,new DateSerializer(){
//自定义对时间类型做序列化操作
/**
*
* @param value :指的是序列化的对象里面Date类型的字段以及值
* @param g :json生成器:用来负责将数据输出到json中去
* @param provider :暂时用不到
* @throws IOException
*/
@Override
public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
// super.serialize(value, g, provider);
// 处理时间时区 处理日期时间格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
String format = simpleDateFormat.format(value);
g.writeString(format);
}
});
// 对时间格式进行反序列化
javaTimeModule.addDeserializer(Date.class,new DateDeserializers.DateDeserializer(){
/**
*
* @param p Json的解析器
* @param ctxt
* @return
* @throws IOException
*/
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String text = p.getText();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8"));
try {
Date parseDate = dateFormat.parse(text);
return parseDate;
} catch (ParseException e) {
throw new GuiguException(201,"时间格式不对,无法解析");
}
}
});
// 将时间模式注册到builder中
jacksonObjectMapperBuilder.modulesToInstall(javaTimeModule);
}
}