DateTimeFormatter解析无分隔符毫秒时间失败的原因及修复方案
为什么DateTimeFormatter解析无分隔符的
yyyyMMddHHmmssSSS会失败?怎么修复? 这个问题其实是因为DateTimeFormatter和SimpleDateFormat对模式中连续数字字段的解析逻辑完全不同,我来给你拆解清楚:
问题根源
在SimpleDateFormat里,模式yyyyMMddHHmmssSSS是按固定长度截取来解析的:它会依次取前4位当年份,接下来2位月份,……,第13-14位当秒,最后3位当毫秒——完全不管字段之间有没有分隔符,只要长度对就没问题。
但DateTimeFormatter是基于时间字段语义来解析的:
ss代表的是SECOND_OF_MINUTE字段(合法范围0-59)SSS代表的是MILLI_OF_SECOND字段(合法范围0-999)
当这两个字段在模式里连写(没有分隔符)时,解析器会把ssSSS当成一个连续的数字串,尝试将其解析为秒字段的数值(包括小数部分)。比如如果你的时间字符串里秒部分是30,毫秒是123,那解析器会把30123当成秒的值,这显然远远超过了秒的合法范围,直接抛出DateTimeParseException。
修复方法
要让DateTimeFormatter正确解析这种无分隔符的格式,你需要明确告诉它每个字段的长度,避免它把秒和毫秒的数字混在一起。最可靠的方式是用DateTimeFormatterBuilder来构建格式化器:
// 构建自定义格式化器,明确指定秒和毫秒的固定长度 DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendPattern("yyyyMMddHHmm") // 先处理到分钟部分 .appendValue(ChronoField.SECOND_OF_MINUTE, 2) // 秒:固定2位 .appendValue(ChronoField.MILLI_OF_SECOND, 3) // 毫秒:固定3位 .toFormatter(); // 测试代码 LocalDateTime now = LocalDateTime.now(); String s = formatter.format(now); System.out.println(now); System.out.println(s); System.out.println(LocalDateTime.parse(s, formatter)); // 现在可以正常解析了
这种方式强制解析器按固定长度截取秒和毫秒的部分,完全复刻了SimpleDateFormat的行为,但又保留了DateTimeFormatter的类型安全和线程安全特性。
内容的提问来源于stack exchange,提问作者Martin Fernau
相关产品推荐
相关产品推荐

