如何用一个DateTimeFormatter解析带可选秒的yyyyMMddHHmmss格式时间?
问题:解析带可选秒的日期字符串失败
需要解析格式为yyyyMMddHHmmss的日期,其中秒(ss)部分是可选的,202308301000(12位)和20230830100005(14位)均为合法输入。
定义了如下格式化器:
private static final DateTimeFormatter INPUT_FORMATTER = new DateTimeFormatterBuilder() .appendPattern("yyyyMMddHHmm") .optionalStart() .appendPattern("ss") .optionalEnd() .toFormatter();
但解析带秒的字符串时抛出异常:
INPUT_FORMATTER.parse("202308301000"); // 执行正常 INPUT_FORMATTER.parse("20230830100005"); // 抛出异常
异常信息:
Exception in thread "main" java.time.format.DateTimeParseException: Text '20230830100005' could not be parsed at index 0
解决方案
问题根源在于appendPattern("yyyyMMddHHmm")的使用逻辑:该方法会将整个12位的模式作为一个完整单元匹配,当解析14位字符串时,解析器会先消耗前12位完成匹配,剩余的2位无法被后续的可选ss段处理,导致解析失败。
以下两种方法可解决该问题:
方式一:使用带可选段的简化模式字符串
无需借助DateTimeFormatterBuilder,直接在模式中用方括号[]标记秒部分为可选:
private static final DateTimeFormatter INPUT_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmm[ss]");
方式二:通过DateTimeFormatterBuilder逐个指定字段长度
如果需要更精细的字段控制,可通过appendValue明确每个字段的固定长度,并将秒字段设为可选:
private static final DateTimeFormatter INPUT_FORMATTER = new DateTimeFormatterBuilder() .appendValue(ChronoField.YEAR, 4) .appendValue(ChronoField.MONTH_OF_YEAR, 2) .appendValue(ChronoField.DAY_OF_MONTH, 2) .appendValue(ChronoField.HOUR_OF_DAY, 2) .appendValue(ChronoField.MINUTE_OF_HOUR, 2) .optionalStart() .appendValue(ChronoField.SECOND_OF_MINUTE, 2) .optionalEnd() .toFormatter();
两种方案均能同时正确解析12位(无秒)和14位(带秒)的日期字符串。
内容的提问来源于stack exchange,提问作者luki27
相关产品推荐
相关产品推荐

