使用MM/dd/yyyy格式的SimpleDateFormat可解析带多余后缀的非法日期问题
问题成因
SimpleDateFormat的parse(String source)方法仅从输入字符串的起始位置匹配指定格式,只要前缀符合格式要求就会返回解析后的日期对象,剩余未匹配的字符会被直接忽略。你调用的setLenient(false)仅作用于日期值的合法性校验(比如禁止将13月、32日这类非法日期自动折算为合法日期),不会校验输入字符串是否被完整解析,因此"01/01/2021anything"的前缀匹配成功后就正常返回结果,不会抛出异常。
实现严格全匹配校验的方案
你可以使用parse的重载方法parse(String source, ParsePosition pos),通过比对解析结束的位置和输入字符串的总长度,判断是否存在多余的未解析字符,示例代码如下:
import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; public class DateValidateDemo { public static Date strictParseDate(String input, String pattern) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setLenient(false); ParsePosition pos = new ParsePosition(0); Date date = sdf.parse(input, pos); // 解析失败 或者 未完整解析整个字符串都视为格式非法 if (date == null || pos.getIndex() != input.length()) { throw new ParseException("Invalid date format: " + input, pos.getErrorIndex()); } return date; } public static void main(String[] args) throws ParseException { // 测试带多余字符的非法输入,会抛出ParseException strictParseDate("01/01/2021anything", "MM/dd/yyyy"); } }
注意:
SimpleDateFormat是非线程安全类,不要在多线程场景下作为共享变量复用,避免出现解析异常。
内容的提问来源于stack exchange,提问作者Arn
相关产品推荐
相关产品推荐

