simpledateformat 默认宽松模式,需调用 setlenient(false) 在 parse/format 前启用严格校验,否则无效;严格模式下月份、日期、小时越界或星期不匹配均抛 parseexception;其非线程安全,推荐 threadlocal 或 java 8+ 的 datetimeformatter(默认严格且线程安全)。

在 Java 中,SimpleDateFormat 默认是宽松模式(lenient),比如把 "2023-02-30" 解析成 2023 年 3 月 2 日(自动进位)。调用 setLenient(false) 就能开启严格校验,让非法日期直接抛出 ParseException。
设置 setLenient(false) 的正确时机
必须在调用 parse() 或 format() 之前设置,否则无效。推荐在创建格式器后立即设置:
- 错误写法:先 parse 再 setLenient → 不起作用
- 正确写法:new SimpleDateFormat() → setLenient(false) → parse()
严格模式下会拒绝哪些输入
开启后,以下情况都会抛出 ParseException:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 月份超出 1–12(如 "2023-13-01")
- 日期超出当月天数(如 "2023-02-30"、"2023-04-31")
- 小时超出 0–23(
HH)或 1–12(hh) - 星期几与日期不匹配(如设为
yyyy-MM-dd E且 "2023-01-01 周二")
注意线程安全问题
SimpleDateFormat 本身不是线程安全的,即使设置了 lenient 也不行。多线程场景下建议:
- 每个线程使用独立实例(推荐)
- 用
ThreadLocal<simpledateformat></simpledateformat>包装 - 迁移到
java.time(如DateTimeFormatter+LocalDate.parse(),天然严格且线程安全)
替代方案:Java 8+ 更推荐用 java.time
DateTimeFormatter 默认就是严格模式,无需额外设置:
-
LocalDate.parse("2023-02-30", DateTimeFormatter.ISO_LOCAL_DATE)直接抛DateTimeParseException - 支持自定义模式:
DateTimeFormatter.ofPattern("yyyy-MM-dd").withResolverStyle(ResolverStyle.STRICT) - 无并发风险,语义更清晰
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










