应根据业务是否需要时间部分选择:仅需日期用LocalDate,需精确到秒用LocalDateTime;二者不可变、线程安全,但不可混用;解析字符串须匹配格式,数据库交互推荐JDBC 4.2+原生支持,跨系统需警惕时区语义。

LocalDate 和 LocalDateTime 到底该选哪个
看业务是否需要时间部分。如果只关心“哪一天”,比如生日、合同生效日、请假日期,用 LocalDate;如果必须精确到秒甚至纳秒,比如订单创建时间、日志打点、定时任务触发时刻,就得用 LocalDateTime。二者都不可变、线程安全,但混用会出问题——LocalDate 加 1 天还是 LocalDate,而 LocalDateTime 加 1 天仍是 LocalDateTime,不能直接赋值或比较。
从字符串解析时最容易踩的坑
默认格式严格:LocalDate.parse("2024-05-20") 可以,但 LocalDate.parse("2024/05/20") 直接抛 DateTimeParseException。同理,LocalDateTime.parse("2024-05-20 14:30:00") 会失败,因为默认格式是 "yyyy-MM-dd'T'HH:mm:ss"(带 T)。
- 用预定义格式器:
LocalDate.parse("2024/05/20", DateTimeFormatter.ofPattern("yyyy/MM/dd")) - 用自定义格式器时注意大小写:
MM是月,mm是分,写反了会解析出错但不报异常(比如把 12 当成分) - 避免用
SimpleDateFormat转换再包装——多此一举且引入线程不安全隐患
和数据库交互时怎么映射
JDBC 4.2+ 原生支持 LocalDate 和 LocalDateTime,不需要转成 java.sql.Date 或 Timestamp。
- 写入:
ps.setObject(1, LocalDate.now())、ps.setObject(2, LocalDateTime.now()) - 读取:
rs.getObject("create_date", LocalDate.class)、rs.getObject("update_time", LocalDateTime.class) - MySQL 中字段类型建议对应:日期用
DATE,日期时间用DATETIME(不是TIMESTAMP,后者会隐式转时区) - MyBatis 3.4+ 默认支持,老版本需配置
TypeHandler,否则可能映射为 byte[] 或 null
别忘了时区这个隐形变量
LocalDate 和 LocalDateTime 都不含时区信息,它们只是“本地挂历上的时间”。这意味着:
立即学习“Java免费学习笔记(深入)”;
- 跨系统传输时,如果对方按不同时区解释,可能差半天——比如你传
LocalDateTime.of(2024, 5, 20, 12, 0),对方当成 UTC 解释,实际可能是北京时间 20 日 20:00 - 做时间计算(如“7 天后”)没问题,但涉及“当前时刻”或“服务器时间”判断时,应优先考虑
ZonedDateTime或Instant - 日志记录建议统一用
Instant.now(),而不是LocalDateTime.now(),避免排查问题时被本地时区干扰
真正难的不是怎么创建或格式化,而是想清楚:这个时间值,在业务语义里,到底代表“某地墙上挂钟的读数”,还是“宇宙中某个绝对瞬间”。选错类型,后期补时区逻辑的成本远高于初期多想两秒。










