SimpleDateFormat解析非法输入未抛出ParseException的异常行为咨询
问题
我使用如下方式调用SimpleDateFormat:
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS"); Date result = sdf.parse("20221114-12:34:56.789");
正常输入时能得到正确结果(输出:Mon Nov 14 12:34:56 CET 2022),但处理明显非法输入时出现异常行为:
123-20221114-12:34:56.789解析结果为Sun Feb 15 12:34:56 CET 72812320221114-12:34:56.789解析结果为Mon Nov 21 12:34:56 CET 1289
我预期这些情况应抛出ParseException,且输入时间戳格式无法修改。交叉验证时,输入abc-20221114-12:34:56.789可正常抛出ParseException,请问为何会出现这种差异?
原因分析
这是SimpleDateFormat的默认行为导致的,核心原因有两点:
宽松解析模式默认开启
SimpleDateFormat默认处于宽松解析模式,不会严格校验输入是否完全匹配格式,而是允许数字溢出、通过部分匹配调整日期:- 输入
123-20221114-12:34:56.789时,解析器先读取123作为年份,后续的2022会被当作月份和日期处理——月份超过12自动进位到年份,日期超过当月天数自动进位到月份,最终拼凑出一个合法但不符合预期的日期。 - 输入
12320221114-12:34:56.789时,解析器会把超长数字串按格式段拆分并处理溢出,最终得到不合理的日期结果。
- 输入
数字与字母的匹配逻辑差异
yyyyMMdd格式段要求匹配数字,当输入以字母abc开头时,解析器无法找到符合要求的数字,直接触发ParseException;但如果输入以数字开头,解析器会尽可能提取数字进行匹配,哪怕后续内容不符合格式,也会通过宽松模式调整出一个日期结果。
如果要让非法输入抛出异常,可以关闭宽松模式:
sdf.setLenient(false);
内容的提问来源于stack exchange,提问作者Csaba Faragó
相关产品推荐
相关产品推荐

