SimpleDateFormat解析异常:年份不同为何成功或抛出异常?
问题原因解析
1. 离奇年份的来源
SimpleDateFormat的解析逻辑存在非严谨特性:当输入字符串长度超过格式串指定长度时,它不会立即停止解析,而是会继续读取剩余字符,并将其作为额外数值,持续对已解析日期进行字段累加/溢出。
针对你的格式串ddMMyy,具体解析流程如下:
- 先解析前6位字符:
09(日)、01(月)、20(两位年,解析结果取决于JDK默认的两位年基准规则,通常对应1920或2020年)。 - 剩余的超长字符(如
23000000000)会被解析为连续数字,SimpleDateFormat会循环复用格式串的字段规则(日→月→年)重复设置这些数值。每一次设置都会触发Calendar的字段溢出机制:比如设置超过当月天数的日会自动进位到下一月,设置超过12的月会进位到下一年;而当设置极大的年份数值时,会因Calendar年份的int存储溢出,最终得到看似离奇的年份值(如70403584)。
简单来说,剩余的超长数字会被反复当作日、月、年字段设置,每一次设置都会让日期向未来跳跃极大跨度,最终年份因数值溢出变成异常大的正数。
2. 2023与2022输入的解析差异
当lenient=false时,SimpleDateFormat会严格校验每个字段的合法性:
- 输入
09012023000000000的剩余字符首段是23,作为“日”字段是合法的(1-31),后续的00作为“月”字段时,虽在严格模式下原本非法,但Calendar的溢出机制或解析器的特殊处理让解析得以继续,最终仅年份因多次溢出变得异常大。 - 输入
09012022000000000的剩余字符首段是22,看似合法,但后续字段设置过程中,某个数值触发了严格模式下的合法性校验(如字段数值超出合法范围且无法通过溢出修正),因此直接抛出ParseException。
这种差异本质是SimpleDateFormat非严谨解析逻辑的产物——它对超长输入的处理没有明确规范,导致不同输入的解析行为出现随机差异。
内容的提问来源于stack exchange,提问作者jqno
相关产品推荐
相关产品推荐

