LocalDate.now() 返回系统默认时区下的纯日期(yyyy-MM-dd),不带时间与时区,不可变且线程安全;本质是ISO日历日期,区别于Date的时间戳语义,推荐用于仅需“某一天”的业务场景。
localdate.now() 直接返回当前系统默认时区下的“纯日期”(年-月-日),不带时间、不带时区、不可变,是 java 8 引入的 java.time 包中专为日期建模设计的类。
LocalDate.now() 的本质和用法
它只关注日期本身,忽略小时、分钟、秒、毫秒以及时区信息。调用时会读取系统默认时区的本地日历日期:
- 例如系统时区是 Asia/Shanghai,且当前是 2024-06-15 23:59:59,
LocalDate.now()仍返回2024-06-15 - 它基于 ISO-8601 日历系统(公历),线程安全,所有方法都返回新对象(不可变)
- 若需指定时区,应使用
LocalDate.now(ZoneId.of("Asia/Shanghai")),否则默认用ZoneId.systemDefault()
与旧版 java.util.Date 的核心差异
Date 表面叫“日期”,实际是“时间戳”——它内部只存自 1970-01-01 00:00:00 UTC 起的毫秒数,本质是时刻点(instant),不是日历日期:
-
Date打印时会自动按 JVM 默认时区格式化显示(如Sat Jun 15 23:59:59 CST 2024),容易误以为它“有日期概念”,其实只是 toString() 的副作用 -
Date可变(setTime() 等方法会修改原对象),线程不安全;LocalDate所有操作都生成新实例 -
Date与日历逻辑耦合深(依赖Calendar类做年月日计算),易出错;LocalDate提供直观方法如plusMonths(1)、isBefore(other)、withDayOfMonth(1)
为什么推荐 LocalDate 替代 Date 处理日期业务
当你真正需要的是“某一天”(如生日、合同生效日、报表统计日),而非“某一刻”,LocalDate 更准确、更安全、更易读:
- 避免因时区或时间部分引发的边界问题(比如用
Date存“2024-06-15”,实际可能被序列化为 2024-06-15 00:00:00 UTC,在东八区显示成 2024-06-15 08:00:00,造成混淆) - 数据库映射更清晰:JDBC 4.2+ 支持直接用
LocalDate绑定DATE类型字段,无需手动转换 - 与现代框架(Spring Boot、Hibernate 5.2+)天然兼容,配置简单,不易出错
简单迁移提示
如果老代码用 Date 存日期(忽略时间部分),可这样转为 LocalDate:
- 从
Date→LocalDate:date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() - 从
LocalDate→Date(仅当必须兼容旧 API):localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toDate() - 日常开发中,新逻辑优先声明为
LocalDate,避免无意义的Date中间转换

















