日期格式化处理
# 日期格式化处理
前言
在 Spring Boot 中,日期格式化的需求非常常见,涉及请求参数的日期格式化、请求对象属性的日期格式化、响应数据的日期格式化、以及全局统一的日期格式化配置,下面我将详细说明如何在不同场景中进行日期格式化处理.
# 1. 请求参数的日期格式化
# 1.1 使用 @DateTimeFormat
注解格式化请求参数
当我们通过 GET
请求传递日期参数时,默认情况下,Spring Boot 无法自动将 String
转换为 LocalDateTime
或 Date
。需要使用 @DateTimeFormat
注解来指定格式:
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
@RestController
public class DateController {
/**
* 接收带有日期格式的请求参数,并将其解析为 LocalDateTime
* @param startDate 请求中的开始日期
* @return 格式化后的日期
*/
@GetMapping("/api/date")
public String getDate(
@RequestParam("startDate") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startDate) {
// 返回日期的字符串形式
return "Received date: " + startDate.toString();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
关键点说明:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
:用于指定请求参数的日期格式,pattern
属性定义了日期的格式,例如yyyy-MM-dd HH:mm:ss
。这种方式适用于GET
请求的日期参数解析。- 适用场景:当请求参数为日期类型时,例如
@RequestParam
、@PathVariable
需要传递日期数据时,需要使用@DateTimeFormat
注解来指定解析格式。 - 注意事项:
@DateTimeFormat
只适用于解析请求参数中的日期,不适用于响应数据或请求体中的日期。
# 1.2 请求体中日期格式化的处理
如果日期数据是在请求体中传递的,比如在 POST
请求中,直接通过对象传递,则需要在接收对象的属性上使用 @JsonFormat
来控制日期格式。
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserRequest {
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime birthDate;
}
2
3
4
5
6
7
8
9
10
11
12
13
在控制器中:
@PostMapping("/api/user")
public String createUser(@RequestBody UserRequest userRequest) {
// 处理业务逻辑
return "User created with birth date: " + userRequest.getBirthDate();
}
2
3
4
5
关键点说明:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
:用于指定请求体中日期字段的格式,pattern
属性定义格式,timezone
属性用于指定时区。如果日期字段带有@JsonFormat
,在接收请求时会自动进行格式化。- 适用场景:适用于
POST
请求体中传递日期数据的场景,通过对象接收数据时控制日期格式。 - 注意事项:
@JsonFormat
注解不仅在请求体中生效,响应数据时也会自动按照指定格式返回日期。
# 2. 响应数据的日期格式化
# 2.1 使用 @JsonFormat
注解格式化响应数据
在返回响应数据时,如果需要指定特定的日期格式,可以在响应对象的日期字段上使用 @JsonFormat
注解:
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class UserDTO {
private Integer id;
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime updateTime;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在控制器中:
@GetMapping("/api/user/{id}")
public UserDTO getUser(@PathVariable Integer id) {
// 模拟查询用户信息
return userService.getUserById(id);
}
2
3
4
5
关键点说明:
@JsonFormat
注解:指定响应数据中日期字段的格式。无论是在请求体中还是在返回数据中,只要加了@JsonFormat
注解,日期都会按照指定格式自动格式化。- 适用场景:适用于返回响应数据时,需要格式化日期字段的场景,确保前端接收到的日期数据是符合预期格式的。
- 注意事项:
@JsonFormat
注解是全局配置中的例外。如果在全局配置了日期格式化,但某些字段需要特定的格式,可以使用@JsonFormat
覆盖全局配置。
# 3. 数据库查询时的日期格式化
# 3.1 使用 DateTimeFormatter
手动格式化查询结果
在从数据库查询数据时,可以使用 Java 的 DateTimeFormatter
来手动格式化日期。通常是在服务层进行处理。
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
@Override
public List<UserDTO> getUserList(int page, int size) {
// 查询分页数据
Page<User> userPage = new Page<>(page, size);
IPage<User> resultPage = userMapper.selectPage(userPage, new QueryWrapper<>());
// 创建日期格式化器
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 手动格式化日期字段
return resultPage.getRecords().stream().map(user -> {
UserDTO userDTO = new UserDTO();
userDTO.setId(user.getId());
userDTO.setName(user.getName());
userDTO.setCreateTime(LocalDateTime.parse(user.getCreateTime().format(formatter), formatter));
userDTO.setUpdateTime(LocalDateTime.parse(user.getUpdateTime().format(formatter), formatter));
return userDTO;
}).collect(Collectors.toList());
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
关键点说明:
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
:创建一个日期格式化器,用于格式化LocalDateTime
对象。- 适用场景:适用于从数据库查询数据后,在返回给前端之前对日期进行手动格式化。例如,查询结果中带有日期字段,且需要统一格式化返回时,可以手动格式化处理。
- 注意事项:这种方式更灵活,可以针对特定场景自定义格式。
# 4. 全局日期格式化配置
# 4.1 在 application.yml
或 application.properties
中配置
如果希望全局统一控制日期格式化,可以在配置文件中进行配置,这样就不需要在每个日期字段上添加 @JsonFormat
注解了。
application.yml 配置:
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
2
3
4
application.properties 配置:
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
2
关键点说明:
spring.jackson.date-format
:配置全局日期格式,适用于 JSON 数据的序列化和反序列化,包括请求和响应。spring.jackson.time-zone
:配置全局时区,确保日期在不同时区中表现一致。- 适用场景:适用于整个应用中统一控制日期格式的场景,减少重复配置。特别是当项目中大量使用日期时,可以通过全局配置简化格式化逻辑。
- 注意事项:全局配置的日期格式会自动应用于所有 JSON 数据,但如果某个字段需要特殊格式,仍然可以使用
@JsonFormat
覆盖全局配置。
# 5. 自定义日期转换器(高级用法)
如果需要更灵活的日期格式化处理,可以通过实现 Spring 的 Converter
接口来自定义日期转换逻辑。
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public LocalDateTime convert(String source) {
try {
return LocalDateTime.parse(source, DATE_TIME_FORMATTER);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid date format. Please use 'yyyy-MM-dd HH:mm:ss'");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
关键点说明:
Converter<String, LocalDateTime>
:实现 Spring 的Converter
接口,实现从String
到LocalDateTime
的自定义转换。适用场景:适用于复杂的日期转换逻辑,或者需要处理多种日期格式的场景。可以全局处理不同格式的日期请求。
注意事项:自定义转换器会自动应用于所有需要日期转换的地方,适合在项目中需要处理多种格式时使用。
# 6. 统一处理全局日期格式化
在某些场景中,可以通过控制器中的 @InitBinder
来统一处理日期格式化。
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import java.util.Date;
@RestController
public class GlobalDateController {
@InitBinder
public void initBinder(WebDataBinder binder) {
// 统一格式化请求参数中的日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
关键点说明:
@InitBinder
:在控制器层面统一处理日期格式化,特别适用于传统的Date
类型。SimpleDateFormat
用于指定格式,CustomDateEditor
用于绑定日期数据。- 适用场景:在需要统一处理某些特定控制器的请求日期时,这种方式特别有用。致。