Java日期时间处理的核心错误在于类型误用和语义混淆:Date表示UTC时间戳而非日期,应改用LocalDate、ZonedDateTime、LocalTime;SimpleDateFormat非线程安全,需用DateTimeFormatter或ThreadLocal封装;Calendar加减天数须用DATE而非DAY_OF_WEEK;LocalDateTime无时区,持久化应选Instant或ZonedDateTime。

Java 日期时间处理的多数问题,不是代码写错了,而是用错了类型、搞混了语义、或者踩了老 API 的设计雷区。避开这些错误,关键不在“怎么写”,而在“为什么这么写”。
别拿 Date 当“日期”用
Date 表示的是一个精确到毫秒的时刻(UTC 时间戳),它不表达“2026年10月12日”这种纯日期概念,也不自带时区信息。但很多人用 new Date() 初始化后直接 toString(),看到“Sun Oct 12 14:32:00 CST 2026”就以为这是“今天”,其实这只是 JVM 默认时区对同一时间戳的本地化展示。
- 想表示“某一天”,用 LocalDate —— 它只含年月日,无时间、无时区
- 想表示“某个带时区的具体时刻”,用 ZonedDateTime —— 比如“2026-10-12T14:32:00+08:00[Asia/Shanghai]”
- 想表示“仅时间”,比如“下午2点32分”,用 LocalTime,而不是截取 Date 的小时分钟
别让 SimpleDateFormat 在多线程里共享
SimpleDateFormat 是典型的“内部可变 + 状态共享”类。多个线程共用一个 static 实例调用 parse() 或 format(),必然出现解析错乱、抛异常或返回错误时间字符串。
- 最稳妥:每次使用都 new 一个实例(适合低频场景)
- 更推荐:用 DateTimeFormatter 替代 —— 它是不可变的、线程安全的,且支持预编译模式
- 如果必须复用旧代码,至少用
ThreadLocal包一层,避免状态污染
别在加减天数时用 Calendar.DAY_OF_WEEK
这是高频误用:calendar.add(Calendar.DAY_OF_WEEK, 7) 并不是加 7 天,而是给“星期几”这个字段加 7 —— 周一(1)变成周一(8),实际行为未定义,可能跳到下周同一天,也可能完全错乱。
- 加减天数,明确用
Calendar.DATE或Calendar.DAY_OF_MONTH - 现代写法直接用 LocalDate.plusDays(7) 或 ZonedDateTime.plusDays(7),语义清晰、结果确定
- 需要跨周逻辑(比如“下周三”),用 TemporalAdjusters.next(DayOfWeek.WEDNESDAY)
别把 LocalDateTime 当完整时间点存储
LocalDateTime 是“没有时区的日期时间”,它就像一张纸写的“2026-10-12 14:32:00”,没人知道这是北京时间、纽约时间还是东京时间。把它存进数据库或传给前端,一旦系统跨时区运行,就会出现时间偏移。
- 持久化或传输时,优先用 ZonedDateTime 或 Instant(UTC 时间戳)
- 如果数据库字段是
TIMESTAMP WITHOUT TIME ZONE,那它本质上就是 LocalDateTime,需确保所有写入方约定统一时区(比如全用 UTC 写入) - 展示给用户时,再根据用户所在时区,用
withZoneSameInstant()转换
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











