Java Duration 类
Duration 类是 Java 8 引入的日期时间 API(java.time 包)中的一个重要类,用于表示时间间隔或持续时间。
Duration 类主要用于计算两个时间点之间的差异,或者表示一段特定的时间长度。
基本概念
Duration 类表示的时间间隔可以精确到纳秒级别。它主要用于处理基于时间的量(小时、分钟、秒和纳秒),而不涉及日期或时区的概念。
主要特点:
- 不可变性 - Duration 对象一旦创建就不能被修改
- 线程安全 - 可以在多线程环境中安全使用
- 精确度高 - 可以精确到纳秒级别
- 链式调用 - 支持方法链式调用
创建 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);
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);
Duration customDuration = Duration.ofDays(1).plusHours(2).plusMinutes(3);
3. 通过两个时间点计算
实例
Instant start = Instant.now();
// 执行一些操作...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
// 执行一些操作...
Instant end = Instant.now();
Duration elapsed = Duration.between(start, end);
4. 解析字符串创建
实例
// 从ISO-8601格式的字符串创建
Duration parsedDuration = Duration.parse("PT2H30M15S"); // 2小时30分钟15秒
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
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小时
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
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();
// 转换为其他单位
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() + " 毫秒");
// 模拟耗时操作
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
// 转换为"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;
}
// 执行其他操作...
}
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");
}
}
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
注意事项
精度问题:Duration 可以精确到纳秒级别,但实际精度取决于操作系统和硬件的支持。
与 Period 的区别:
- Duration 用于测量基于时间的小时、分钟、秒和纳秒
- Period 用于测量基于日期的年、月和日
不可变性:所有 Duration 对象都是不可变的,任何修改操作都会返回一个新的 Duration 实例。
负值处理:Duration 可以表示负的时间间隔,这在计算时间差时可能会遇到。
字符串格式:使用 ISO-8601 持续时间格式
PnDTnHnMn.nS
,其中:- P 是持续时间指示符
- D 是天数
- T 是时间部分的分隔符
- H 是小时数
- M 是分钟数
- S 是秒数(可以有小数部分)
总结
Java 的 Duration 类为处理时间间隔提供了强大而灵活的工具。通过掌握 Duration 类的使用,开发者可以更轻松地处理各种与时间计算相关的需求,如性能测量、超时控制、任务调度等。Duration 类与 Java 8 引入的其他日期时间类(如 Instant、LocalDateTime 等)配合使用,可以构建出更加健壮和易读的时间处理代码。
点我分享笔记