経過時間のゴールイメージ
「処理に何秒かかった?」「ログインから何時間経過した?」「締切まであと何時間?」
業務システムでは、“2つの日時の差”=経過時間を扱う場面がとても多いです。
ここでまず押さえてほしいのは、
年・月・日・時・分・秒を自分でバラして引き算しない、ということです。
Java には Duration と ChronoUnit という、“時間差専用の道具”が用意されています。
これを素直に使うと、安全で読みやすい経過時間のコードが書けます。
Duration を使った経過時間の基本
Duration.between(開始日時, 終了日時)
Duration は「時間の長さ」を表すクラスです。
2つの LocalDateTime や Instant から経過時間を求めるときに使います。
import java.time.Duration;
import java.time.LocalDateTime;
public class ElapsedTimeBasic {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2025, 3, 26, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 3, 26, 12, 30, 15);
Duration d = Duration.between(start, end);
long seconds = d.getSeconds();
long minutes = d.toMinutes();
long hours = d.toHours();
System.out.println("開始 : " + start);
System.out.println("終了 : " + end);
System.out.println("経過秒 : " + seconds); // 9015
System.out.println("経過分 : " + minutes); // 150
System.out.println("経過時間 : " + hours); // 2
}
}
Javaここで重要なのは、Duration が「秒」をベースにしていることです。getSeconds() で総秒数、toMinutes() で総分数、toHours() で総時間数が取れます。
「2時間30分15秒」という“見た目”ではなく、
「9015秒」「150分」「2時間」といった“総量”として扱えるのがポイントです。
経過時間を「時・分・秒」に分解する
総秒数から時・分・秒を計算する
画面表示などでは、「2時間30分15秒」のように分解して見せたいことが多いです。
その場合は、総秒数から自分で割り算していきます。
import java.time.Duration;
import java.time.LocalDateTime;
public class ElapsedTimeBreakdown {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2025, 3, 26, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 3, 26, 12, 30, 15);
Duration d = Duration.between(start, end);
long totalSeconds = d.getSeconds();
long hours = totalSeconds / 3600;
long remain = totalSeconds % 3600;
long minutes = remain / 60;
long seconds = remain % 60;
System.out.println("経過時間: " + hours + "時間" + minutes + "分" + seconds + "秒");
// 2時間30分15秒
}
}
Javaここで深掘りしたいのは、
「Duration は“総秒数”を持っているので、あとは算数でどうとでも表現できる」
という感覚です。
内部では常に「秒」で持っておき、
表示のときだけ「時・分・秒」に分解する、という設計にすると、
ロジックがシンプルになります。
ChronoUnit を使った経過時間の取得
HOURS.between, MINUTES.between, SECONDS.between
ChronoUnit を使うと、「何時間」「何分」「何秒」といった差を直接取ることもできます。
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
public class ElapsedTimeChronoUnit {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2025, 3, 26, 10, 0, 0);
LocalDateTime end = LocalDateTime.of(2025, 3, 26, 12, 30, 15);
long hours = ChronoUnit.HOURS.between(start, end);
long minutes = ChronoUnit.MINUTES.between(start, end);
long seconds = ChronoUnit.SECONDS.between(start, end);
System.out.println("経過時間(時間単位) : " + hours); // 2
System.out.println("経過時間(分単位) : " + minutes); // 150
System.out.println("経過時間(秒単位) : " + seconds); // 9015
}
}
JavaChronoUnit.HOURS.between は「何時間分進んだか」を返します。
2時間30分15秒なら「2時間」、
分単位なら「150分」、秒単位なら「9015秒」です。
Duration と ChronoUnit のどちらを使うかは好みですが、
「経過時間を一つのオブジェクトとして扱いたい」なら Duration、
「特定の単位だけ欲しい」なら ChronoUnit が読みやすいことが多いです。
Instant / ZonedDateTime と経過時間
Instant で“絶対時間”としての差を取る
サーバ間の通信時間や、タイムゾーンをまたぐ処理時間など、
「世界共通の時間軸」で経過時間を測りたいときは Instant を使います。
import java.time.Duration;
import java.time.Instant;
public class ElapsedTimeInstant {
public static void main(String[] args) throws InterruptedException {
Instant start = Instant.now();
Thread.sleep(1234); // 1.234秒待つ
Instant end = Instant.now();
Duration d = Duration.between(start, end);
System.out.println("経過ミリ秒 : " + d.toMillis());
}
}
JavaInstant は「UTC 上の一点」を表すクラスです。Instant.now() で取得した時刻同士の差は、
タイムゾーンに影響されない“純粋な経過時間”になります。
ZonedDateTime でも Duration.between は同じ
タイムゾーン付きの ZonedDateTime でも、Duration.between は使えます。
import java.time.Duration;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ElapsedTimeZoned {
public static void main(String[] args) {
ZonedDateTime start = ZonedDateTime.of(
2025, 3, 26,
10, 0, 0, 0,
ZoneId.of("Asia/Tokyo")
);
ZonedDateTime end = start.plusHours(5).withZoneSameInstant(ZoneId.of("Europe/London"));
Duration d = Duration.between(start, end);
System.out.println("経過時間(時間) : " + d.toHours()); // 5
}
}
Javaここでのポイントは、Duration.between は「同じ瞬間を指しているかどうか」を見ているので、
タイムゾーンが違っていても、同じ“Instant”なら正しい差が取れる、ということです。
実務での経過時間の使いどころ
例1:処理時間の計測(簡易プロファイル)
「この処理にどれくらい時間がかかっているか」を知りたいときです。
import java.time.Duration;
import java.time.Instant;
public class ProcessingTimeExample {
public static void main(String[] args) {
Instant start = Instant.now();
heavyProcess();
Instant end = Instant.now();
Duration d = Duration.between(start, end);
System.out.println("処理時間(ms): " + d.toMillis());
}
private static void heavyProcess() {
long sum = 0;
for (int i = 0; i < 10_000_000; i++) {
sum += i;
}
}
}
Javaここでのポイントは、
「処理の前後で Instant を取って、Duration で差を出す」というパターンを覚えることです。
これだけで、簡易的な性能計測ができるようになります。
例2:締切までの残り時間を出す
「締切まであと何時間何分か」をユーザーに見せたいケースです。
import java.time.Duration;
import java.time.LocalDateTime;
public class RemainingTimeExample {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.of(2025, 3, 26, 10, 0);
LocalDateTime due = LocalDateTime.of(2025, 3, 26, 15, 45);
Duration d = Duration.between(now, due);
long totalMinutes = d.toMinutes();
long hours = totalMinutes / 60;
long minutes = totalMinutes % 60;
System.out.println("締切まで残り: " + hours + "時間" + minutes + "分");
}
}
Javaここでも、「総分数→時と分に分解」という流れを使っています。
内部では常に「一つの単位(秒や分)」で持っておき、
表示のときだけ分解する、というパターンはとても応用が利きます。
経過時間ユーティリティとしてまとめる
measure(Runnable) のような“計測用メソッド”を作る
経過時間の計測は、あちこちで同じようなコードを書きがちなので、
ユーティリティにしておくと便利です。
import java.time.Duration;
import java.time.Instant;
public class TimeMeasureUtils {
public static long measureMillis(Runnable task) {
Instant start = Instant.now();
try {
task.run();
} finally {
Instant end = Instant.now();
return Duration.between(start, end).toMillis();
}
}
public static void main(String[] args) {
long ms = measureMillis(() -> {
long sum = 0;
for (int i = 0; i < 5_000_000; i++) {
sum += i;
}
});
System.out.println("処理時間(ms): " + ms);
}
}
Javaここで深掘りしたいのは、
「経過時間の計測パターンを一か所に閉じ込めると、
どこで何を測っているかが分かりやすくなる」という点です。
まとめ:経過時間で絶対に覚えてほしいこと
経過時間は、「2つの日時の間に“どれだけの時間が流れたか”」を表す値です。
Duration.between(開始, 終了) で経過時間オブジェクトを作り、toSeconds(), toMinutes(), toHours(), toMillis() などで必要な単位に変換する。ChronoUnit.SECONDS/HOURS/... .between で、特定の単位だけを直接取ることもできる。
内部では「秒」や「分」のような一つの単位で持ち、表示のときだけ「時・分・秒」に分解する。
処理時間計測などのパターンはユーティリティメソッドにまとめておく。
もしあなたのコードのどこかに、
「時・分・秒を自前で引き算して、繰り下がりを頑張って処理している」ような箇所があれば、
そこを一度 Duration や ChronoUnit ベースに書き換えられないか眺めてみてください。
その小さな置き換えが、
“時間とカレンダーに強いエンジニア”への、確かな一歩になります。

