Spring Boot中@JsonFormat标注的Date字段自动添加时间如何解决
解决java.util.Date反序列化后携带时间信息的问题
问题原因
java.util.Date类型本身存储的是精确到毫秒的时间戳,你看到的Sun Jul 05 05:30:00 IST 1998是Date的toString()方法按系统默认时区格式化后的输出结果。你当前加的@JsonFormat注解没有指定时区,Jackson默认使用UTC时区解析日期字符串,和你服务所在的IST时区存在时差,导致解析后出现非预期的时间部分。
解决方案(无需修改Date类型为LocalDate)
方案1:补全@JsonFormat注解的时区配置
直接在现有@JsonFormat注解中指定和你服务一致的时区即可解决时区偏移问题,示例如下:
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd", timezone = "Asia/Kolkata") public Date date;
该方案仅保证反序列化时的日期和传入一致,Date对象本身仍会保留时间部分(当前时区的0点),如果需要彻底清空时间部分可采用方案2。
方案2:自定义Date反序列化器,清空时间部分
自定义Jackson反序列化器,解析日期后主动将时分秒毫秒置为0:
- 首先编写自定义反序列化类:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; public class DateOnlyDeserializer extends StdDeserializer<Date> { private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); static { // 指定对应时区 DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata")); DATE_FORMAT.setLenient(false); } public DateOnlyDeserializer() { super(Date.class); } @Override public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { String dateStr = jsonParser.getText().trim(); try { Date parsedDate = DATE_FORMAT.parse(dateStr); // 清空时间部分 Calendar calendar = Calendar.getInstance(); calendar.setTime(parsedDate); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime(); } catch (ParseException e) { throw new RuntimeException("日期格式非法,请传入yyyy-MM-dd格式的字符串:" + dateStr); } } }
- 在date字段上添加反序列化器绑定注解:
@JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd", timezone = "Asia/Kolkata") @JsonDeserialize(using = DateOnlyDeserializer.class) public Date date;
方案3:SpringBoot项目全局配置
如果项目中大量存在此类只需要日期的Date类型字段,可以直接在项目配置文件中全局指定Jackson的日期格式和时区,无需单独给字段加注解:application.yml配置示例:
spring: jackson: date-format: yyyy-MM-dd time-zone: Asia/Kolkata
补充说明
java.util.Date本身没有时区属性,输出时的时间信息是调用toString()方法按JVM默认时区格式化的结果,只要确保Date对应的时间戳为当日0点,即可满足你仅保留日期的需求。
内容的提问来源于stack exchange,提问作者snacks
相关产品推荐
相关产品推荐

