Java 8 的 java.time API 因线程安全、不可变、语义明确而取代 Date 和 SimpleDateFormat;核心类按场景选用:LocalDateTime(本地时间)、ZonedDateTime(带时区)、Instant(UTC 时间戳)、LocalDate/LocalTime(分离日期或时间);字符串解析与格式化统一使用线程安全的 DateTimeFormatter;类型转换需显式处理时区;JDBC 4.2+ 原生支持 java.time 类型直接读写。

Java 8 引入的 java.time API(JSR-310)彻底取代了老旧、线程不安全的 Date 和 SimpleDateFormat,推荐用于所有新项目中的日期时间处理。它设计清晰、不可变、线程安全,且语义明确。
核心类怎么选?
根据使用场景选择合适类型:
-
LocalDateTime:只有日期和时间(无时区),适合记录本地业务时间(如订单创建时间) -
ZonedDateTime:带时区的完整时间,适合跨区域系统(如全球用户下单时间比对) -
Instant:UTC 时间戳(从 1970-01-01T00:00:00Z 开始的纳秒数),适合日志、数据库存储、系统间时间传递 -
LocalDate/LocalTime:仅日期或仅时间,适合生日、营业时段等分离场景
字符串 ↔ 时间对象:用 DateTimeFormatter
不再用 SimpleDateFormat,而是用线程安全、预定义或自定义的 DateTimeFormatter:
- 常用预定义格式:
DateTimeFormatter.ISO_LOCAL_DATE_TIME、DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - 解析字符串:
LocalDateTime.parse("2024-05-20 14:30:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) - 格式化输出:
localDateTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm")) - 注意:模式字母大小写敏感,
MM是月份,mm是分钟;yyyy表示四位年,YYYY是“周计年”,一般不用
不同时间类型之间怎么转换?
转换必须明确时区含义,不能随意强转:
立即学习“Java免费学习笔记(深入)”;
-
LocalDateTime → Instant:需指定时区,例如localDateTime.atZone(ZoneId.systemDefault()).toInstant() -
Instant → LocalDateTime:需指定时区解释,例如instant.atZone(ZoneId.of("Asia/Shanghai")).toLocalDateTime() -
LocalDateTime → ZonedDateTime:用atZone(ZoneId),如localDateTime.atZone(ZoneId.of("UTC")) - 避免直接用
new Date().toInstant()或Date.from(instant)—— 这些是兼容旧 API 的桥接方法,新代码应尽量全程使用java.time
与数据库交互(JDBC 4.2+)
现代 JDBC 驱动原生支持 java.time 类型,无需手动字符串转换:
- 写入:
PreparedStatement.setObject(1, localDateTime)、setObject(2, instant) - 读取:
ResultSet.getObject("create_time", LocalDateTime.class)、getTimestamp("time_col").toInstant()(若字段是TIMESTAMP且驱动较老,可先转为Timestamp再转Instant) - 数据库字段建议:用
TIMESTAMP WITH TIME ZONE存Instant或ZonedDateTime;用DATE或TIMESTAMP存LocalDate/LocalDateTime(需确保应用层统一按本地时区理解)


















