Duration
是 Java 8 引入的 java.time
包中的核心类,用于精确表示基于时间的时间量(如秒、纳秒)。它专门处理小时、分钟、秒和纳秒级别的时间间隔,适合高精度时间计算。
核心特性
- 时间单位
处理纳秒到天的转换(1 天 = 24 小时,不涉及日历日期)。 - 不可变且线程安全
所有修改操作返回新实例。 - 精确到纳秒
最高支持纳秒精度(1 秒 = 1,000,000,000 纳秒)。 - ISO-8601 标准兼容
字符串格式为PnDTnHnMn.nS
(如PT2H30M15.5S
)。
使用场景
场景 | 说明 |
---|---|
计算代码执行时间 | 测量方法运行耗时(替代 System.currentTimeMillis() ) |
超时控制 | 定义网络请求、任务执行的超时阈值 |
时间间隔计算 | 计算两个时间点(如 Instant )之间的间隔 |
时间单位转换 | 将分钟转换为秒、小时转换为纳秒等 |
调度任务 | 定义任务之间的固定延迟(如 ScheduledExecutorService ) |
关键 API 及用法
1. 创建 Duration 对象
// 通过时间单位创建
Duration d1 = Duration.ofSeconds(30); // 30 秒
Duration d2 = Duration.ofMillis(500); // 500 毫秒
Duration d3 = Duration.ofNanos(100_000); // 100,000 纳秒
// 通过时间点计算
Instant start = Instant.now();
// ... 执行操作 ...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
// 解析字符串 (ISO-8601)
Duration d4 = Duration.parse("PT2H10M30.5S"); // 2小时10分30.5秒
2. 获取时间值
long seconds = d1.getSeconds(); // 总秒数(整数部分)
int nanos = d1.getNano(); // 纳秒部分(0~999,999,999)
long millis = d1.toMillis(); // 转换为毫秒(推荐替代 getNano())
3. 运算操作
Duration d5 = d1.plusMinutes(15); // 增加 15 分钟
Duration d6 = d2.minusSeconds(10); // 减去 10 秒
Duration d7 = d3.multipliedBy(2); // 乘以 2
Duration d8 = d4.dividedBy(3); // 除以 3
4. 比较与判断
boolean isZero = d1.isZero(); // 是否为零时长
boolean isNegative = d1.isNegative(); // 是否为负(当结束时间早于开始时间)
int compare = d1.compareTo(d2); // 比较两个 Duration
完整案例演示
场景 1:计算代码执行时间
Instant start = Instant.now();
TimeUnit.SECONDS.sleep(2); // 模拟耗时操作
Instant end = Instant.now();
Duration duration = Duration.between(start, end);
System.out.println("执行耗时: " + duration.toMillis() + " 毫秒");
// 输出:执行耗时: 2000 毫秒
场景 2:定义任务超时阈值
Duration timeout = Duration.ofSeconds(5);
try {
CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(10); // 模拟超时任务
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result";
}).get(timeout.toMillis(), TimeUnit.MILLISECONDS); // 设置超时
} catch (TimeoutException e) {
System.err.println("任务超时!");
}
场景 3:时间单位转换
Duration dailyWork = Duration.ofHours(8);
System.out.println("每日工作分钟数: " + dailyWork.toMinutes()); // 输出 480
Duration shortBreak = Duration.parse("PT15M");
System.out.println("休息秒数: " + shortBreak.getSeconds()); // 输出 900
场景 4:时间区间运算
Duration taskTime = Duration.ofMinutes(45);
Duration breakTime = Duration.ofMinutes(15);
Duration totalTime = taskTime.plus(breakTime);
System.out.println("总时间: " + totalTime.toMinutes() + " 分钟"); // 输出 60
注意事项
- 日期无关性
Duration
仅处理时间量,若需处理日历日期(如月、年),使用Period
类。 - 负值处理
当end < start
时,Duration.between()
会产生负值,可通过abs()
取绝对值。 - 精度损失
toNanos()
/toMillis()
可能导致溢出(Long.MAX_VALUE
约 292 年)。 - 替代
TimeUnit
优先用Duration
代替TimeUnit
做时间运算(更直观且支持纳秒)。
总结
Duration
是处理精确时间间隔的理想工具,适用于:
- 高精度计时(纳秒级)
- 超时控制与调度
- 时间单位转换
- 时间区间运算
结合 Instant
、LocalTime
等时间类,可构建健壮的时间处理逻辑,彻底替代传统的 System.currentTimeMillis()
和 Date
计算。