Java Duration 类

Duration 类是 Java 8 引入的日期时间 API(java.time 包)中的一个重要类,用于表示时间间隔或持续时间。

Duration 类主要用于计算两个时间点之间的差异,或者表示一段特定的时间长度。


基本概念

Duration 类表示的时间间隔可以精确到纳秒级别。它主要用于处理基于时间的量(小时、分钟、秒和纳秒),而不涉及日期或时区的概念。

主要特点:

  1. 不可变性 - Duration 对象一旦创建就不能被修改
  2. 线程安全 - 可以在多线程环境中安全使用
  3. 精确度高 - 可以精确到纳秒级别
  4. 链式调用 - 支持方法链式调用

创建 Duration 对象

Duration 类提供了多种静态方法来创建 Duration 实例:

1. 通过时间单位创建

实例

// 创建一个持续2小时的Duration
Duration twoHours = Duration.ofHours(2);

// 创建一个持续30分钟的Duration
Duration thirtyMinutes = Duration.ofMinutes(30);

// 创建一个持续45秒的Duration
Duration fortyFiveSeconds = Duration.ofSeconds(45);

// 创建一个持续500毫秒的Duration
Duration fiveHundredMillis = Duration.ofMillis(500);

// 创建一个持续1000000纳秒的Duration
Duration oneMillionNanos = Duration.ofNanos(1_000_000);

2. 通过时间量创建

实例

// 创建一个持续1天2小时3分钟的Duration
Duration customDuration = Duration.ofDays(1).plusHours(2).plusMinutes(3);

3. 通过两个时间点计算

实例

Instant start = Instant.now();
// 执行一些操作...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);

4. 解析字符串创建

实例

// 从ISO-8601格式的字符串创建
Duration parsedDuration = Duration.parse("PT2H30M15S"); // 2小时30分钟15秒

常用方法

Duration 类提供了丰富的方法来处理时间间隔:

1. 获取时间值

实例

Duration duration = Duration.ofHours(2).plusMinutes(30);

long hours = duration.toHours();      // 2
long minutes = duration.toMinutes();  // 150
long seconds = duration.getSeconds(); // 9000
int nanos = duration.getNano();      // 0

2. 时间运算

实例

Duration d1 = Duration.ofHours(2);
Duration d2 = Duration.ofMinutes(30);

// 加法
Duration sum = d1.plus(d2);  // 2小时30分钟

// 减法
Duration diff = d1.minus(d2); // 1小时30分钟

// 乘法
Duration multiplied = d1.multipliedBy(3); // 6小时

// 除法
Duration divided = d1.dividedBy(2); // 1小时

3. 比较操作

实例

Duration d1 = Duration.ofHours(1);
Duration d2 = Duration.ofMinutes(90);

boolean isEqual = d1.equals(d2);      // false
int comparison = d1.compareTo(d2);    // -1 (d1 < d2)
boolean isNegative = d1.isNegative(); // false
boolean isZero = d1.isZero();         // false

4. 其他实用方法

实例

Duration duration = Duration.ofMinutes(90);

// 转换为其他单位
long hours = duration.toHours();      // 1
long minutes = duration.toMinutes();  // 90
long seconds = duration.toSeconds();  // 5400
long millis = duration.toMillis();    // 5400000
long nanos = duration.toNanos();      // 5400000000000

// 获取各部分
long secondsPart = duration.getSeconds(); // 5400
int nanoPart = duration.getNano();       // 0

// 取绝对值
Duration absDuration = duration.abs();

// 取负值
Duration negated = duration.negated();

实际应用示例

示例1:计算代码执行时间

实例

Instant start = Instant.now();

// 模拟耗时操作
try {
    Thread.sleep(1500);
} catch (InterruptedException e) {
    e.printStackTrace();
}

Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);

System.out.println("代码执行耗时: " + elapsed.toMillis() + " 毫秒");

示例2:时间格式转换

实例

Duration duration = Duration.ofMinutes(135);

// 转换为"HH:MM:SS"格式
long hours = duration.toHours();
long minutes = duration.minusHours(hours).toMinutes();
long seconds = duration.minusHours(hours).minusMinutes(minutes).getSeconds();

String formatted = String.format("%02d:%02d:%02d", hours, minutes, seconds);
System.out.println(formatted); // 输出: 02:15:00

示例3:超时控制

实例

Duration timeout = Duration.ofSeconds(30);
Instant startTime = Instant.now();

while (true) {
    // 检查是否超时
    if (Duration.between(startTime, Instant.now()).compareTo(timeout) > 0) {
        System.out.println("操作超时");
        break;
    }
   
    // 执行其他操作...
}

实例

import java.time.Duration;
import java.time.LocalTime;
import java.time.Instant;

public class DurationDemo {
    public static void main(String[] args) {
        // 创建 Duration 对象的几种方式
       
        // 1. 使用 of...() 方法
        Duration duration1 = Duration.ofHours(2); // 2小时
        Duration duration2 = Duration.ofMinutes(90); // 90分钟
        System.out.println("Duration 1: " + duration1);
        System.out.println("Duration 2: " + duration2);
       
        // 2. 使用 between() 方法计算两个时间点之间的时长
        LocalTime startTime = LocalTime.of(9, 0);
        LocalTime endTime = LocalTime.of(11, 30);
        Duration duration3 = Duration.between(startTime, endTime);
        System.out.println("Duration between times: " + duration3);
       
        // 3. 使用 parse() 方法从字符串创建
        Duration duration4 = Duration.parse("PT2H30M"); // ISO-8601格式
        System.out.println("Parsed Duration: " + duration4);
       
        // 4. 使用 Instant 计算时间差
        Instant startInstant = Instant.now();
        // 模拟耗时操作
        try { Thread.sleep(1500); } catch (InterruptedException e) {}
        Instant endInstant = Instant.now();
        Duration duration5 = Duration.between(startInstant, endInstant);
        System.out.println("Execution duration: " + duration5.toMillis() + "ms");
    }
}

输出结果为:

Duration 1: PT2H
Duration 2: PT1H30M
Duration between times: PT2H30M
Parsed Duration: PT2H30M
Execution duration: 1501ms

注意事项

  1. 精度问题:Duration 可以精确到纳秒级别,但实际精度取决于操作系统和硬件的支持。

  2. 与 Period 的区别

    • Duration 用于测量基于时间的小时、分钟、秒和纳秒
    • Period 用于测量基于日期的年、月和日
  3. 不可变性:所有 Duration 对象都是不可变的,任何修改操作都会返回一个新的 Duration 实例。

  4. 负值处理:Duration 可以表示负的时间间隔,这在计算时间差时可能会遇到。

  5. 字符串格式:使用 ISO-8601 持续时间格式 PnDTnHnMn.nS,其中:

    • P 是持续时间指示符
    • D 是天数
    • T 是时间部分的分隔符
    • H 是小时数
    • M 是分钟数
    • S 是秒数(可以有小数部分)

总结

Java 的 Duration 类为处理时间间隔提供了强大而灵活的工具。通过掌握 Duration 类的使用,开发者可以更轻松地处理各种与时间计算相关的需求,如性能测量、超时控制、任务调度等。Duration 类与 Java 8 引入的其他日期时间类(如 Instant、LocalDateTime 等)配合使用,可以构建出更加健壮和易读的时间处理代码。