You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java EE JSONB序列化Date对象时日期自动减一天问题求助

解决JSONB序列化Date时日期偏移一天的问题

这个问题的核心根源是时区不匹配:Date本质是UTC时间戳,你用SimpleDateFormat解析日期时默认使用了本地时区,而JSONB序列化时又默认转换为UTC时区,一进一出的时区差就导致了日期显示偏移一天。

问题拆解

当你执行new SimpleDateFormat("yyyy-MM-dd").parse("2021-03-19")时,它会把字符串解析成你本地时区的2021-03-19 00:00:00。比如你在东八区(UTC+8),这个时间对应的UTC时间是2021-03-18 16:00:00。JSONB序列化Date时默认用UTC时区格式化,最终就输出了2021-03-18。

另外你后来添加时间的代码出现2020-12-19的错误,是因为格式字符串写错了:HH:MM:SS里的MM代表月份,不是分钟,SS是毫秒,不是秒,正确格式应该是yyyy-MM-dd HH:mm:ss。

解决方案

方案1:统一解析与序列化的时区

给SimpleDateFormat和JSONB都指定同一个时区(比如UTC,或者业务需要的特定时区),消除时区转换带来的偏移。

修改后代码:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import javax.json.bind.annotation.JsonbDateFormat;

public class MyDate {
    @JsonbDateFormat(value = "yyyy-MM-dd", locale = "en_US")
    private Date myDate;

    // Getter & Setter
    public Date getMyDate() {
        return myDate;
    }

    public void setMyDate(Date myDate) {
        this.myDate = myDate;
    }

    public static void main(String[] args) throws ParseException {
        // 解析时指定UTC时区
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date parsedDate = sdf.parse("2021-03-19");

        MyDate myDateObj = new MyDate();
        myDateObj.setMyDate(parsedDate);

        // JSONB序列化时也指定UTC时区
        JsonbConfig config = new JsonbConfig()
                .setProperty("jsonb.timezone", "UTC");
        Jsonb jsonb = JsonbBuilder.create(config);

        System.out.println(jsonb.toJson(myDateObj));
    }
}

运行结果:{"myDate":"2021-03-19"}

方案2:使用Java 8+的LocalDate(推荐)

如果你只需要存储日期(不需要时间和时区信息),Java 8引入的java.time.LocalDate是更合适的选择——它是无时区的纯日期类型,从根源上避免了时区转换问题,也更符合你想要的"强类型"需求。

修改后代码:

import java.time.LocalDate;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.annotation.JsonbDateFormat;

public class MyDate {
    @JsonbDateFormat("yyyy-MM-dd")
    private LocalDate myDate;

    // Getter & Setter
    public LocalDate getMyDate() {
        return myDate;
    }

    public void setMyDate(LocalDate myDate) {
        this.myDate = myDate;
    }

    public static void main(String[] args) {
        MyDate myDateObj = new MyDate();
        myDateObj.setMyDate(LocalDate.parse("2021-03-19"));

        System.out.println(JsonbBuilder.create().toJson(myDateObj));
    }
}

运行结果直接是:{"myDate":"2021-03-19"}


内容的提问来源于stack exchange,提问作者Nicolas Baumann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:47:48