SimpleDateFormat非线程安全,多线程复用会导致结果错乱,应局部新建、加锁或改用DateTimeFormatter;parse()抛ParseException主因是字符串与模式不匹配,如时区缺失、月份超限、yy解析四位年份等;安全格式化需用局部变量指定模式及时区;DateTimeFormatter不可变、线程安全、API清晰,是Java 8+推荐替代方案。

SimpleDateFormat 不是线程安全的,多线程环境下直接复用同一个实例会导致解析/格式化结果错乱——必须每次新建、局部使用,或加锁,或改用 DateTimeFormatter(推荐)。
为什么 SimpleDateFormat.parse() 会抛出 ParseException?
常见原因是传入字符串与模式不严格匹配,比如:
- 时区缺失但模式含
Z或z(如"yyyy-MM-dd HH:mm:ss Z"要求输入带+0800) - 月份写成
13却用了MM(它只接受 01–12) - 年份用
yy解析"2024"会当成 2020 年(yy只读两位) - 默认 lenient 模式开启时看似能解析,但关闭后(
setLenient(false))会立即报错
如何安全地格式化当前时间并输出为 "2024-05-21 14:30:45"?
用局部变量 + 明确模式,避免共享:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 如需固定时区
String formatted = sdf.format(new Date());
注意:HH 是 24 小时制,hh 是 12 小时制;mm 是分钟,MM 是月份——大小写敏感,写错就出错。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
替换方案:用 DateTimeFormatter 替代 SimpleDateFormat 的理由
DateTimeFormatter 是 Java 8+ 的标准替代,不可变、线程安全、API 更清晰:
- 预定义常量可直接用:
DateTimeFormatter.ISO_LOCAL_DATE_TIME - 自定义模式更直观:
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - 时区支持更自然:
LocalDateTime.now().atZone(ZoneId.of("Asia/Shanghai")).format(...) - 不会因共享导致诡异 bug,也不需要手动同步
旧项目若无法升级到 Java 8,至少把 SimpleDateFormat 声明为方法内局部变量,别塞进 static 字段里。
真正容易被忽略的是:哪怕你只在单线程里用,只要这个 SimpleDateFormat 实例被多个方法共享(比如作为工具类的 static 成员),就可能在将来被无意引入并发场景——隐患藏得深,修复成本高。

















