SimpleDateFormat解析EEE MMM dd HH:mm:ss z yyyy格式偶发异常问题
异常原因
- 时区偏移量格式不匹配
SimpleDateFormat中z格式符对GMT类偏移量的要求是必须为带前导零的两位小时+冒号+两位分钟的格式,解析失败的GMT+1是单数字偏移量,不符合格式要求;而解析成功的GMT+05:30完全匹配格式规则,所以可以正常解析。 - 三字母时区缩写存在歧义
IST同时对应印度标准时间、爱尔兰标准时间、以色列标准时间等多个不同时区,SimpleDateFormat对三字母时区缩写的解析依赖运行环境的内置时区映射表,不同JDK版本、系统默认时区配置下映射规则不统一,很容易出现匹配失败的情况。而成功样例中的CST在你当前的运行环境中存在明确的映射规则,所以可以解析成功。
对应解决方案
- 方案1:兼容现有输入格式调整解析规则
调整格式符并开启宽松解析模式,兼容单数字偏移量和多义时区缩写:
如果单数字GMT偏移量还是无法解析,可以将格式符调整为SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH); sdf.setLenient(true);EEE MMM dd HH:mm:ss z Z yyyy,同时匹配两种时区格式。 - 方案2:使用Java 8+新增的
DateTimeFormatter(推荐)
新日期时间API不存在线程安全问题,对时区格式的兼容度更高,解析规则可明确配置:
该配置可以同时兼容单数字偏移量、带冒号的偏移量、三字母时区缩写三种格式。DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendPattern("EEE MMM dd HH:mm:ss ") .appendZoneText(TextStyle.SHORT) .optionalStart() .appendOffset("+H", "Z") .optionalEnd() .appendPattern(" yyyy") .toFormatter(Locale.ENGLISH); - 方案3:从数据源侧统一格式
要求输入方统一使用ISO 8601标准日期格式,或者统一使用四位数字偏移量的时区格式,从根源消除解析歧义。
内容的提问来源于stack exchange,提问作者Pavel Poley
相关产品推荐
相关产品推荐

