ZetCode

Java ChronoUnit 枚举

最后修改时间:2025 年 4 月 16 日

java.time.temporal.ChronoUnit 枚举表示标准的时间度量单位。它为 Java Time API 提供了从纳秒到世纪的单位。ChronoUnit 实现了 TemporalUnit 接口。

ChronoUnit 用于时间算术和日期时间计算。它与 InstantLocalDateZonedDateTime 等类一起使用。该枚举提供了基于时间和基于日期的单位。

ChronoUnit 枚举概述

ChronoUnit 包含各种时间单位的常量。每个单位都有一个持续时间和用于时间计算的方法。该枚举一致地处理小的 时间单位和大的基于日期的单位。

public enum ChronoUnit implements TemporalUnit {
    NANOS, MICROS, MILLIS, SECONDS, MINUTES, HOURS, HALF_DAYS,
    DAYS, WEEKS, MONTHS, YEARS, DECADES, CENTURIES, MILLENNIA, ERAS,
    FOREVER;
    
    public boolean isDateBased();
    public boolean isTimeBased();
    public Duration getDuration();
    public boolean isSupportedBy(Temporal temporal);
    public <R extends Temporal> R addTo(R temporal, long amount);
}

上面的代码显示了 ChronoUnit 中的关键方法和常量。该枚举提供了从纳秒到千年的单位。每个单位都可用于从时间对象中添加/减去时间。

ChronoUnit 的基本用法

ChronoUnit 常量可以直接用于时间计算。最简单的用法涉及从时间对象中添加或减去单位。这提供了对日期时间操作的精确控制。

Main.java
package com.zetcode;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDateTime now = LocalDateTime.now();
        System.out.println("Current time: " + now);
        
        // Add 5 hours
        LocalDateTime later = now.plus(5, ChronoUnit.HOURS);
        System.out.println("5 hours later: " + later);
        
        // Subtract 3 days
        LocalDateTime earlier = now.minus(3, ChronoUnit.DAYS);
        System.out.println("3 days earlier: " + earlier);
        
        // Add 30 minutes
        LocalDateTime soon = now.plus(30, ChronoUnit.MINUTES);
        System.out.println("30 minutes later: " + soon);
    }
}

此示例演示了 ChronoUnit 的基本算术运算。我们从当前日期时间添加和减去不同的时间单位。这些操作正确地维护了所有日期时间字段,并自动处理溢出。

计算时间差

ChronoUnit 可以计算时间对象之间的差异。between 方法返回指定单位的时间量。这对于测量事件之间的持续时间很有用。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date1 = LocalDate.of(2025, 1, 1);
        LocalDate date2 = LocalDate.of(2025, 12, 31);
        
        // Days between dates
        long daysBetween = ChronoUnit.DAYS.between(date1, date2);
        System.out.println("Days between: " + daysBetween);
        
        // Months between dates
        long monthsBetween = ChronoUnit.MONTHS.between(date1, date2);
        System.out.println("Months between: " + monthsBetween);
        
        LocalTime time1 = LocalTime.of(8, 30);
        LocalTime time2 = LocalTime.of(17, 45);
        
        // Hours between times
        long hoursBetween = ChronoUnit.HOURS.between(time1, time2);
        System.out.println("Hours between: " + hoursBetween);
        
        // Minutes between times
        long minsBetween = ChronoUnit.MINUTES.between(time1, time2);
        System.out.println("Minutes between: " + minsBetween);
    }
}

此示例展示了如何使用各种 ChronoUnit 值计算日期和时间之间的差异。该方法返回两个时间对象之间指定单位的完整计数。

检查单位支持

并非所有时间对象都支持所有 ChronoUnit 值。isSupportedBy 方法检查一个单位是否可以与特定的时间对象一起使用。这可以防止运行时不支持的操作。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.now();
        LocalTime time = LocalTime.now();
        
        // Check date-based units
        System.out.println("DAYS supported by date: " + 
            ChronoUnit.DAYS.isSupportedBy(date));
        System.out.println("HOURS supported by date: " + 
            ChronoUnit.HOURS.isSupportedBy(date));
            
        // Check time-based units
        System.out.println("HOURS supported by time: " + 
            ChronoUnit.HOURS.isSupportedBy(time));
        System.out.println("MONTHS supported by time: " + 
            ChronoUnit.MONTHS.isSupportedBy(time));
            
        // Check mixed units
        System.out.println("WEEKS supported by date: " + 
            ChronoUnit.WEEKS.isSupportedBy(date));
        System.out.println("NANOS supported by time: " + 
            ChronoUnit.NANOS.isSupportedBy(time));
    }
}

