登录
首页 >  文章 >  java教程

Java新时间API:LocalDate和LocalDateTime详解

时间:2026-02-02 15:47:35 149浏览 收藏

大家好,我们又见面了啊~本文《Java新时间API:LocalDate和LocalDateTime使用详解》的内容中将会涉及到等等。如果你正在学习文章相关知识,欢迎关注我,以后会给大家带来更多文章相关文章,希望我们能一起进步!下面就开始本文的正式内容~

LocalDate仅存年月日,LocalDateTime存年月日及时分秒,二者均无时区;需表示绝对时刻须用ZonedDateTime或Instant。

在Java里如何使用LocalDate和LocalDateTime_Java新时间API用法说明

LocalDate 和 LocalDateTime 的核心区别在哪

别一上来就套用,LocalDate 只存年月日(不带时分秒、不带时区),LocalDateTime 存年月日 + 时分秒(依然不带时区)。两者都不可变、线程安全,但如果你需要表示“某个时刻”,比如数据库写入时间戳或计算两个时间点的毫秒差,LocalDateTime 不够——它没时区信息,无法映射到真实世界的时间轴。这时候得升维用 ZonedDateTimeInstant

怎么从字符串解析成 LocalDate 或 LocalDateTime

parse() 最常见,但格式必须严格匹配默认格式,否则抛 DateTimeParseException。比如 LocalDate.parse("2024-05-20") 没问题,但 "20/05/2024" 就会炸。这时候要显式传 DateTimeFormatter

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse("20/05/2024", formatter);
  • LocalDateTime.parse("2024-05-20T14:30:45") 能直接解析 ISO 格式(含 T
  • 如果字符串只有日期没有时间,别硬塞给 LocalDateTime.parse(),会报错;先用 LocalDate.parse() 再调 atStartOfDay()
  • 中文格式如“2024年05月20日”必须自定义 DateTimeFormatter,且注意 是文字,要用 yyyy年MM月dd日,不能写成 yyyy-MM-dd

如何把 LocalDate / LocalDateTime 转成时间戳或旧 API 的 Date

它们本身不提供 getTime(),因为没时区。想转 java.util.Date 或毫秒值,必须先指定时区:

// LocalDate → Date(按系统默认时区的当天零点)
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());

// LocalDateTime → Date(按系统默认时区解释该时刻)
Date dt = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
  • 千万别用 localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli() 来“假装”得到 UTC 时间戳——这其实把你的本地时间强行当 UTC 解释了,结果错 8 小时(东八区)
  • 如果业务明确要求“所有时间按 UTC 存储”,那应该统一用 Instant 接收输入,再转成 LocalDateTime.ofInstant(instant, ZoneOffset.UTC) 展示
  • JDBC 4.2+ 支持直接 set LocalDateTimePreparedStatement,但底层驱动是否真正按 UTC 处理,取决于数据库连接参数(如 MySQL 的 serverTimezone=UTC

加减日期和跨月计算要注意什么

plusDays()minusMonths() 看似简单,但跨月逻辑容易掉坑。比如 LocalDate.of(2024, 1, 31).plusMonths(1) 得到的是 2024-02-29(不是 31 日),因为 2 月没有 31 号,Java 自动“退到当月最后一天”。类似地,plusYears(1) 遇到闰年 2 月 29 日也会回退。

  • withDayOfMonth(31) 强行设日期可能抛 DateTimeException(比如 2 月设 31)
  • 需要“每月固定日期”的场景(如每月 25 日扣款),建议用 TemporalAdjusters.dayOfMonthOfMonth(25),它会在目标月自动取有效最大日
  • Period.between(d1, d2) 返回的是“年月日”逻辑差,不是总天数;要总天数用 ChronoUnit.DAYS.between(d1, d2)
实际项目里最常出问题的,是把 LocalDateTime 当作带时区的时间来用,或者在跨系统传时间时混淆了“本地时间表达”和“绝对时间点”。这两者一旦混用,测试环境看着对,上线后时区一变就全乱。

到这里,我们也就讲完了《Java新时间API:LocalDate和LocalDateTime详解》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>