FastDateFormat解析非法日期未抛出异常,如何实现正确的日期合法性校验?
FastDateFormat解析非法日期未抛出异常,如何实现正确的日期合法性校验?
我太懂你这种踩坑的感受了!FastDateFormat和你之前用的SimpleDateFormat一样,默认都是宽松模式(lenient mode),遇到不合法的日期不会直接报错,反而会自动“脑补”成合理的日期——比如你输入的101.10.2010,它会把101天自动拆成3个月零9天(10月31天+11月30天+12月31天=92天,101-92=9),所以就变成了2011年1月9日,自然不会抛出异常,你的校验方法就返回true了。
下面给你两种解决方案,根据你的需求选就行:
方案一:给FastDateFormat开启严格模式
FastDateFormat其实支持关闭宽松模式,只是默认没开。你可以用它的Builder来创建实例,显式设置lenient(false),这样遇到非法日期就会直接抛出ParseException,你的校验就能正确返回false了。
修改后的代码示例:
String INCORRECT_DATE_1 = "101.10.2010"; String dtFormatString_104 = "dd.MM.yyyy"; @Test public void isValidDate() { // 用Builder创建严格模式的FastDateFormat实例 FastDateFormat formatter = FastDateFormat.builder() .pattern(dtFormatString_104) .lenient(false) // 关键:关闭宽松解析模式 .build(); try { final Date parse = formatter.parse(INCORRECT_DATE_1); } catch (java.text.ParseException e) { return false; } return true; }
方案二:改用Java 8+ 官方推荐的java.time API(更推荐)
既然你用的是Java 8或17,完全可以直接用JDK自带的java.time包下的日期时间类,它们不仅天生线程安全,设计也更合理,而且默认的解析逻辑更严格。
具体来说,你可以用DateTimeFormatter配合ResolverStyle.STRICT来实现严格校验,遇到非法日期会抛出DateTimeParseException,代码示例如下:
import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.ResolverStyle; String INCORRECT_DATE_1 = "101.10.2010"; String dtFormatString_104 = "dd.MM.yyyy"; @Test public void isValidDate() { // 创建严格模式的DateTimeFormatter DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dtFormatString_104) .withResolverStyle(ResolverStyle.STRICT); try { LocalDate.parse(INCORRECT_DATE_1, formatter); } catch (DateTimeParseException e) { return false; } return true; }
这里的ResolverStyle.STRICT会强制要求日期完全符合规则:
- 日期必须是当月的有效天数(比如10月最多31天,101肯定不合法)
- 月份必须在1-12之间
- 年份也必须是合法的数值
这种方案不需要依赖第三方库,是Java 8之后官方推荐的日期时间处理方式,完全避免了旧Date/SimpleDateFormat的各种坑,线程安全问题也根本不用操心。
总结
- 如果要继续用FastDateFormat,就通过Builder关闭宽松模式即可;
- 更推荐切换到java.time API,这是长期的最优解,适配你当前使用的Java版本,还能避免旧API的各种遗留问题。
备注:内容来源于stack exchange,提问作者Dred
相关产品推荐
相关产品推荐

