Java ChronoUnit 类
ChronoUnit 是 Java 8 引入的一个枚举类,属于 java.time.temporal
包。
ChronoUnit 定义了一组标准的时间单位,用于表示日期和时间的不同粒度。ChronoUnit 主要用于与 Java 8 日期时间 API(如 LocalDate
、LocalTime
、LocalDateTime
等)一起使用,进行时间的计算和比较。
核心功能
1. 时间单位表示
ChronoUnit 提供了从纳秒到世纪的各种时间单位,包括:
NANOS
:纳秒MICROS
:微秒MILLIS
:毫秒SECONDS
:秒MINUTES
:分钟HOURS
:小时HALF_DAYS
:半天(12 小时)DAYS
:天WEEKS
:周MONTHS
:月YEARS
:年DECADES
:十年CENTURIES
:世纪MILLENNIA
:千年ERAS
:纪元
2. 时间计算
ChronoUnit 可以与 Temporal
对象(如 LocalDate
)一起使用,进行时间的加减操作。
实例
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); // 加一周
LocalDate lastMonth = today.minus(1, ChronoUnit.MONTHS); // 减一个月
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS); // 加一周
LocalDate lastMonth = today.minus(1, ChronoUnit.MONTHS); // 减一个月
3. 时间差计算
可以使用 between()
方法计算两个时间点之间的差值。
实例
LocalDate start = LocalDate.of(2023, 1, 1);
LocalDate end = LocalDate.of(2023, 12, 31);
long days = ChronoUnit.DAYS.between(start, end); // 计算天数差
LocalDate end = LocalDate.of(2023, 12, 31);
long days = ChronoUnit.DAYS.between(start, end); // 计算天数差
常用方法详解
1. between() 方法
计算两个 Temporal 对象之间的时间差。
实例
public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive)
示例:
实例
LocalDateTime start = LocalDateTime.of(2023, 1, 1, 0, 0);
LocalDateTime end = LocalDateTime.of(2023, 1, 2, 12, 0);
long hours = ChronoUnit.HOURS.between(start, end); // 36 小时
LocalDateTime end = LocalDateTime.of(2023, 1, 2, 12, 0);
long hours = ChronoUnit.HOURS.between(start, end); // 36 小时
2. addTo() 方法
将时间单位添加到 Temporal 对象。
实例
public Temporal addTo(Temporal temporal, long amount)
示例:
实例
LocalTime time = LocalTime.of(14, 30);
LocalTime newTime = (LocalTime) ChronoUnit.HOURS.addTo(time, 3); // 17:30
LocalTime newTime = (LocalTime) ChronoUnit.HOURS.addTo(time, 3); // 17:30
3. isSupportedBy() 方法
检查 Temporal 对象是否支持该时间单位。
实例
public boolean isSupportedBy(Temporal temporal)
示例:
实例
LocalDate date = LocalDate.now();
boolean supported = ChronoUnit.HOURS.isSupportedBy(date); // false,因为 LocalDate 不支持小时单位
boolean supported = ChronoUnit.HOURS.isSupportedBy(date); // false,因为 LocalDate 不支持小时单位
实际应用示例
1. 计算年龄
实例
LocalDate birthDate = LocalDate.of(1990, 5, 15);
LocalDate now = LocalDate.now();
long age = ChronoUnit.YEARS.between(birthDate, now);
System.out.println("年龄: " + age + " 岁");
LocalDate now = LocalDate.now();
long age = ChronoUnit.YEARS.between(birthDate, now);
System.out.println("年龄: " + age + " 岁");
2. 计算项目持续时间
实例
LocalDateTime projectStart = LocalDateTime.of(2023, 1, 1, 9, 0);
LocalDateTime projectEnd = LocalDateTime.of(2023, 6, 30, 18, 0);
long months = ChronoUnit.MONTHS.between(projectStart, projectEnd);
long days = ChronoUnit.DAYS.between(projectStart, projectEnd);
System.out.println("项目持续: " + months + " 个月,或 " + days + " 天");
LocalDateTime projectEnd = LocalDateTime.of(2023, 6, 30, 18, 0);
long months = ChronoUnit.MONTHS.between(projectStart, projectEnd);
long days = ChronoUnit.DAYS.between(projectStart, projectEnd);
System.out.println("项目持续: " + months + " 个月,或 " + days + " 天");
3. 生成日期序列
实例
LocalDate start = LocalDate.of(2023, 1, 1);
List<LocalDate> dates = new ArrayList<>();
for (int i = 0; i < 7; i++) {
dates.add(start.plus(i, ChronoUnit.DAYS));
}
List<LocalDate> dates = new ArrayList<>();
for (int i = 0; i < 7; i++) {
dates.add(start.plus(i, ChronoUnit.DAYS));
}
简单实例
实例
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ChronoUnitExample {
public static void main(String[] args) {
// 1. 计算两个日期之间的天数
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
long daysBetween = ChronoUnit.DAYS.between(today, nextWeek);
System.out.println("今天和下周今天之间的天数: " + daysBetween);
// 2. 时间加减
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间: " + now);
LocalDateTime in2Hours = now.plus(2, ChronoUnit.HOURS);
System.out.println("两小时后: " + in2Hours);
LocalDateTime yesterday = now.minus(1, ChronoUnit.DAYS);
System.out.println("昨天此时: " + yesterday);
// 3. 计算两个时间点之间的小时数
long hoursBetween = ChronoUnit.HOURS.between(yesterday, now);
System.out.println("昨天此时到现在的小时数: " + hoursBetween);
// 4. 使用不同的时间单位
System.out.println("相差的分钟数: " + ChronoUnit.MINUTES.between(yesterday, now));
System.out.println("相差的秒数: " + ChronoUnit.SECONDS.between(yesterday, now));
// 5. 检查时间单位是否支持特定类型
System.out.println("DAYS是否支持LocalDate: " + ChronoUnit.DAYS.isSupportedBy(today));
System.out.println("HOURS是否支持LocalDate: " + ChronoUnit.HOURS.isSupportedBy(today));
}
}
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ChronoUnitExample {
public static void main(String[] args) {
// 1. 计算两个日期之间的天数
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
long daysBetween = ChronoUnit.DAYS.between(today, nextWeek);
System.out.println("今天和下周今天之间的天数: " + daysBetween);
// 2. 时间加减
LocalDateTime now = LocalDateTime.now();
System.out.println("当前时间: " + now);
LocalDateTime in2Hours = now.plus(2, ChronoUnit.HOURS);
System.out.println("两小时后: " + in2Hours);
LocalDateTime yesterday = now.minus(1, ChronoUnit.DAYS);
System.out.println("昨天此时: " + yesterday);
// 3. 计算两个时间点之间的小时数
long hoursBetween = ChronoUnit.HOURS.between(yesterday, now);
System.out.println("昨天此时到现在的小时数: " + hoursBetween);
// 4. 使用不同的时间单位
System.out.println("相差的分钟数: " + ChronoUnit.MINUTES.between(yesterday, now));
System.out.println("相差的秒数: " + ChronoUnit.SECONDS.between(yesterday, now));
// 5. 检查时间单位是否支持特定类型
System.out.println("DAYS是否支持LocalDate: " + ChronoUnit.DAYS.isSupportedBy(today));
System.out.println("HOURS是否支持LocalDate: " + ChronoUnit.HOURS.isSupportedBy(today));
}
}
输出结果为:
今天和下周今天之间的天数: 7 当前时间: 2025-05-01T11:22:22.247669 两小时后: 2025-05-01T13:22:22.247669 昨天此时: 2025-04-30T11:22:22.247669 昨天此时到现在的小时数: 24 相差的分钟数: 1440 相差的秒数: 86400 DAYS是否支持LocalDate: true HOURS是否支持LocalDate: false
计算年龄
实例
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
public class AgeCalculator {
public static void main(String[] args) {
LocalDate birthDate = LocalDate.of(1990, 5, 15);
LocalDate currentDate = LocalDate.now();
long years = ChronoUnit.YEARS.between(birthDate, currentDate);
long months = ChronoUnit.MONTHS.between(birthDate, currentDate) % 12;
long days = ChronoUnit.DAYS.between(
birthDate.plusYears(years).plusMonths(months),
currentDate
);
System.out.printf("年龄: %d 年 %d 个月 %d 天%n", years, months, days);
}
}
import java.time.temporal.ChronoUnit;
public class AgeCalculator {
public static void main(String[] args) {
LocalDate birthDate = LocalDate.of(1990, 5, 15);
LocalDate currentDate = LocalDate.now();
long years = ChronoUnit.YEARS.between(birthDate, currentDate);
long months = ChronoUnit.MONTHS.between(birthDate, currentDate) % 12;
long days = ChronoUnit.DAYS.between(
birthDate.plusYears(years).plusMonths(months),
currentDate
);
System.out.printf("年龄: %d 年 %d 个月 %d 天%n", years, months, days);
}
}
输出结果为:
年龄: 34 年 11 个月 16 天
注意事项
时间单位支持:不是所有 Temporal 对象都支持所有 ChronoUnit。例如,
LocalDate
不支持HOURS
或MINUTES
。负值处理:当第一个参数晚于第二个参数时,
between()
方法会返回负值。精度问题:对于较大的时间单位(如 MONTHS 或 YEARS),计算可能不会完全精确,因为这些单位的天数不固定。
性能考虑:对于频繁的时间计算,使用 ChronoUnit 比手动计算更高效且不易出错。
与其他类的比较
1. ChronoUnit vs TimeUnit
TimeUnit
主要用于线程休眠和并发操作,时间单位粒度较细(纳秒到天)ChronoUnit
专为日期时间 API 设计,支持更大的时间单位(周到千年)
2. ChronoUnit vs Duration/Period
Duration
用于精确的时间量(纳秒到天)Period
用于日期量(天到年)ChronoUnit
提供了更灵活的单位选择和计算方法
点我分享笔记