Класс Java Duration

Класс Duration — важный класс в API даты и времени (пакете java.time), представленном в Java 8, используемый для представления временных интервалов или длительностей.

Класс Duration в основном используется для вычисления разницы между двумя моментами времени или для представления определённой длины времени.


Базовые понятия

Временной интервал, представленный классом Duration, может быть точен до наносекунд. Он в основном используется для работы с величинами времени (часы, минуты, секунды и наносекунды), не затрагивая понятия даты или часовых поясов.

Основные возможности:

  1. Неизменяемость — после создания объекта Duration его нельзя изменить
  2. Потокобезопасность — можно безопасно использовать в многопоточных средах
  3. Высокая точность — может быть точен до наносекунд
  4. Цепочки вызовов — поддерживает цепочки методов

Создание объектов Duration

Класс Duration предоставляет несколько статических методов для создания экземпляров Duration:

1. Создание через единицы времени

Пример

// Создать Duration продолжительностью 2 часа
Duration twoHours = Duration.ofHours(2);

// Создать Duration продолжительностью 30 минут
Duration thirtyMinutes = Duration.ofMinutes(30);

// Создать Duration продолжительностью 45 секунд
Duration fortyFiveSeconds = Duration.ofSeconds(45);

// Создать Duration продолжительностью 500 миллисекунд
Duration fiveHundredMillis = Duration.ofMillis(500);

// Создать Duration продолжительностью 1,000,000 наносекунд
Duration oneMillionNanos = Duration.ofNanos(1_000_000);

2. Создание через Time Amount

Пример

// Создать Duration продолжительностью 1 день, 2 часа и 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);

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 hours

// Деление
Duration divided = d1.dividedBy(2); // 1 hour

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("Длительность 1: " + duration1);
        System.out.println("Длительность 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("Длительность между моментами времени: " + duration3);
       
        // 3. Используйте метод parse() для создания из строки
        Duration duration4 = Duration.parse("PT2H30M"); // Формат ISO-8601
        System.out.println("Разобранная длительность: " + 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("Длительность выполнения: " + 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-8601PnDTnHnMn.nS, где:

    • P — это обозначение длительности
    • D — количество дней
    • T — разделитель для части времени
    • H — количество часов
    • M — количество минут
    • S — количество секунд (может иметь дробную часть)

Итог

Класс Duration в Java предоставляет мощные и гибкие инструменты для работы с интервалами времени. Овладев использованием класса Duration, разработчики смогут легче решать различные задачи, связанные с вычислениями времени, такие как измерение производительности, контроль тайм-аутов, планирование задач и т. д. При совместном использовании с другими классами даты и времени, появившимися в Java 8 (такими как Instant, LocalDateTime и т. д.), класс Duration позволяет создавать более надёжный и читаемый код для работы со временем.

Другие расширения