解决Date日期类型在本地和服务器中时区不匹配的问题

一、遇到一个非常奇怪的bug

在本地开发环境中,从前端传入一个日期字段 reviewDate(如 "2009-11-30"),后端接收并保存到数据库时是正确的。

但部署到服务器后,同样的请求传入 "2009-11-30",最终在数据库中却变成了 "2009-11-29"日期自动减少了一天

二、问题定位与根本原因

1. 使用类型:Date + @JsonFormat

原始代码如下:

    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private Date reviewDate;

此注解表示 Jackson 会按照默认时区将前端传来的字符串解析为 Date 类型。
问题在于:Jackson 默认使用 JVM 的时区来解析日期字符串。

2. 服务器与本地环境的时区不同

  • 本地环境运行在 GMT+8(中国标准时间)。
  • 服务器运行在 UTC(或其他非 GMT+8 的时区)。

三、为什么 @JsonFormat(timezone = "GMT+8") 没有解决问题?

虽然这能确保 Jackson 使用 GMT+8 来解析日期,但由于以下原因仍可能失败:

  • Java 中的 Date 是基于 UTC 时间戳的;
  • 如果数据库字段是 DATE 类型,并且数据库服务器运行在 UTC 时区,则仍然会把时间点解释为前一天;
  • 这意味着即使 Jackson 正确解析了日期,数据库层面的转换也会导致日期偏移

四、最终解决方案

改用 LocalDate 替代 Date

@JsonFormat(pattern = "yyyy-MM-dd")
private LocalDate reviewDate;
效果:
  • LocalDate 不包含任何时间信息和时区概念;
  • Jackson 不会对它进行时区转换;
  • 数据库字段为 DATE 类型即可正确保存;
  • 前后端传输一致,不再出现“少一天”问题。

五、建议扩展内容

如果你未来希望继续使用 Date 类型,推荐统一配置:

设置 Jackson 使用固定时区

@Configuration
public class JacksonConfig {
    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder()
                .timeZone(TimeZone.getTimeZone("GMT+8"));
    }
}

配置数据库连接串时区(以 MySQL 为例):

spring.datasource.url=jdbc:mysql://localhost:3306/db?serverTimezone=Asia/Shanghai

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值