Java Duration クラス

Duration クラスは、Java 8 で導入された日時 API(java.time パッケージ)における重要なクラスの1つで、時間間隔や継続時間を表すために使用されます。

Duration クラスは主に、2つの時点の差を計算したり、特定の時間の長さを表したりするために使用されます。


基本概念

Duration クラスが表す時間間隔は、ナノ秒単位まで正確です。主に時間ベースの量(時、分、秒、ナノ秒)を扱い、日付やタイムゾーンの概念は含みません。

主な特徴:

  1. 不変性 - Duration オブジェクトは一度作成されると変更できません
  2. スレッドセーフ - マルチスレッド環境で安全に使用できます
  3. 高精度 - ナノ秒単位までの精度があります
  4. チェーン呼び出し - メソッドチェーンをサポートします

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

2. 時間量による作成

例

// 1日2時間3分のDurationを作成
Duration customDuration = Duration.ofDays(1).plusHours(2).plusMinutes(3);

3. 2つの時点の計算による作成

例

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時間

// 除算
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

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("Duration 1: " + duration1);
        System.out.println("Duration 2: " + duration2);
       
        // 2. between() メソッドを使用して2つの時点間の時間を計算
        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

注意事項

  1. 精度の問題:Duration はナノ秒単位まで正確ですが、実際の精度はオペレーティングシステムとハードウェアのサポートに依存します。

  2. Period との違い:

    • Duration は、時間ベースの時、分、秒、ナノ秒を計測するために使用されます
    • Period は、日付ベースの年、月、日を計測するために使用されます
  3. 不変性:すべての Duration オブジェクトは不変であり、変更操作はすべて新しい Duration インスタンスを返します。

  4. 負の値の扱い:Duration は負の時間間隔を表すことができます。これは時間差を計算する際に発生する可能性があります。

  5. 文字列形式:ISO-8601 の継続時間形式を使用しますPnDTnHnMn.nS。その内訳は:

    • P は継続時間の指示子です
    • D は日数です
    • T は時間部分の区切り文字です
    • H は時間数です
    • M は分数です
    • S は秒数です(小数部分を持つことができます)

まとめ

Java の Duration クラスは、時間間隔を処理するための強力で柔軟なツールを提供します。Duration クラスの使用方法をマスターすることで、開発者はパフォーマンス測定、タイムアウト制御、タスクスケジューリングなど、時間計算に関連するさまざまなニーズをより簡単に処理できます。Duration クラスは、Java 8 で導入された他の日時クラス(Instant、LocalDateTime など)と組み合わせて使用することで、より堅牢で読みやすい時間処理コードを構築できます。

その他の拡張