DateTimeFormatter 是线程安全的,因其内部状态完全不可变,构造后格式模式、区域设置、时区等均固化,format() 和 parse() 不修改自身;推荐优先使用预定义常量或 ofPattern() 构建的共享实例。

DateTimeFormatter 是 Java 8 引入的 java.time 包中线程安全的日期格式化工具,替代了旧版非线程安全的 SimpleDateFormat。它本身不可变,所有实例(包括预定义常量和自定义构建)都可被多线程共享,无需额外同步或每次新建。
为什么 DateTimeFormatter 是线程安全的
DateTimeFormatter 内部状态完全不可变:格式模式、区域设置、时区等在构造时就已固化,后续调用 format() 或 parse() 不会修改其自身。这与 SimpleDateFormat 在解析时会修改内部日历字段、导致并发下数据错乱有本质区别。
常见误区:有人误以为“用了 DateTimeFormatter 就绝对不出错”,其实若混用可变对象(如手动修改传入的 LocalDateTime 实例,或在 formatter 中动态设置时区并复用),问题仍可能出现——但责任不在 formatter 本身。
推荐用法:优先使用预定义常量
Java 提供了多个静态常量,语义清晰、性能好、开箱即用:
-
DateTimeFormatter.ISO_LOCAL_DATE→ 2024-05-20 -
DateTimeFormatter.ISO_LOCAL_DATE_TIME→ 2024-05-20T14:30:45 -
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")→ 自定义常用格式(注意:该方法返回的 formatter 仍是线程安全的) -
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)→ 按 Locale 自动适配(如中文环境输出“2024年5月20日 下午2:30:45”)
自定义 Pattern 的注意事项
书写 pattern 字符串时需注意大小写和重复数,例如:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
-
yyyy表示 4 位年份;yy表示 2 位(如 24),不建议用于持久化存储 -
MM是月份(01–12);mm是分钟(00–59)——大小写敏感,写错会导致解析异常或静默错误 - 想显示星期几?用
EEEE(全称,如“星期一”)或EE(缩写,如“周一”),需配合Locale使用:DateTimeFormatter.ofPattern("yyyy-MM-dd EEEE").withLocale(Locale.CHINA) - 处理带时区的时间(如
ZonedDateTime)时,用XXX输出 "+08",XXXXX输出 "+08:00"
解析与格式化的典型代码示例
以下操作均无需加锁,可在高并发服务中直接复用 formatter 实例:
格式化:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");<br>
String s = fmt.format(LocalDateTime.now()); // → "2024-05-20 14:30:45"
解析:LocalDateTime t = LocalDateTime.parse("2024-05-20 14:30:45", fmt);
若输入可能含毫秒或时区,务必用匹配的 pattern,否则抛 DateTimeParseException。必要时用 try-catch 并提供明确错误提示,而不是静默失败。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










