Duration 是基于时间的时间段(如 “34.5 秒”),以秒和纳秒为核心存储单位,也支持分钟、小时、天(1 天 = 24 小时,无视夏令时)等单位访问,与日期维度的 Period 对应。
Duration 用于表示两个时间点之间的时间间隔,主要用于处理短时间间隔,支持正负值(正表示时间在未来,负表示时间在过去)。尤其适合需要精确到秒 / 纳秒的场景(如程序执行时间统计、定时任务等)。
由于 Duration 的取值范围超出了长整型(long)的存储能力,为解决这一问题,此类通过两个字段存储持续时间:一个长整型(long)字段表示秒数,一个整型(int)字段表示 “秒内的纳秒数”(该字段的值始终在 0 到 999,999,999 之间)。
注意,Duration 被建模为“有方向的时间段”,这意味着其值可能为负。使用时需注意与 Period 的区别(Period 用于处理日期差),并合理选择时间单位转换方法。
通过指定时间单位直接创建 Duration 实例,支持多种时间单位(从纳秒到天)。常用方法:
方法 | 说明 | 示例 |
ofNanos(long) | 创建纳秒级间隔 | Duration.ofNanos(1_000_000) → 1 毫秒 |
ofMillis(long) | 创建毫秒级间隔 | Duration.ofMillis(500) → 500 毫秒 |
ofSeconds(long) | 创建秒级间隔(可额外加纳秒) | Duration.ofSeconds(60, 500_000_000) → 60.5 秒 |
ofMinutes(long) | 创建分钟级间隔 | Duration.ofMinutes(30) → 30 分钟 |
ofHours(long) | 创建小时级间隔 | Duration.ofHours(2) → 2 小时 |
ofDays(long) | 创建天数间隔(按 24 小时计算) | Duration.ofDays(1) → 24 小时 |
注意:
所有 ofXxx 方法都是静态方法,直接通过 Duration 类调用。
参数为正数时表示正向间隔,负数时表示负向间隔。
内部以秒 + 纳秒存储,无论输入单位如何,最终都会转换为这两个值。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; public class DurationOfExample { public static void main(String[] args) { Duration twoHours = Duration.ofHours(2); Duration halfMinute = Duration.ofSeconds(30); Duration oneAndHalfSecond = Duration.ofSeconds(1, 500_000_000); // 1秒 + 500纳秒 System.out.println(twoHours); // PT2H(2小时) System.out.println(halfMinute); // PT30S(30秒) System.out.println(oneAndHalfSecond); // PT1.5S(1.5秒) } }
运行结果:
PT2H PT30S PT1.5S
计算两个时间点之间的间隔,返回一个 Duration 对象。两个参数必须是时间相关的 Temporal 类型(如 Instant、LocalTime、ZonedDateTime 等),且两个参数的类型必须兼容(例如不能一个是 LocalDate 另一个是 Instant)。
计算逻辑:
结果 = 结束时间 - 开始时间(end - start)。
若结束时间早于开始时间,返回负的 Duration(可通过 abs() 取绝对值)。
支持的时间类型:
推荐搭配 Instant(计算 UTC 时间间隔)、LocalTime(计算当天时间间隔)使用。
不支持 LocalDate(日期无时间信息,需用 Period 类)。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; import java.time.Instant; import java.time.LocalTime; public class DurationBetweenExample { public static void main(String[] args) { // 示例1:计算两个Instant之间的间隔(UTC时间) Instant start = Instant.parse("2025-09-19T10:00:00Z"); Instant end = Instant.parse("2025-09-19T12:30:00Z"); Duration interval = Duration.between(start, end); System.out.println(interval); // PT2H30M(2小时30分钟) // 示例2:计算两个LocalTime之间的间隔(当天时间) LocalTime morning = LocalTime.of(8, 30); LocalTime afternoon = LocalTime.of(15, 45); Duration workDuration = Duration.between(morning, afternoon); System.out.println(workDuration.toHours()); // 7(小时) // 示例3:结束时间早于开始时间(返回负间隔) Duration negativeDuration = Duration.between(end, start); System.out.println(negativeDuration); // PT-2H30M System.out.println(negativeDuration.abs()); // PT2H30M(取绝对值) } }
运行结果:
PT2H30M 7 PT-2H-30M PT2H30M
将 Duration 转换为总天数(向下取整)。
计算逻辑:总秒数 ÷ 86400(1 天 = 24×60×60 秒),结果向下取整。
注意:仅包含完整的天数,不足 1 天的部分会被舍弃。
Duration duration = Duration.ofHours(30); // 30小时 System.out.println(duration.toDays()); // 1(30小时 = 1天6小时 → 仅取1天)
将 Duration 转换为总小时数(包含天数折算的小时)。
计算逻辑:总秒数 ÷ 3600(1 小时 = 60×60 秒),结果向下取整。
注意:会将所有天数转换为小时后累加(1 天 = 24 小时)。
Duration duration = Duration.ofDays(2).plusHours(3); // 2天3小时 System.out.println(duration.toHours()); // 51(2×24 + 3 = 51小时)
将 Duration 转换为总分钟数(包含天数和小时折算的分钟)。
计算逻辑:总秒数 ÷ 60(1 分钟 = 60 秒),结果向下取整。
注意:会将所有天数、小时转换为分钟后累加。
Duration duration = Duration.ofHours(2).plusMinutes(30); // 2小时30分钟 System.out.println(duration.toMinutes()); // 150(2×60 + 30 = 150分钟)
获取 Duration 的总秒数(基础单位,包含所有时间折算)。直接返回内部存储的总秒数(包含天数、小时、分钟等所有单位折算)。例如:
Duration duration = Duration.ofMinutes(2).plusSeconds(30); // 2分30秒 System.out.println(duration.getSeconds()); // 150(2×60 + 30 = 150秒)
获取 Duration 中不足 1 秒的纳秒部分(仅表示小数部分),范围 0~999,999,999(1 秒 = 10 亿纳秒)。
注意:不包含完整的秒数,仅用于补充 getSeconds() 实现高精度表示。
Duration duration = Duration.ofSeconds(5, 750_000_000); // 5秒 + 750毫秒(750,000,000纳秒) System.out.println(duration.getSeconds()); // 5(总秒数) System.out.println(duration.getNano()); // 750000000(纳秒部分)
在当前 Duration 基础上增加指定单位的时间,返回新的 Duration 实例。常用方法如下:
方法 | 功能描述 | 示例 |
plusNanos(long) | 增加纳秒数 | duration.plusNanos(1_000_000) → 增加 1 毫秒 |
plusMillis(long) | 增加毫秒数 | duration.plusMillis(500) → 增加 500 毫秒 |
plusSeconds(long) | 增加秒数 | duration.plusSeconds(30) → 增加 30 秒 |
plusMinutes(long) | 增加分钟数 | duration.plusMinutes(15) → 增加 15 分钟 |
plusHours(long) | 增加小时数 | duration.plusHours(2) → 增加 2 小时 |
plusDays(long) | 增加天数(按 24 小时计算) | duration.plusDays(1) → 增加 24 小时 |
注意:
参数 amount 可以是正数(增加)或负数(等于减少,建议优先使用 minusXxx 实现减少)。
内部会自动处理单位转换(如增加 60 秒会转换为 1 分钟)。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; public class DurationPlusExample { public static void main(String[] args) { // 初始间隔:1小时 Duration duration = Duration.ofHours(1); // 增加30分钟 Duration plus30Minutes = duration.plusMinutes(30); System.out.println(plus30Minutes); // PT1H30M(1小时30分钟) // 再增加90秒(1分30秒) Duration plus90Seconds = plus30Minutes.plusSeconds(90); System.out.println(plus90Seconds); // PT1H31M30S(1小时31分30秒) // 增加1天(24小时) Duration plus1Day = plus90Seconds.plusDays(1); System.out.println(plus1Day.toHours()); // 25(总小时数) } }
运行结果:
PT1H30M PT1H31M30S 25
在当前 Duration 基础上减少指定单位的时间,返回新的 Duration 实例。常用方法如下:
方法 | 功能描述 | 示例 |
minusNanos(long) | 减少纳秒数 | duration.minusNanos(500_000_000) → 减少 0.5 毫秒 |
minusMillis(long) | 减少毫秒数 | duration.minusMillis(1000) → 减少 1 秒 |
minusSeconds(long) | 减少秒数 | duration.minusSeconds(45) → 减少 45 秒 |
minusMinutes(long) | 减少分钟数 | duration.minusMinutes(20) → 减少 20 分钟 |
minusHours(long) | 减少小时数 | duration.minusHours(1) → 减少 1 小时 |
minusDays(long) | 减少天数(按 24 小时计算) | duration.minusDays(1) → 减少 24 小时 |
注意:
参数 amount 为正数时表示减少对应时间,负数时等效于增加(建议优先使用 plusXxx 实现增加)。
若减少后结果为负数,会返回负的 Duration(可通过 abs() 方法取绝对值)。
示例代码:
import java.time.Duration; public class DurationMinusExample { public static void main(String[] args) { // 初始间隔:3小时 Duration duration = Duration.ofHours(3); // 减少1小时15分钟 Duration minus1h15m = duration.minusHours(1).minusMinutes(15); System.out.println(minus1h15m); // PT1H45M(1小时45分钟) // 再减少2小时(结果为负数) Duration negativeDuration = minus1h15m.minusHours(2); System.out.println(negativeDuration); // PT-15M(负15分钟) // 取绝对值 Duration absolute = negativeDuration.abs(); System.out.println(absolute); // PT15M(15分钟) } }
运行结果:
PT1H45M PT-15M PT15M
与 plus(Duration)/minus(Duration) 的区别:
plusXxx(long) / minusXxx(long) 直接按单位增加,更简洁(如 plusHours(2))。
plus(Duration) 用于累加另一个 Duration 对象(如 plus(Duration.ofHours(2)))。
// 初始间隔:3小时 Duration duration = Duration.ofHours(3); // 累加1小时15分钟 Duration minus1h15m = duration.plus(Duration.ofHours(1)).plus(Duration.ofMinutes(15)); System.out.println(minus1h15m); // PT4H15M(4小时15分钟) // 再累加2小时 Duration negativeDuration = minus1h15m.plus(Duration.ofHours(2)); System.out.println(negativeDuration); // PT6H15M(6小时15分钟)
这些方法使得 Duration 可以灵活地进行时间间隔的调整,适用于计算任务执行时间、调整超时设置等场景。
比较当前 Duration 与另一个 Duration 的大小关系,返回一个整数表示比较结果。
返回值规则:
正数:当前 Duration 大于参数 Duration
0:两个 Duration 相等
负数:当前 Duration 小于参数 Duration
比较逻辑:基于时间间隔的总长度(纳秒级精度),先比较秒数,秒数相同则比较纳秒数。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; public class DurationCompareTo { public static void main(String[] args) { Duration d1 = Duration.ofHours(2); Duration d2 = Duration.ofMinutes(120); // 2小时(与d1相等) Duration d3 = Duration.ofHours(1); // 1小时(小于d1) System.out.println(d1.compareTo(d2)); // 0(相等) System.out.println(d1.compareTo(d3)); // 1(d1 > d3) System.out.println(d3.compareTo(d1)); // -1(d3 < d1) } }
运行结果:
0 1 -1
判断当前 Duration 的时间间隔是否为 0 长度(即总时长为 0)。当 Duration 的总秒数和纳秒数均为 0 时返回 true,否则返回 false。适用于检查两个时间点是否完全相同、任务是否耗时为 0 等。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; import java.time.Instant; public class DurationIsZero { public static void main(String[] args) { // 场景1:显式创建0长度的Duration Duration zero = Duration.ofSeconds(0); System.out.println(zero.isZero()); // true // 场景2:两个相同时间点的间隔 Instant now = Instant.now(); Duration sameTime = Duration.between(now, now); System.out.println(sameTime.isZero()); // true // 场景3:非零长度的Duration Duration oneHour = Duration.ofHours(1); System.out.println(oneHour.isZero()); // false } }
运行结果:
true true false
判断当前 Duration 的时间间隔是否为 负值(即总时长小于 0)。当 Duration 的总时长小于 0 时返回 true,否则返回 false(包括 0 长度)。
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; import java.time.Instant; public class DurationIsNegative { public static void main(String[] args) { // 场景1:结束时间早于开始时间(负间隔) Instant earlier = Instant.parse("2025-09-19T10:00:00Z"); Instant later = Instant.parse("2025-09-19T12:00:00Z"); Duration negative = Duration.between(later, earlier); // later -> earlier 是反向 System.out.println(negative.isNegative()); // true // 场景2:正常正向间隔(非负) Duration positive = Duration.between(earlier, later); System.out.println(positive.isNegative()); // false // 场景3:0长度间隔(非负) Duration zero = Duration.ofSeconds(0); System.out.println(zero.isNegative()); // false } }
运行结果:
true false false
将当前 Duration 时间间隔乘以指定系数,返回一个新的 Duration 实例(原实例不变)。参数 factor 表示乘数(可以是正数、负数或零)。注意:
若乘数为正数,保持原间隔的正负性;若为负数,反转间隔的正负性
若乘数为零,返回表示 "零间隔" 的 Duration
内部通过对秒和纳秒分别乘以系数实现,可能导致精度溢出(超出范围时抛出 ArithmeticException)
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; public class DurationMultipliedBy { public static void main(String[] args) { Duration original = Duration.ofHours(2); // PT2H(2小时) // 乘以正数:时间翻倍 Duration doubled = original.multipliedBy(2); System.out.println(doubled); // PT4H(4小时) // 乘以负数:反转方向并缩放 Duration negative = original.multipliedBy(-3); System.out.println(negative); // PT-6H(-6小时) // 乘以零:零间隔 Duration zero = original.multipliedBy(0); System.out.println(zero); // PT0S(零秒) } }
运行结果:
PT4H PT-6H PT0S
将当前 Duration 时间间隔除以指定系数,返回一个新的 Duration 实例(原实例不变)。参数 divisor 表示除数(必须是非零值,否则抛出 ArithmeticException)。注意:
除法结果向下取整(截断小数部分)
若除数为负数,结果的正负性与原间隔相反
内部通过对总纳秒数进行除法运算实现
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; public class DurationDividedBy { public static void main(String[] args) { Duration original = Duration.ofMinutes(15); // PT15M(15分钟) // 除以正数:时间减半 Duration half = original.dividedBy(2); System.out.println(half); // PT7M30S(7分30秒) // 除以更大的数:向下取整 Duration divided = original.dividedBy(4); System.out.println(divided); // PT3M(3分钟,截断剩余3分钟) // 负数除数:反转方向 Duration negativeResult = original.dividedBy(-3); System.out.println(negativeResult); // PT-5M(-5分钟) } }
运行结果:
PT7M30S PT3M45S PT-5M
返回当前 Duration 的绝对值(将负间隔转为正间隔,正间隔保持不变)。注意:
仅影响间隔的正负性,不改变时间长度
对于零间隔,返回自身(仍为零)
常用于处理 Duration.between() 可能返回的负间隔情况
示例代码:
package com.hxstrive.java_date_time.duration; import java.time.Duration; import java.time.Instant; public class DurationAbs { public static void main(String[] args) { // 计算一个负间隔(结束时间早于开始时间) Instant start = Instant.parse("2025-09-19T10:00:00Z"); Instant end = Instant.parse("2025-09-19T08:00:00Z"); Duration negative = Duration.between(start, end); System.out.println(negative); // PT-2H(-2小时) // 取绝对值 Duration absolute = negative.abs(); System.out.println(absolute); // PT2H(2小时) // 正数间隔取绝对值保持不变 Duration positive = Duration.ofHours(3); System.out.println(positive.abs()); // PT3H(3小时) } }
运行结果:
PT-2H PT2H PT3H
内部以秒 + 纳秒存储,超过 Long.MAX_VALUE 秒会抛出异常。
multipliedBy() 可能因数值过大导致溢出(如 Duration.ofSeconds(Long.MAX_VALUE).multipliedBy(2))
dividedBy() 采用截断除法(非四舍五入)
toHours() 等方法返回的是总单位数(包含更小单位的折算),而 getHours() 仅返回小时部分(0-23)。
不能直接与 LocalDate 等日期类计算(需先转为 LocalDateTime)。
// 错误示例:LocalDate 没有时间信息,无法计算 Duration Duration.between(LocalDate.now(), LocalDate.now().plusDays(1)); // 编译错误
运行抛出如下错误:
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds at java.base/java.time.LocalDate.until(LocalDate.java:1636) at java.base/java.time.Duration.between(Duration.java:492)