duration适用于纳秒级精确时长计算,如定时任务、超时控制;period适用于日历日期偏移,如“下个月今天”,二者不可隐式转换,选择依据是输入输出类型:instant用duration,localdate用period。

Duration适合算秒级以下的精确时长
Duration 表示的是基于时间单位(纳秒、秒、毫秒)的**固定长度**,比如“3小时15分钟20秒”,它不关心日历,只认时钟走过的物理时间。你拿它去加减 LocalDateTime 或 Instant 是安全的,因为底层全是纳秒计数。
常见错误现象:Duration.ofDays(30) 看起来像一个月,但实际就是 30 × 24 × 3600 秒 —— 和月份天数无关,也不随闰年变化。
- 用在定时任务间隔、超时控制、性能耗时统计等场景最稳妥
-
Duration.between(Instant, Instant)返回值可靠;但Duration.between(LocalDateTime, LocalDateTime)会忽略时区,可能出错 - 不能表达“下个月今天”这种语义,
plus(Duration)加到 LocalDate 上会抛UnsupportedTemporalTypeException
Period适合处理日历上的日期偏移
Period 表示的是年、月、日层面的**日历单位组合**,比如“2年3个月10天”。它依赖具体日期才能算出真实天数 —— 因为2月有28或29天,7月和8月天数不同,闰年也影响结果。
常见错误现象:用 Period.ofMonths(1) 加到 2023-01-31 上得到 2023-02-28(不是31号),这是按日历规则“滚动”出来的,不是简单加24×3600秒。
立即学习“Java免费学习笔记(深入)”;
- 必须配合 LocalDate / LocalDateTime 使用才有意义,
Period.between(LocalDate, LocalDate)才是典型用法 - 不能用于 Instant,
Instant.plus(Period)直接编译失败 - 跨时区计算时,先转成 LocalDate 再加 Period,否则时区偏移会干扰日历逻辑
别混着用:Duration + Period 不会自动转换
Java 不提供 Duration 和 Period 之间的隐式转换,也没有“多少天等于多少秒”的通用换算 —— 因为“一个月”到底多少秒根本不确定。
常见错误现象:想把 Period.ofDays(30) 当作 Duration.ofDays(30) 传给 Thread.sleep(),结果编译不过;或者手动调用 toTotalDays() 再乘 86400,却忽略了 Period 可能含年/月单位,toTotalDays() 仅对纯日单位有效。
-
Period.toDuration()只在不含年、月时才返回非 null,否则抛UnsupportedOperationException -
Duration.toDays()返回的是向下取整的完整天数,小数部分丢弃,不四舍五入 - 如果真需要近似换算(比如展示用),得先用
Period.normalized().getDays()拆解,再手动处理年月部分
选哪个?看你的输入和输出类型
判断依据非常直接:如果你操作的是 Instant 或需要纳秒精度,用 Duration;如果你在处理生日、合同截止日、报表周期这类和日历强相关的逻辑,用 Period。
容易被忽略的一点:LocalDateTime 是“无时区的本地时间”,它既不是 Instant 也不是纯日历 —— 对它做运算时,要先想清楚你想要物理时长(用 Duration)还是日历偏移(先转 LocalDate 再用 Period)。











