java中date无时区,仅表示utc毫秒数;json序列化默认输出utc格式(如"2024-05-20t12:34:56.789z"),本质毫秒值未变;推荐改用java.time包的zoneddatetime或offsetdatetime,并通过jackson配置统一时区(如asia/shanghai)及iso 8601带偏移格式。

Java 中 Date 对象本身不带时区信息,它只是自 Unix 纪元(1970-01-01 00:00:00 UTC)以来的毫秒数。当通过 JSON(如 Jackson)序列化时,默认会按 UTC 格式输出(例如 "2024-05-20T12:34:56.789Z"),这容易让人误以为“时间被改了”,其实是展示方式问题——本质毫秒值没变,只是序列化逻辑默认用了 UTC。
明确时区意图,优先用 java.time 替代 Date
Date 是遗留类,已不推荐用于新业务。应改用 ZonedDateTime 或 OffsetDateTime,它们自带时区/偏移信息,能清晰表达“这个时间属于哪个时区”。
- 接收前端带时区的时间(如
"2024-05-20T14:30:00+08:00")→ 用OffsetDateTime.parse()或ZonedDateTime.parse() - 存储或传输时想固定为东八区 → 转成
ZonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Shanghai")) - 序列化时保持该时区 → 配置 Jackson 使用
JavaTimeModule并设置序列化格式
Jackson 序列化时固定输出指定时区
即使你仍用 Date,也可通过 Jackson 控制输出格式(但不推荐长期依赖)。关键在于配置 ObjectMapper:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 禁用默认的 UTC 行为:
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) - 设置时区(影响
Date和Calendar):mapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")) - 这样
Date会被格式化为"2024-05-20T14:30:00.000+08:00"而非"...Z"
前后端约定:统一用 ISO 8601 带偏移格式
避免“谁转谁”的混乱。建议约定:
- 后端所有 JSON 时间字段统一输出带偏移格式(如
+08:00),不使用Z - 前端传入时间也必须带时区信息(如
"2024-05-20T14:30:00+08:00"),禁止只传"2024-05-20T14:30:00" - 服务内部统一用
Instant存储、ZonedDateTime展示,时区转换在边界做(如 Controller 入参解析时)
注意 Spring Boot 的自动配置陷阱
Spring Boot 2.0+ 默认启用 spring.jackson.time-zone=UTC,会覆盖你的手动设置。需显式覆盖:
- 在
application.yml中加:
spring:
jackson:
time-zone: Asia/Shanghai
date-format: yyyy-MM-dd HH:mm:ss.SSS - 若用
@JsonFormat注解,务必带上timezone = "GMT+8"或"Asia/Shanghai" - 验证方式:写个简单接口返回
new Date(),看响应是否含+08:00而非Z
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










