Java | Java 標準ライブラリ:Period と Duration

Java Java
スポンサーリンク

Period と Duration をざっくり一言でいうと

PeriodDuration は、どちらも「時間の長さ」を表すクラスですが、
何を基準にしているかがまったく違います。

  • Period … 年・月・日ベース(カレンダー的な「◯年◯か月◯日」)
  • Duration … 時・分・秒・ナノ秒ベース(ストップウォッチ的な「◯時間◯分◯秒」)

たとえば、

「このプロジェクトは 2 年 3 か月 10 日かかる」
→ Period が得意な世界

「処理時間は 3 秒 200 ミリ秒だった」
→ Duration が得意な世界

というイメージです。

「日付の差」を扱いたいのか、「時刻の差」を扱いたいのか。
ここを意識すると、どちらを使うべきか迷いにくくなります。


Period:年・月・日で扱う“カレンダー的な期間”

Period の基本イメージと生成方法

Period は「◯年◯か月◯日」という単位で期間を扱います。
使う対象は LocalDate(日付だけ)の世界が基本です。

代表的な生成方法は 2 つあります。

import java.time.LocalDate;
import java.time.Period;

public class PeriodBasic {
    public static void main(String[] args) {
        // 1. 直接「2年3か月10日」という期間を作る
        Period p1 = Period.of(2, 3, 10);
        System.out.println(p1); // P2Y3M10D

        // 2. 2つの LocalDate の差から作る
        LocalDate start = LocalDate.of(2025, 1, 1);
        LocalDate end   = LocalDate.of(2027, 4, 11);

        Period p2 = Period.between(start, end);
        System.out.println(p2); // P2Y3M10D のような感じ
    }
}
Java

Period.between(start, end) は「start から end までの差」を「年・月・日」に分解したものです。
マイナス方向(start > end)の場合は、負の値を持つ Period が返ります。

Period の中身を取り出す

LocalDate start = LocalDate.of(2025, 1, 1);
LocalDate end   = LocalDate.of(2027, 4, 11);
Period p = Period.between(start, end);

int years  = p.getYears();   // 2
int months = p.getMonths();  // 3
int days   = p.getDays();    // 10

System.out.println(years + "年" + months + "か月" + days + "日");
Java

getYears() / getMonths() / getDays() で、「何年」「何か月」「何日か」をそれぞれ取り出せます。

ここで重要なのは、
「トータル◯日」というより、「年・月・日それぞれの差」だということです。
1 か月を 30 日と決めつけたりせず、カレンダー通りの差になります。

Period を日付に加える・引く

LocalDatePeriod を足したり引いたりできます。

import java.time.LocalDate;
import java.time.Period;

public class PeriodAdd {
    public static void main(String[] args) {
        LocalDate start = LocalDate.of(2025, 1, 10);
        Period period = Period.of(1, 2, 3); // 1年2か月3日

        LocalDate result = start.plus(period);
        System.out.println(result); // 2026-03-13
    }
}
Java

minus(period) とすれば引き算もできます。

Period を使うと、

「1 か月後の締切」
「3 か月ごとの請求日」
「2 年間の契約期間」

といった「カレンダー的な期間」を、そのままコードに表現できます。


Duration:時・分・秒で扱う“ストップウォッチ的な時間”

Duration の基本イメージと生成方法

Duration は「◯時間◯分◯秒◯ナノ秒」という、時間ベースの量を扱います。
対象は LocalTime / LocalDateTime / Instant など、「時刻を含む API」です。

代表的な生成方法はこんな感じです。

import java.time.Duration;

public class DurationBasic {
    public static void main(String[] args) {
        Duration threeHours = Duration.ofHours(3);
        Duration twoMinutes = Duration.ofMinutes(2);
        Duration tenSeconds = Duration.ofSeconds(10);

        System.out.println(threeHours); // PT3H
        System.out.println(twoMinutes); // PT2M
        System.out.println(tenSeconds); // PT10S
    }
}
Java

ofSeconds / ofMinutes / ofHours などで、秒・分・時間ベースの Duration を作れます。

2 つの日時の差から Duration を作る

Duration.between を使うと、2 つの日時の差を「時間量」として求められます。

import java.time.Duration;
import java.time.LocalTime;

public class DurationBetween {
    public static void main(String[] args) {
        LocalTime start = LocalTime.of(9, 0, 0);
        LocalTime end   = LocalTime.of(11, 30, 0);

        Duration d = Duration.between(start, end);

        System.out.println(d);            // PT2H30M
        System.out.println(d.toHours());  // 2
        System.out.println(d.toMinutes()); // 150
        System.out.println(d.getSeconds()); // 9000
    }
}
Java

