Spring Boot Batch中CSV转H2库时LocalDateTime格式转换异常问题
问题:Spring Boot Batch CSV时间格式转换保留日期部分报错
使用Spring Boot Batch读取CSV文件并写入H2数据库时,CSV内时间格式为2000-08-15 19:07:46,希望仅保留日期部分2000-08-15。但将localDateTimeFormat方法中的DateTimeFormatter格式改为yyyy-MM-dd时,出现DateTimeParseException错误,提示无法解析含时间的文本。
错误信息
java.time.format.DateTimeParseException: Text '1999-01-25 13:08:57' could not be parsed, unparsed text found at index 10 at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2109) ~[na:na] at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:2008) ~[na:na] at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:494) ~[na:na] at com.example.batchprocessingcsvtodatabase.config.UserProcessor.localDateTimeFormat(UserProcessor.java:37) ~[classes/:na] at com.example.batchprocessingcsvtodatabase.config.UserProcessor.process(UserProcessor.java:26) ~[classes/:na] at com.example.batchprocessingcsvtodatabase.config.UserProcessor.process(UserProcessor.java:14) ~[classes/:na]
User实体类
public class User extends BaseEntity{ @Type(type = "org.hibernate.type.UUIDCharType") private UUID personId; private String firstName; private String lastName; private String email; @Enumerated(EnumType.STRING) private Gender gender; private String country; @JsonFormat(pattern="yyyy-MM-dd") private LocalDateTime birthday; private int age; }
UserProcessor处理器类
public class UserProcessor implements ItemProcessor<UserInput, User> { @Override public User process(UserInput userInput) throws Exception { User user = User.builder() .personId(UUID.fromString(userInput.getPersonId())) .firstName(userInput.getFirstName()) .lastName(userInput.getLastName()) .email(userInput.getEmail()) .country(userInput.getCountry()) .birthday(localDateTimeFormat(userInput.getBirthday())) .gender(userInput.getGender().equals("Male") ? Gender.MALE : Gender.FEMALE) .age(Period.between(localDateTimeFormat(userInput.getBirthday()).toLocalDate(), LocalDate.now()).getYears()) .build(); return user; } private LocalDateTime localDateTimeFormat(String birthday) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime formatDateTime = LocalDateTime.parse(birthday, formatter); return formatDateTime; } }
解决办法
核心原因
报错是因为用yyyy-MM-dd格式去解析包含时分秒的完整时间字符串,格式不匹配导致解析失败。必须先按CSV的原始格式解析,再处理日期部分。
方案1:解析完整时间后截断日期(保留LocalDateTime类型)
修改localDateTimeFormat方法,先解析完整时间,再将时分秒设为0:
private LocalDateTime localDateTimeFormat(String birthday) { // 按CSV原始格式解析完整时间 DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime fullDateTime = LocalDateTime.parse(birthday, fullFormatter); // 保留日期部分,时分秒置为00:00:00 return fullDateTime.with(LocalTime.MIN); }
方案2:截取日期字符串再解析(更高效)
直接截取原始字符串的前10位(日期部分),再解析为LocalDateTime:
private LocalDateTime localDateTimeFormat(String birthday) { // 截取前10位日期字符串 String datePart = birthday.substring(0, 10); DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 解析为LocalDate后转成LocalDateTime(时分秒默认0) return LocalDate.parse(datePart, dateFormatter).atStartOfDay(); }
优化建议:字段类型替换为LocalDate
如果业务中只需要日期,建议将实体类的birthday字段改为LocalDate类型,更贴合业务语义,简化后续处理:
// 替换原LocalDateTime字段 @JsonFormat(pattern="yyyy-MM-dd") private LocalDate birthday;
对应的处理器方法修改为返回LocalDate:
private LocalDate localDateFormat(String birthday) { DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); return LocalDateTime.parse(birthday, fullFormatter).toLocalDate(); }
计算年龄的代码也可以简化:
.age(Period.between(localDateFormat(userInput.getBirthday()), LocalDate.now()).getYears())
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

