一、为什么需要统一时间处理
在后端开发中,时间处理经常出现问题,例如:
常见问题:
1 前端传来的时间解析失败
2 GET 参数时间解析失败
3 返回给前端的时间格式不统一
4 LocalDateTime 无法解析
5 时区错乱(+8 / UTC)
6 Jackson 返回时间戳
根本原因是:
SpringBoot 中时间处理是由多个组件协同完成的
主要涉及三个组件:
| 组件 | 作用 |
|---|---|
| SpringMVC | 处理请求参数 |
| Jackson | JSON 序列化 / 反序列化 |
| JDK 时间 API | Date / LocalDateTime |
二、SpringBoot 时间处理完整流程
在 Spring Boot 中,时间处理分为 三种场景。
| 场景 | 示例 | 处理组件 |
|---|---|---|
| GET 请求参数 | /test?time=2026-03-05 | SpringMVC |
| POST JSON | {time:"2026-03-05"} | Jackson |
| 返回 JSON | return object | Jackson |
完整流程:
请求 → Controller
GET参数
URL → SpringMVC → ConversionService → Java对象
POST JSON
JSON → Jackson → Java对象
返回JSON
Java对象 → Jackson → JSON
所以:
GET 参数 → @DateTimeFormat
JSON 解析 → @JsonFormat
三、SpringBoot 支持的时间类型
企业开发推荐使用 JDK8 时间 API。
| 类型 | 是否推荐 | 说明 |
|---|---|---|
| Date | 不推荐 | 老 API |
| Calendar | 不推荐 | 复杂 |
| LocalDate | 推荐 | 日期 |
| LocalTime | 推荐 | 时间 |
| LocalDateTime | 推荐 | 日期+时间 |
| Instant | 推荐 | 时间戳 |
推荐:
LocalDateTime
原因:
线程安全
API 更清晰
支持时区
四、常用时间注解
SpringBoot 时间解析常用两个注解。
@DateTimeFormat
作用:用于 SpringMVC 参数绑定
适用于:
GET
Query参数
Form表单
示例:
public class TestDate {
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
}
请求:
GET /test?time=2026-03-05 12:00:00
@JsonFormat
作用:用于 JSON 序列化 / 反序列化
由 Jackson 处理。
示例:
public class TestDate {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime time;
}
请求:
{
"time":"2026-03-05 12:00:00"
}
五、SpringBoot 默认时间格
SpringBoot 默认:LocalDateTime
返回:2026-03-05T12:00:00
因为:ISO-8601 标准
但企业通常要求:
yyyy-MM-dd HH:mm:ss
所以需要 全局配置。
六、全局时间格式配置
企业开发推荐:
统一全局时间格式
避免每个字段写注解
application.yml 配置
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
serialization:
WRITE_DATES_AS_TIMESTAMPS: false
作用:
| 配置 | 作用 |
|---|---|
| date-format | Date 类型格式 |
| time-zone | 时区 |
| WRITE_DATES_AS_TIMESTAMPS | 禁止时间戳 |
注意:
这个配置只影响 java.util.Date
不会影响:LocalDateTime
JDK8 时间全局配置
需要自定义 Jackson 配置。
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> {
JavaTimeModule module = new JavaTimeModule();
DateTimeFormatter dateTimeFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter dateFormatter =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter timeFormatter =
DateTimeFormatter.ofPattern("HH:mm:ss");
module.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(dateTimeFormatter));
module.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(dateTimeFormatter));
module.addSerializer(LocalDate.class,
new LocalDateSerializer(dateFormatter));
module.addDeserializer(LocalDate.class,
new LocalDateDeserializer(dateFormatter));
module.addSerializer(LocalTime.class,
new LocalTimeSerializer(timeFormatter));
module.addDeserializer(LocalTime.class,
new LocalTimeDeserializer(timeFormatter));
builder.modules(module);
builder.timeZone(TimeZone.getTimeZone("GMT+8"));
};
}
}
七、GET 请求时间全局配置
GET 参数由 SpringMVC 解析。
可以全局配置:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
registrar.setDateTimeFormatter(
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
registrar.registerFormatters(registry);
}
}
这样:
GET /test?time=2026-03-05 12:00:00
即可自动解析。
八、实体类示例
推荐写法:
public class TestDate {
private Integer id;
private LocalDateTime time;
}
Controller:
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/get")
public TestDate get(TestDate date){
return date;
}
@PostMapping("/post")
public TestDate post(@RequestBody TestDate date){
return date;
}
}
返回结果:
{
"id":1,
"time":"2026-03-05 12:00:00"
}
九、推荐规范
项目一般遵循以下规范:
-
时间类型
统一使用:
LocalDateTime禁止:
Date Calendar -
时间格式
统一格式:
yyyy-MM-dd HH:mm:ss -
时区
统一使用
GMT+8或者
UTC -
统一 JSON 序列化
JacksonConfig
十、常见时间坑
10.1 返回时间戳
错误:
1700000000000
原因:
WRITE_DATES_AS_TIMESTAMPS = true
解决:
WRITE_DATES_AS_TIMESTAMPS: false
10.2 LocalDateTime 无法解析
原因:
未配置 JavaTimeModule
解决:
JacksonConfig
10.3 GET 参数解析失败
错误:
Failed to convert value
原因:
没有 @DateTimeFormat
或未配置 Formatter。
10.4 时区错乱
表现:
数据库时间正确
接口返回时间 +8 小时
原因:
Jackson 默认 UTC
解决:
spring.jackson.time-zone=GMT+8
十一、时间处理架构
最终架构:
请求
│
▼
Controller
/ \
/ \
GET 参数解析 JSON解析
│ │
SpringMVC Jackson
ConversionService ObjectMapper
\ /
\ /
▼ ▼
Java对象
│
▼
返回JSON
│
▼
Jackson