如何解析含可选时间的字符串为LocalDateTime,无时间时设为当日23:59:59?
解决方案
可以通过DateTimeFormatter的可选模式功能同时适配两种格式,再根据解析后的类型补全日终时间,具体实现如下:
方法1:用模式字符串定义可选时间部分
直接在格式串中用方括号[]标记时间部分为可选,配合parseBest方法区分解析结果类型:
import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; public class DateParser { // 定义支持可选时间的格式化器 private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd[ HH:mm:ss]"); public static LocalDateTime parse(String input) { // 优先尝试解析为LocalDateTime,失败则解析为LocalDate TemporalAccessor temporal = FORMATTER.parseBest(input, LocalDateTime::from, LocalDate::from); if (temporal instanceof LocalDate) { // 仅日期时,设置为当日23:59:59 return ((LocalDate) temporal).atTime(23, 59, 59); } else { return (LocalDateTime) temporal; } } public static void main(String[] args) { System.out.println(parse("2022-03-03")); // 输出:2022-03-03T23:59:59 System.out.println(parse("2022-03-03 15:10:05")); // 输出:2022-03-03T15:10:05 } }
方法2:用DateTimeFormatterBuilder构建
如果需要更灵活的格式组合,可手动拼接可选部分,逻辑和方法1一致:
import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.TemporalAccessor; public class DateParser { private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() .append(DateTimeFormatter.ISO_LOCAL_DATE) // 固定日期部分 .optionalStart() // 标记后续为可选 .appendLiteral(' ') .append(DateTimeFormatter.ISO_LOCAL_TIME) // 时间部分 .optionalEnd() .toFormatter(); public static LocalDateTime parse(String input) { TemporalAccessor temporal = FORMATTER.parseBest(input, LocalDateTime::from, LocalDate::from); if (temporal instanceof LocalDate) { return ((LocalDate) temporal).atTime(23, 59, 59); } else { return (LocalDateTime) temporal; } } public static void main(String[] args) { System.out.println(parse("2022-03-03")); // 输出:2022-03-03T23:59:59 System.out.println(parse("2022-03-03 15:10:05")); // 输出:2022-03-03T15:10:05 } }
关键说明
- 格式串中的
[]表示内部模式为可选,解析时会自动适配有无时间部分的输入。 parseBest方法会按传入的类型顺序尝试解析,优先匹配LocalDateTime,若输入只有日期则匹配LocalDate。- 当解析结果为
LocalDate时,调用atTime(23,59,59)补全日终时间,转换为LocalDateTime。
内容的提问来源于stack exchange,提问作者Abhinash Jha
相关产品推荐
相关产品推荐