「9:00 から 11:30 までは、2 時間 30 分(150 分)」という感覚を、そのまま Duration として持てます。

Duration を時刻に加える・引く

import java.time.Duration;
import java.time.LocalDateTime;

public class DurationAdd {
    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2025, 1, 10, 9, 0);
        Duration d = Duration.ofMinutes(90); // 90分

        LocalDateTime result = start.plus(d);
        System.out.println(result); // 2025-01-10T10:30
    }
}
Java

処理時間やタイムアウト時間、待ち時間など、
「純粋な時間量」を足したり引いたりするのに向いています。


Period と Duration の違いを“ちゃんと”整理する

単位の違い(ここが一番大事)

Period
…… 年・月・日ベース。「カレンダー」と同じ単位

Duration
…… 秒・ナノ秒ベース。24 時間= 86400 秒という世界

同じ「1 日」でも、Period と Duration では意味が違うことがあります。

例えば、夏時間(サマータイム)で 1 時間進んだり戻ったりする日を考えます。

import java.time.*;

ZoneId zone = ZoneId.of("Europe/Berlin"); // 夏時間があるタイムゾーン
ZonedDateTime zdt = ZonedDateTime.of(2025, 3, 30, 18, 0, 0, 0, zone);

ZonedDateTime plus1DayWithPeriod   = zdt.plus(Period.ofDays(1));
ZonedDateTime plus1DayWithDuration = zdt.plus(Duration.ofDays(1)); // 24時間後
Java

公式ドキュメントにもある通り:

  • Period.ofDays(1) は「概念上の 1 日」を足すので、翌日の 18:00 になります
  • Duration.ofDays(1) は「正確に 24 時間」を足すので、夏時間ギャップがある場合は 翌日の 19:00 になることがあります

つまり、

「カレンダー上で 1 日後」なら Period
「24 時間後きっちり」なら Duration

と使い分けが必要です。

何と一緒に使うかの違い

Period は LocalDate(日付だけ)との相性が良く、
DurationLocalTime / LocalDateTime / Instant など「時刻を含む型」との相性が良いです。

ざっくり言うと、

日付の差・日付ベースの期間 → Period
時間・処理時間・待ち時間 → Duration

という棲み分けを意識しておくと、かなり整理されます。


実務でありがちな例でイメージを固める

例1:2 つの日付の「年・月・日」の差を出したい(Period)

「入社日から今日までで、何年何か月働いたか?」
これは Period の出番です。

import java.time.LocalDate;
import java.time.Period;

public class WorkPeriod {
    public static void main(String[] args) {
        LocalDate joined = LocalDate.of(2020, 4, 1);
        LocalDate today  = LocalDate.now();

        Period period = Period.between(joined, today);

        int years  = period.getYears();
        int months = period.getMonths();
        int days   = period.getDays();

        System.out.println("勤続 " + years + "年" + months + "か月" + days + "日");
    }
}
Java

「何日間働いたか(トータル日数)」というより、
「何年・何か月・何日」という“人間向けの表現”に向いています。

例2:処理時間を測りたい(Duration)

処理時間・レスポンスタイムなどの計測には、Duration がぴったりです。

import java.time.Duration;
import java.time.Instant;

public class MeasureTime {
    public static void main(String[] args) {
        Instant start = Instant.now();

        // 何か重い処理
        doHeavyWork();

        Instant end = Instant.now();

        Duration d = Duration.between(start, end);

        System.out.println("処理時間(ミリ秒): " + d.toMillis());
        System.out.println("処理時間(秒): " + d.toMillis() / 1000.0);
    }

    private static void doHeavyWork() {
        try {
            Thread.sleep(1234); // ダミーで1.234秒スリープ
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
Java

toMillis() / toSeconds() などで単位を変換できるので、
ストップウォッチのように扱えます。


Period と Duration をどのように頭に定着させるか

Period と Duration を、初心者向けに整理するとこうなります。

  • Period
    …… 年・月・日ベースの期間。カレンダー的な「◯年◯か月◯日」。
    …… LocalDate の差や、「1 か月後の締切」「2 年間の契約」などに使う。
  • Duration
    …… 秒・ナノ秒ベースの時間量。ストップウォッチ的な「◯時間◯分◯秒」。
    …… 処理時間、タイムアウト、待ち時間、「きっちり 24 時間後」などに使う。

特に意識してほしいポイントは、

「カレンダー上の期間を扱いたいのか」
「時間量(秒・分・時間)を扱いたいのか」

この質問を自分にしてみて、前者なら Period、後者なら Duration を選ぶ、という感覚です。

タイトルとURLをコピーしました