在Java中LocalDate和LocalDateTime如何使用_Java时间处理新API解析

LocalDate与LocalDateTime的核心区别在于是否包含时间信息:前者仅含年月日,适用于生日等场景;后者含时分秒,适用于订单创建时间等需精确到秒的场景。

LocalDate 和 LocalDateTime 的核心区别在哪

关键看要不要带时间。如果只处理年月日(比如生日、合同生效日),用 LocalDate;如果必须精确到时分秒(比如订单创建时间、日志打点),就得用 LocalDateTime。两者都不含时区,也不带毫秒精度以外的纳秒(LocalDateTime 默认纳秒,但多数场景截断到毫秒就够了)。

常见错误是把 LocalDate.now() 直接塞进需要时间戳的数据库字段,结果报 SQLException: Cannot convert class java.time.LocalDate to java.sql.Timestamp —— 因为 JDBC 驱动不认 LocalDate 作时间类型。

怎么安全地和数据库交互

JDBC 4.2+ 支持直接传入 LocalDateTimeLocalDate,但前提是驱动版本够新(如 PostgreSQL 42.2.5+、MySQL 8.0.21+),且不能混用旧 API(比如还用 java.sql.Timestamp.valueOf() 转换)。

  • 写入 LocalDateTimeTIMESTAMP 字段:
    PreparedStatement.setObject(1, LocalDateTime.now());
  • 写入 LocalDateDATE 字段:
    PreparedStatement.setObject(2, LocalDate.now());
  • 读取时也直接用 ResultSet.getObject(),别用 getDate()getTimestamp() —— 后者会强制转成 java.util.Date,再转回 LocalDateTime 容易丢精度或出时区偏移

解析字符串时最容易踩的坑

LocalDate.parse()LocalDateTime.parse() 默认只认 ISO 格式("2025-06-15""2025-06-15T14:30:45")。遇到中文格式(如 "2025年06月15日")或自定义分隔符(如 "2025/06/15 14:30:45"),必须

显式传 DateTimeFormatter

错误示例:

LocalDateTime.parse("2025/06/15 14:30:45"); // 抛 DateTimeParseException

正确写法:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime.parse("2025/06/15 14:30:45", formatter);

注意:ofPattern() 中的字母大小写敏感(MM 是月,mm 是分),且不能用 YYYY 代替 yyyy —— 前者是“基于周的年”,跨年时可能错乱。

和老式 Date/Calendar 互转要留意什么

转换本身有标准方法,但容易忽略时区隐含行为:

  • LocalDateTimeDate:必须通过 ZonedDateTime 指定时区,否则默认用系统时区
    localDateTime.atZone(ZoneId.systemDefault()).toInstant().toDate()
  • DateLocalDateTime:同理,Date.toInstant() 得到的是 UTC 时间,再转必须指定目标时区
    date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()
  • 千万别用 new Date().toInstant().atOffset(ZoneOffset.UTC).toLocalDateTime() —— 这会丢掉本地时区信息,导致夏令时或跨时区场景下时间偏差一小时

真正复杂的不是语法,是搞清你手里的字符串或数据库字段到底代表哪个时区的时间,以及业务逻辑是否允许隐式使用系统默认时区。