Java 8中LocalDateTime解析多日期格式时触发DateTimeParseException
问题原因及解决办法
一、错误原因分析
1. 移除空格后解析失败
字符串01/05/202403:41pm的日期与时间部分无分隔符,若你使用的格式字符串仍包含空格(比如MM/dd/yyyy hh:mm a),解析器处理完yyyy部分后,剩余的03:41pm无法匹配格式中的空格分隔规则,导致抛出“未解析文本”错误。正确的格式需要去掉时间部分的空格,且a(上午/下午标识)直接紧跟分钟。
2. 保留空格时解析失败
当你同时尝试MM/dd/yyyy和MM/dd/yyyy hh:mm a两种格式时,解析器可能优先匹配到MM/dd/yyyy,仅解析到01/05/2024就停止,剩余的 03:41 pm未被处理,因此触发异常。
二、解决办法
1. 单独处理两种格式
- 针对带空格的字符串
01/05/2024 03:41 pm,使用格式MM/dd/yyyy hh:mm a,确保开启大小写不敏感并指定en_US区域:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a", Locale.US) .parseCaseInsensitive(); LocalDateTime dateTime = LocalDateTime.parse("01/05/2024 03:41 pm", dateTimeFormatter);
- 针对无空格的字符串
01/05/202403:41pm,使用格式MM/dd/yyyyhh:mma:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyyhh:mma", Locale.US) .parseCaseInsensitive(); LocalDateTime dateTime = LocalDateTime.parse("01/05/202403:41pm", dateTimeFormatter);
2. 构建支持多格式的解析器
若要同时兼容纯日期、带空格的日期时间、无空格的日期时间三种情况,使用DateTimeFormatterBuilder构建可选格式:
DateTimeFormatter multiFormatter = new DateTimeFormatterBuilder() .parseCaseInsensitive() // 支持大小写不敏感解析am/pm .appendPattern("MM/dd/yyyy") // 基础日期格式 .optionalStart() // 可选的时间部分开始 .appendPattern("[ hh:mm a][hh:mma]") // 同时支持带空格和无空格的时间格式 .optionalEnd() // 可选的时间部分结束 .toFormatter(Locale.US); // 测试三种输入 LocalDate dateOnly = LocalDate.parse("01/05/2024", multiFormatter); LocalDateTime dateTimeWithSpace = LocalDateTime.parse("01/05/2024 03:41 pm", multiFormatter); LocalDateTime dateTimeNoSpace = LocalDateTime.parse("01/05/202403:41pm", multiFormatter);
3. 使用parseBest方法区分输入类型
如果你需要明确区分仅日期和带时间的输入,可使用parseBest方法:
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy", Locale.US); DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm a", Locale.US) .parseCaseInsensitive(); DateTimeFormatter dateTimeNoSpaceFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyyhh:mma", Locale.US) .parseCaseInsensitive(); String input = "01/05/2024 03:41 pm"; TemporalAccessor parsed = dateTimeFormatter.parseBest(input, LocalDateTime::from, LocalDate::from); if (parsed instanceof LocalDateTime) { System.out.println("解析为日期时间:" + parsed); } else if (parsed instanceof LocalDate) { System.out.println("解析为日期:" + parsed); }
内容的提问来源于stack exchange,提问作者S Hornby
相关产品推荐
相关产品推荐

