如何让SimpleDateFormat严格校验月份格式,解析非法字符串时抛出异常?
解决SimpleDateFormat解析超长月份字符串不报错的问题
这个问题我之前也碰到过,SimpleDateFormat的这种"过度容错"行为确实挺让人头疼的——哪怕你关掉了宽松解析,它还是会把0012这种超长字符串截断成12来解析,自然不会抛出异常。
为什么会出现这种情况?
SimpleDateFormat的设计本身就有不少反直觉的地方:当你使用MM模式时,它并不会严格校验输入字符串的长度,哪怕输入超过两位,它会自动截取有效部分(比如0012会被当成12处理)。而setLenient(false)只是禁用了日期合理性校验(比如不允许2月30日、13月这种),但对输入的长度没有严格限制,所以才会出现你看到的情况。
最优解决方案:使用Java 8+的DateTimeFormatter
Java 8引入的java.time包(JSR-310)是专门用来替代老旧的Date、SimpleDateFormat的,它的DateTimeFormatter默认就会做严格的格式校验,包括输入长度。
代码示例
import java.time.Month; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.format.ResolverStyle; public class StrictMonthParser { public static void main(String[] args) { // 创建严格模式的格式化器,显式指定ResolverStyle.STRICT(其实默认就是严格的) DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("MM") .withResolverStyle(ResolverStyle.STRICT); try { // 尝试解析超长字符串"0012" Month month = Month.parse("0012", monthFormatter); System.out.println("解析结果:" + month); } catch (DateTimeParseException e) { System.out.println("解析失败:" + e.getMessage()); // 控制台会输出:解析失败:Text '0012' could not be parsed at index 2 } } }
这段代码会直接抛出DateTimeParseException,完美符合你的需求。而且java.time下的类都是线程安全的,比SimpleDateFormat好用太多。
兼容旧代码:手动校验输入(不推荐)
如果因为项目限制必须使用SimpleDateFormat,那只能手动先对输入字符串做校验:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class StrictSimpleDateFormatFix { public static void main(String[] args) throws ParseException { String input = "0012"; SimpleDateFormat sdf = new SimpleDateFormat("MM"); sdf.setLenient(false); // 第一步:校验长度必须是2位 if (input.length() != 2) { throw new IllegalArgumentException("月份格式错误:必须是两位数字"); } // 第二步:校验数字是否在1-12之间 int monthValue; try { monthValue = Integer.parseInt(input); } catch (NumberFormatException e) { throw new IllegalArgumentException("月份格式错误:必须是数字"); } if (monthValue < 1 || monthValue > 12) { throw new IllegalArgumentException("月份格式错误:必须在1-12之间"); } // 最后再解析 Date date = sdf.parse(input); System.out.println(date); } }
这种方法虽然能解决问题,但代码冗余,而且还是依赖SimpleDateFormat的老旧实现,不如直接迁移到java.time省心。
内容的提问来源于stack exchange,提问作者Roland
相关产品推荐
相关产品推荐

