如何让DateTimeFormatter解析秒数占3位的异常格式时间戳
问题原因
直接使用MMM-dd-yy HH:mm:sss'Z'构建DateTimeFormatter会报错,核心原因是DateTimeFormatter的默认规则中,秒字段对应的模式字母s最多支持2位写法(对应00-59的秒值范围),连续写3个s会被判定为非法模式。你这里存储的3位数字是补了前导零的秒值(范围000-059),本质还是秒字段,不是毫秒,也不能直接套用毫秒字段SSS的解析逻辑。
可行方案
使用DateTimeFormatterBuilder手动指定秒字段的解析宽度,绕过模式字符串的长度限制,代码示例如下:
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; import java.util.Locale; public class TimeParser { public static void main(String[] args) { DateTimeFormatter formatter = new DateTimeFormatterBuilder() // 先拼接除了3位秒之外的固定格式 .appendPattern("MMM-dd-yy HH:mm:") // 手动指定秒字段为固定3位宽度,取值范围是秒的合法区间0-59 .appendValue(ChronoField.SECOND_OF_MINUTE, 3) // 拼接字面量Z .appendLiteral('Z') // 必须指定和存储时月份缩写匹配的Locale,比如存的是英文月份缩写就用ENGLISH,中文就用CHINA,否则会解析失败 .toFormatter(Locale.ENGLISH); // 测试样例:Jan-01-24 12:30:005Z 会被正确解析为2024-01-01T12:30:05Z } }
注意事项
- 不要直接将3位秒替换为毫秒模式
SSS,否则会把秒值错当毫秒解析,比如005会被识别为5毫秒,秒值变为0,得到完全错误的时间 - 如果存储的
Z代表UTC时区,可以在构建formatter时追加.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)配置,直接解析为带UTC时区的时间对象,避免时区偏差 - 历史脏数据解析完成后,建议统一回写为标准时间格式(比如ISO 8601格式),避免后续维护再遇到同类问题
内容的提问来源于stack exchange,提问作者needoriginalname
相关产品推荐
相关产品推荐

