Класс Java ChronoUnit

ChronoUnit — это enum-класс, появившийся в Java 8, принадлежащийjava.time.temporalпакет.

ChronoUnit определяет набор стандартных единиц времени, используемых для представления различных гранулярностей даты и времени. ChronoUnit в основном используется с Java 8 Date-Time 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); // Вычесть один месяц

3. Расчёт разницы во времени

Вы можете использоватьbetween()метод для вычисления разницы между двумя моментами времени.

Пример

LocalDate start = LocalDate.of(2023, 1, 1);
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 часов

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

3. Метод isSupportedBy()

Проверяет, поддерживает ли объект Temporal единицу времени.

Пример

public boolean isSupportedBy(Temporal temporal)

Пример:

Пример

LocalDate date = LocalDate.now();
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 + " лет");

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 + " дней");

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));
}

Простой пример

Пример

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));
    }
}

Вывод:

今天和下周今天之间的天数: 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);
    }
}

Вывод:

年龄: 34 年 11 个月 16 天

Примечания

  1. Поддержка единиц времени: Не все объекты Temporal поддерживают все ChronoUnit. Например,LocalDateне поддерживаетHOURSилиMINUTES。

  2. Обработка отрицательных значений: Когда первый параметр позже второго,between()метод вернёт отрицательное значение.

  3. Проблемы точности: Для более крупных единиц времени (таких как MONTHS или YEARS) вычисления могут быть не совсем точными, потому что количество дней в этих единицах не фиксировано.

  4. Соображения производительности: Для частых вычислений времени использование ChronoUnit эффективнее и менее подвержено ошибкам, чем ручной расчёт.


Сравнение с другими классами

1. ChronoUnit против TimeUnit

  • TimeUnitВ основном используется для приостановки потоков и параллельных операций, с более тонкой гранулярностью единиц времени (от наносекунд до дней)
  • ChronoUnitРазработан специально для Date-Time API, поддерживает более крупные единицы времени (от недель до тысячелетий)

2. ChronoUnit против Duration/Period

  • DurationИспользуется для точных промежутков времени (от наносекунд до дней)
  • PeriodИспользуется для величин в датах (от дней до лет)
  • ChronoUnitПредоставляет более гибкий выбор единиц измерения и методы вычислений
Другие расширения