java字符串格式化成日期_SimpleDateFormat与DateTimeFormatter指南

2026-02-02 00:00:00 作者:星降
应优先使用线程安全的DateTimeFormatter并设为static final,避免SimpleDateFormat多线程共享;严格校验格式、关闭宽松解析、对齐时区与数据库类型。

SimpleDateFormat 解析字符串时抛出 ParseException 怎么办

根本原因通常是输入字符串与模式不严格匹配,比如年份少写一位、空格或多了一个字母。它对格式极其敏感,且不是线程安全的——多线程共用同一个 SimpleDateFormat 实例是常见崩溃源头。

实操建议:

  • 每次解析都新建实例,或用 ThreadLocal 封装
  • 确认模式字符串和输入完全对齐:"yyyy-MM-dd" 不能匹配 "2025-1-1"(月份/日期缺零)
  • setLenient(false) 关闭宽松解析,避免把 "2025-13-01" 错误转成 2025-01-01
  • 注意时区:默认使用 JVM 本地时区,若需 UTC,得显式调用 setTimeZone(TimeZone.getTimeZone("UTC"))

DateTimeFormatter.parse() 返回 LocalDateTime 还是 ZonedDateTime

取决于你用的 pattern 和输入字符串是否含时区信息。没有时区字段(如 "HH:mm:ss""yyyy-MM-dd")时,parse() 默认返回 LocalDateTime;若输入含 Z+0800 或时区名(如 "2025-05-20T14:30:00+08:00"),则必须用 ZonedDateTime.parse() 或指定带时区的 formatter。

实操建议:

  • DateTimeFormatter.ISO_OFFSET_DATE_TIME 解析带偏移的时间,别硬套 ISO_LOCAL_DATE_TIME
  • 想统一转成带时区的时间?先 parse 成 LocalDateTime,再用 .atZone(ZoneId.of("Asia/Shanghai"))
  • 自定义 pattern 时,XXX 匹配 +08:00XX 匹配 +0800X 匹配 +08,别混用

从字符串转日期后,为什么存进数据库时间不对

最常踩的坑是:Java 端用了 LocalDateTime(无时区),但数据库字段是 TIMESTAMP WITH TIME ZONE(如 PostgreSQL),JDBC 驱动会按 JVM 本地时区自动转换,导致值偏移。

实操建议:

  • 数据库字段类型和 Java 类型要对齐:DATELocalDateTIMESTAMPLocalDateTimeTIMESTAMP WITH TIME ZONEZonedDateTimeOffsetDateTime
  • 用 JDBC 4.2+ 时,直接传 OffsetDateTime.now(Zone

    Offset.UTC)
    ,别依赖 Timestamp.valueOf(LocalDateTime)
  • Spring Boot + MyBatis 中,确保配置了 spring.jackson.time-zone=UTCspring.jackson.date-format=yyyy-MM-dd HH:mm:ss,否则序列化可能悄悄加本地时区

性能对比:SimpleDateFormat vs DateTimeFormatter

DateTimeFormatter 是不可变且线程安全的,创建开销略高但复用无风险;SimpleDateFormat 创建快,但并发下必须加锁或隔离,实际吞吐反而更低。

实操建议:

  • 高频解析场景(如日志时间提取),把 DateTimeFormatter 声明为 static final,例如:private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
  • 不要在循环里 new SimpleDateFormat——哪怕只用一次,也比复用一个非线程安全实例更安全
  • 如果必须兼容 JDK 7,且无法升级,至少用 ThreadLocal 包一层,别图省事共享实例

真正麻烦的不是语法,而是时区、leniency、JDBC 类型映射这三块的隐式行为。它们不会报错,但会在某个凌晨三点让数据差八小时。

猜你喜欢

联络方式:

400 9058 355

邮箱:8955556@qq.com

Q Q:8955556

微信二维码
在线咨询 拨打电话

电话

400 9058 355

微信二维码

微信二维码