此示例演示了检查不同时间类型的单位支持。基于日期的对象通常不支持时间单位,反之亦然。该方法有助于编写安全处理时间操作的稳健代码。

使用 Instant

ChronoUnit 与 Instant 配合使用时,在精确的时间计算方面表现出色。Instant 支持所有基于时间的单位,但不支持基于日期的单位。这使其成为机器时间操作的理想选择。

Main.java
package com.zetcode;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) throws InterruptedException {
        
        Instant start = Instant.now();
        Thread.sleep(1500); // Simulate work
        Instant end = Instant.now();
        
        // Calculate duration in various units
        System.out.println("Nanos between: " + 
            ChronoUnit.NANOS.between(start, end));
        System.out.println("Millis between: " + 
            ChronoUnit.MILLIS.between(start, end));
        System.out.println("Seconds between: " + 
            ChronoUnit.SECONDS.between(start, end));
            
        // Add time to instant
        Instant future = start.plus(2, ChronoUnit.HOURS)
                             .plus(30, ChronoUnit.MINUTES);
        System.out.println("Future time: " + future);
    }
}

此示例展示了 ChronoUnit 与 Instant 的用法。我们以不同的精度单位测量时间间隔并执行时间算术。Instant 提供纳秒精度(如果可用)。

基于日期的计算

对于基于日期的计算,ChronoUnit 提供了诸如天、周和月之类的单位。这些单位考虑了日历规则,例如不同的月份长度。这些计算保持了日历的正确性。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDate today = LocalDate.now();
        System.out.println("Today: " + today);
        
        // Add weeks
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        System.out.println("Next week: " + nextWeek);
        
        // Subtract months
        LocalDate lastMonth = today.minus(1, ChronoUnit.MONTHS);
        System.out.println("Last month: " + lastMonth);
        
        // Complex calculation
        LocalDate futureDate = today.plus(2, ChronoUnit.YEARS)
                                   .minus(3, ChronoUnit.MONTHS);
        System.out.println("Future date: " + futureDate);
        
        // Days in February 2024 (leap year)
        LocalDate feb1 = LocalDate.of(2024, Month.FEBRUARY, 1);
        long daysInFeb = ChronoUnit.DAYS.between(feb1, 
            feb1.plus(1, ChronoUnit.MONTHS));
        System.out.println("Days in Feb 2024: " + daysInFeb);
    }
}

此示例演示了使用 ChronoUnit 的基于日期的计算。这些操作遵守日历规则,包括闰年和不同的月份长度。结果始终是日历正确的。

组合时间和日期单位

ChronoUnit 允许在计算中组合时间和日期单位。这对于复杂的时间操作很有用。这些操作按顺序应用,并进行适当的单位转换。

Main.java
package com.zetcode;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {
        
        LocalDateTime now = LocalDateTime.now();
        System.out.println("Now: " + now);
        
        // Mixed unit calculation
        LocalDateTime complex = now.plus(2, ChronoUnit.DAYS)
                                  .plus(3, ChronoUnit.HOURS)
                                  .minus(45, ChronoUnit.MINUTES);
        System.out.println("Complex result: " + complex);
        
        // Calculate weeks between dates
        LocalDateTime future = now.plus(10, ChronoUnit.WEEKS);
        long weeksBetween = ChronoUnit.WEEKS.between(now, future);
        System.out.println("Weeks between: " + weeksBetween);
        
        // Check if unit is time or date based
        System.out.println("HOURS is time-based: " + 
            ChronoUnit.HOURS.isTimeBased());
        System.out.println("MONTHS is date-based: " + 
            ChronoUnit.MONTHS.isDateBased());
    }
}

此示例展示了在计算中组合时间和日期单位。我们还检查了单位是基于时间还是基于日期。这些操作在不同的单位类型之间保持时间的一致性。

来源

Java ChronoUnit 枚举文档

在本文中,我们介绍了 Java ChronoUnit 枚举的基本方法和功能。理解这些概念对于在 Java 应用程序中进行精确的时间和日期计算至关重要。

作者

我叫 Jan Bodnar,是一位敬业的程序员,在该领域拥有多年的经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和 8 本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程