simpledateformat解析字符串为date需严格匹配模式且线程不安全;常见parseexception因模式与输入不一致、分隔符错误、年份位数不符或默认严格模式拒绝非法日期;应避免共享实例,推荐threadlocal封装或java 8+ datetimeformatter。

SimpleDateFormat 能解析字符串为 Date,但必须严格匹配模式,且线程不安全——别在多线程环境里复用同一个实例。
为什么 parse() 会抛出 ParseException?
最常见原因是输入字符串和 SimpleDateFormat 的模式不一致。比如模式是 "yyyy-MM-dd",却传入 "2023/05/10" 或 "2023-05-10 14:30",都会失败。
- 检查年份位数:模式用
yy时,"23"可以;用yyyy时,"23"就不行 - 注意分隔符:模式中是
-,字符串里用了/或空格,直接报错 - 默认不宽松:即使日期逻辑合理(如
"2023-02-30"),默认也会拒绝——可通过setLenient(false)显式关闭宽松模式,但通常建议保持false防止隐式修正
如何安全地复用 SimpleDateFormat 实例?
不能直接在类字段或静态变量里共享一个 SimpleDateFormat 实例,尤其在 Web 应用或线程池中。它内部维护可变状态(如 calendar 字段),并发调用 parse() 或 format() 会导致结果错乱甚至 NullPointerException。
- 方法一:每次用都新建(适合低频场景)
new SimpleDateFormat("HH:mm:ss").parse("14:25:30") - 方法二:用
ThreadLocal封装private static final ThreadLocal<simpledateformat> TIME_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss"));</simpledateformat>取用时调TIME_FORMAT.get().parse(...) - 方法三:改用 Java 8+ 的
DateTimeFormatter+LocalDateTime/ZonedDateTime,线程安全且更清晰
SimpleDateFormat 解析后 Date 的时区怎么算?
Date 本身不存时区,只存自 Unix epoch 起的毫秒数;但 SimpleDateFormat 在解析时会按其 TimeZone 解释输入字符串。默认使用 JVM 本地时区,容易造成误解。
- 如果字符串含时区信息(如
"2023-05-10T14:30:00+0800"),模式需包含z或X,且SimpleDateFormat会据此调整时间戳 - 若字符串无时区(如
"2023-05-10"),而你希望按 UTC 解析,必须显式设置:SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");<br>sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - 否则,同一字符串在不同时区的机器上解析出的
Date毫秒值不同
真正麻烦的不是写对一行 parse(),而是确保模式、输入、时区、线程上下文四者始终对齐——漏掉任一环,问题就藏在看似正常的返回值里。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











