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+ 支持直接传入 LocalDateTime 和 LocalDate,但前提是驱动版本够新(如 PostgreSQL 42.2.5+、MySQL 8.0.21+),且不能混用旧 API(比如还用 java.sql.Timestamp.valueOf() 转换)。
- 写入
LocalDateTime到TIMESTAMP字段:PreparedStatement.setObject(1, LocalDateTime.now());
- 写入
LocalDate到DATE字段:PreparedStatement.setObject(2, LocalDate.now());
- 读取时也直接用
ResultSet.getObject(),别用getDate()或getTimestamp()—— 后者会强制转成java.util.Date,再转回LocalDateTime容易丢精度或出时区偏移
解析字符串时最容易踩的坑
LocalDate.parse() 和 LocalDateTime.parse() 默认只认 ISO 格式("2023-06-15"、"2023-06-15T14:30:45")。遇到中文格式(如 "2023年06月15日")或自定义分隔符(如 "2023/06/15 14:30:45"),必须显式传 DateTimeFormatter。
立即学习“Java免费学习笔记(深入)”;
错误示例:
LocalDateTime.parse("2023/06/15 14:30:45"); // 抛 DateTimeParseException
正确写法:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime.parse("2023/06/15 14:30:45", formatter);
注意:ofPattern() 中的字母大小写敏感(MM 是月,mm 是分),且不能用 YYYY 代替 yyyy —— 前者是“基于周的年”,跨年时可能错乱。
和老式 Date/Calendar 互转要留意什么
转换本身有标准方法,但容易忽略时区隐含行为:
-
LocalDateTime→Date:必须通过ZonedDateTime指定时区,否则默认用系统时区localDateTime.atZone(ZoneId.systemDefault()).toInstant().toDate()
-
Date→LocalDateTime:同理,Date.toInstant()得到的是 UTC 时间,再转必须指定目标时区date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()
- 千万别用
new Date().toInstant().atOffset(ZoneOffset.UTC).toLocalDateTime()—— 这会丢掉本地时区信息,导致夏令时或跨时区场景下时间偏差一小时
真正复杂的不是语法,是搞清你手里的字符串或数据库字段到底代表哪个时区的时间,以及业务逻辑是否允许隐式使用系统默认时区。










