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 ZONEZonedDate

    Time
    OffsetDateTime
  • 用 JDBC 4.2+ 时,直接传 OffsetDateTime.now(ZoneOffset.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 类型映射这三块的隐式行为。它们不会报错,但会在某个凌晨三点让数据差八小时。


# java  # ai  # yy  # 为什么  # spring  # spring boot  # jvm  # mybatis  # Static  # 封装  # date  # format  # timestamp  # 字符串  # 循环  # private  # 线程  # 多线程  # 并发  # postgresql  # 数据库  # 转成  # 复用  # 设为  # 会在  # 用了  # 自定义  # 要对  # 三点  # 再用 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  想要更高端的建设网站,这些原则一定要坚持!  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  香港服务器选型指南:免备案配置与高效建站方案解析  如何用免费手机建站系统零基础打造专业网站?  米侠浏览器网页背景异常怎么办 米侠显示修复  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  高性能网站服务器部署指南:稳定运行与安全配置优化方案  Laravel怎么上传文件_Laravel图片上传及存储配置  独立制作一个网站多少钱,建立网站需要花多少钱?  专业商城网站制作公司有哪些,pi商城官网是哪个?  如何在宝塔面板中修改默认建站目录?  中山网站制作网页,中山新生登记系统登记流程?  网站图片在线制作软件,怎么在图片上做链接?  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  Android okhttputils现在进度显示实例代码  Win11怎么恢复误删照片_Win11数据恢复工具使用【推荐】  Laravel如何配置任务调度?(Cron Job示例)  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  Win11应用商店下载慢怎么办 Win11更改DNS提速下载【修复】  Swift中swift中的switch 语句  如何快速搭建安全的FTP站点?  黑客入侵网站服务器的常见手法有哪些?  如何打造高效商业网站?建站目的决定转化率  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  如何用虚拟主机快速搭建网站?详细步骤解析  如何彻底删除建站之星生成的Banner?  音乐网站服务器如何优化API响应速度?  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  实例解析angularjs的filter过滤器  Laravel怎么实现API接口鉴权_Laravel Sanctum令牌生成与请求验证【教程】  Laravel路由怎么定义_Laravel核心路由系统完全入门指南  如何在企业微信快速生成手机电脑官网?  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  如何在七牛云存储上搭建网站并设置自定义域名?  Laravel怎么连接多个数据库_Laravel多数据库连接配置  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  Python自动化办公教程_ExcelWordPDF批量处理案例  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  如何在局域网内绑定自建网站域名?  晋江文学城电脑版官网 晋江文学城网页版直接进入  Laravel安装步骤详细教程_Laravel环境搭建指南  Laravel如何处理JSON字段的查询和更新_Laravel JSON列操作与查询技巧  googleplay官方入口在哪里_Google Play官方商店快速入口指南  Laravel如何实现多对多模型关联?(Eloquent教程)  Python进程池调度策略_任务分发说明【指导】  如何在Tomcat中配置并部署网站项目?