ResolverStyle.STRICT 能真正拒绝“2023-02-29”等非法日期,通过 Java 时间引擎底层校验闰年规则和月份天数,需搭配 withResolverStyle(ResolverStyle.STRICT) 的 DateTimeFormatter 使用,并推荐先正则预筛再严格解析。

用 ResolverStyle.STRICT 能真正拒绝“2023-02-29”这类非法日期,不是靠正则或长度判断,而是靠 Java 时间引擎对日历规则的底层校验。
ResolverStyle.STRICT 对 2月29日的判定逻辑
它不只检查字符串是否“长得像”日期,而是把解析结果代入公历系统验证:年份是否闰年、该月是否有这一天。例如:
-
"2024-02-29"→ 合法(2024 是闰年,2月有29天) -
"2023-02-29"→ 抛DateTimeParseException(2023 平年,2月最多28天) -
"2000-02-29"→ 合法(能被400整除的世纪年仍是闰年) -
"1900-02-29"→ 非法(能被100整除但不能被400整除,不是闰年)
必须搭配严格模式的 DateTimeFormatter 使用
仅设 ResolverStyle.STRICT 不够,还要确保格式器本身不补零、不宽松:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- ❌ 错误写法:
DateTimeFormatter.ofPattern("yyyy-MM-dd").parse("2023-2-29")—— 默认仍按 LENIENT 解析,可能静默转成 2023-03-01 - ✅ 正确写法:
DateTimeFormatter.ofPattern("yyyy-MM-dd").withResolverStyle(ResolverStyle.STRICT) - 注意:模式中
MM和dd要求两位,所以"2023-2-29"会先因格式不匹配失败,不会走到日历校验阶段
校验时推荐配合 TemporalAccessor 或具体类型
直接 parse 到 LocalDate 最直观,异常明确:
立即学习“Java免费学习笔记(深入)”;
- 用
LocalDate.parse(str, formatter):成功即合法,抛异常即非法(含格式错、日历错) - 若只需判断不关心对象,可用
formatter.parseBest(str, LocalDate::from, LocalDateTime::from),但通常没必要 - 避免用
YearMonth.parse或LocalDateTime.parse校验纯日期字符串,类型不匹配会导致提前失败
生产环境建议加一层轻量预筛
Strict 模式虽准,但异常开销不小。高频场景可先用正则快速拦截明显非法输入:
- 比如长度不是 10(
yyyy-MM-dd)、含非数字非横杠字符、年份不在 0001–9999 范围等 - 预筛通过后再走
LocalDate.parse(..., strictFormatter) - 这样既保住日历级准确性,又减少 80%+ 的异常创建开销

















