Duration — その概要、Androidでの続き時間の計算

著者: IT Sectr 公開日: 2026-07-13 読了時間: 9 分

Duration — java.timeパッケージの不変クラスで、秒とナノ秒で表される2つの瞬間の続き時間を表します。Durationは時間ベースの時間量—時、分、秒、ミリ秒、ナノ秒を測定します。Oracle Java 17 (2024)の仕様によると、Period(年・月・日を測定)とは異なり、Durationは精密な時間単位で動作し、カレンダーに依存しません。

まとめ

  • Duration — 秒とナノ秒で続き時間を測定するための不変クラス。
  • Periodとは異なり、Durationは時間ベースの単位(時、分、秒)を扱い、日付ベース(日、月、年)ではありません。
  • Duration.between(start, end)、Duration.ofMinutes()、Duration.ofHours()などのスタティックファクトリメソッドで作成します。
  • 演算をサポート:plus()、minus()、multipliedBy()、dividedBy()、negated()。
  • Android開発では、Durationはタイムアウト、同期間隔、処理時間の計算に便利です。

Durationとは?

Durationは、秒とナノ秒で時間量をモデル化するクラスです。カレンダーに縛られない物理的な秒数の時間ベースの続き時間を表します。Durationは“125分”や“2時間5分”として考えられますが、Periodは“2ヶ月”と表現します。

Durationの内部表現は、long seconds(秒)とint nanos(ナノ秒、0から999999999)の2つのフィールドから構成されます。値が負になることもあり、これは時間を過去に遅った続き時間を意味します。最大値は±31557014167219200秒です。

Baeldung (2024)によると、Durationは処理時間の計算、タイムアウトの設定、パフォーマンス測定のための主要なクラスです。Durationは不変でスレッドセーフであり、シンクロニゼーションなしでマルチスレッド環境で使用できます。

このクラスは、ComparableTemporalAmountTemporalUnitインタフェースを実装しています。TemporalAmountにより、LocalTime、LocalDateTime、Instant、ZonedDateTimeクラスのplus/minusメソッドでDurationを使用できます。

Duration vs Period:違いは?

主な違いは、Durationが秒の正確な数を測定するのに対し、Periodはカレンダー単位(年、月、日)を測定することです。Durationは“86400秒が経過”したと言い、Periodは“1日が経過”したと言います。夏時間の切り替え時に違いが生じます—Periodで1日は常で1カレンダー日ですが、Durationでは86400秒がDST中は23または25時間に対応することがあります。

Durationは物理的な時間の測定(接続タイムアウト、クエリ実行時間、二つのInstantの間隔)に使用され、Periodはカレンダー計算(人の年齢、契約期間)に使用されます。

Durationは秒とナノ秒を扱い、部分(時、分)に分けられます。Periodは年、月、日を扱い、分けられないカレンダー単位です。Oracle Java Tutorial (2024)によると、DurationとPeriodの選択はタスクの種類に依ります。正確な時間かカレンダー日付かです。

Durationの作成

最も一般的な方法は、Duration.between(Temporal start, Temporal end)です。Temporalは、Instant、LocalTime、LocalDateTime、ZonedDateTimeなどTemporalを実装する任意のタイプです。start - endの差を表すDurationを返します(負になり得ます)。

スタティックファクトリメソッド:Duration.ofSeconds(long)、ofMinutes(long)、ofHours(long)、ofDays(long)、ofMillis(long)、ofNanos(long)。任意の単位にはof(long amount, TemporalUnit unit)あります—ChronoUnit.HOURS、ChronoUnit.MINUTESなど。

parse(CharSequence)メソッドは、ISO-8601形式の文字列を受け付けます:“PT1H30M”(1時間30分)、“PT45S”(45秒)、“P2DT3H”(2日3時間)。文字列は常に“PT”(Period of Time)で始まります。

kotlin
val betweenMoments = Duration.between(
    Instant.parse("2026-07-21T10:00:00Z"),
    Instant.parse("2026-07-21T14:30:00Z")
)

val fromMinutes = Duration.ofMinutes(90)
val fromHours = Duration.ofHours(2)
val parsed = Duration.parse("PT1H30M")

Durationの演算

Durationは完全な演算セットをサポートしています。plus(Duration)minus(Duration)メソッドは、別の続き時間を追加または減算します。plusDays()、plusHours()、plusMinutes()、plusSeconds()、plusMillis()、plusNanos()メソッドは特定の単位を追加します。

乗算と除算には、multipliedBy(long)とdividedBy(long)を使用します。Duration.multipliedBy(2)は続き時間を倍にし、Duration.dividedBy(3)は切り捨てで3つに分けます。negated()メソッドは符号を反転します—正が負になり、その逆もします。

abs()メソッドは絶対値(正)のDurationを返します。isNegative()とisZero()は確認用です。toDays()、toHours()、toMinutes()、toSeconds()、toMillis()、toNanos()でそれぞれの単位に変換します。

kotlin
val oneHour = Duration.ofHours(1)
val twoHours = oneHour.plus(Duration.ofMinutes(60))
val halfHour = oneHour.dividedBy(2)

val minutes = twoHours.toMinutes()
val absDuration = (Duration.ofHours(-1)).abs()

Durationの比較

DurationはComparableインタフェースを実装しており、続き時間を自然に比較できます。compareTo()メソッドは負の数、0、正の数を返します。isNegative()とisZero()は簡単な確認用です。明示的な比較にはequals()を使用します—秒とナノ秒が一致すれば2つのDurationは等しいです。

Durationは負になることがあるため、“大きい”“小さい”の比較は符号を考慮します。-5分は2分より小さいです。abs()メソッドは方向に関わらず“絶対的”な長さを比較するのに役立ちます。

Kotlinでは、Durationは演算子オーバーロードにより比較演算子をサポートしています:a < b、a > b、a <= b。また、plusとminusも演算子として使用できます:a + b、a - b。

kotlin
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)

if (short < long) {
    Log.d("Duration", "5分は10より小さいです")
}

val negative = Duration.ofMinutes(-3)
Log.d("Duration", "負の値: ${negative.isNegative()}")

Android実務でのDuration

1つ目の例は、サーバーとの定期同期の設定です。Durationを使って同期間隔を計算し、更新なしの時間制限が超えたかを確認します。

kotlin
data class SyncConfig(
    val interval: Duration = Duration.ofMinutes(15),
    val retryDelay: Duration = Duration.ofSeconds(30)
)

fun calculateNextSync(
    lastSync: Instant,
    config: SyncConfig
): Duration {
    val elapsed = Duration.between(lastSync, Instant.now())
    return config.interval.minus(elapsed)
        .coerceAtLeast(Duration.ZERO)
}

2つ目の例は、パフォーマンスログのための処理実行時間の測定です。

kotlin
fun measureExecution(
    tag: String,
    block: () -> Unit
) {
    val start = Instant.now()
    block()
    val duration = Duration.between(start, Instant.now())
    Log.d(tag, "${duration.toMillis()} msで実行されました")
}

3つ目の例は、タイマーの残り時間の計算です(例えば、キャンペーン終了までのカウントダウン)。

kotlin
class CountdownTimer(
    private val expiresAt: Instant
) {
    fun getRemainingTime(): Duration {
        val remaining = Duration.between(
            Instant.now(), expiresAt
        )
        return remaining.coerceAtLeast(Duration.ZERO)
    }

    fun isExpired(): Boolean = getRemainingTime() == Duration.ZERO
}

Durationの文字列変換

toString()メソッドは、DurationをISO-8601形式で返します:“PT1H30M”(1時間30分)、“PT45.5S”(45.5秒)。この形式はマシン間のデータ交換に便利ですが、ユーザー表示には向きません。

人間が読める形式には、toDays()、toHours()、toMinutes()、toSeconds()を使用して文字列を手動で構築します。例:“${days} 日 ${hours} 時 ${minutes} 分”。toHours()は総時間数を返し、日の中の時間ではないことに注意してください。

Durationを要素に分解するには、val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60の形式を使用します。Apache Commons Lang (2024)によると、DurationFormatUtilsライブラリは追加のフォーマット機能を提供しています。

kotlin
fun formatDuration(duration: Duration): String {
    val hours = duration.toHours()
    val minutes = duration.toMinutes() % 60
    val seconds = duration.seconds % 60

    return buildString {
        if (hours > 0) append("${hours} h ")
        if (minutes > 0) append("${minutes} min ")
        append("${seconds} sec")
    }
}

よくある豁つ

1つ目の豁は、日付扱い時のDurationとPeriodの混同です。Durationは秒を測定するため、Duration.ofDays(1)は夏時間に関係なく常24時間(86400秒)です。カレンダー日が必要な場合は、Period.ofDays(1)を使用します。

2つ目の豁は、変換時にナノ秒を失うことです。Durationはナノ秒を保持できますが、toMillis()とtoSeconds()はそれらを捨てます。正確な計算には、toNanos()を使用するか、プリミティブに変換せずにDurationを直接扱うことです。

3つ目の豁は、負のDurationを無視することです。Duration.between(start, end)はstart - endを返し、startがendより後の場合、Durationは負になります。abs()で絶対値を得られ、isNegative()で引数の順序を確認できます。

4つ目の豁は、UIに対する不正确なDurationのフォーマットです。Duration.toString()はISO-8601を返し、人間には読めません。ユーザー表示には常にtoHours()、toMinutes()、toSeconds()を使用してDurationを手動でフォーマットし、正しい除算の余りを使用します。

よくある質問

Durationは負になりますか?

はい、Durationは負になります。Duration.between(start, end)はstart - endを返し、startがendより後の場合、Durationは負になります。絶対値を得るにはabs()、確認にはisNegative()を使用します。

2つのDurationを足す方法は?

plus(Duration)メソッドか、Kotlinの+ 演算子を使用します:duration1 + duration2。結果は新しいDurationです。minus(Duration)メソッドは一つのDurationからもう一つを減算します。すべての演算は不変で新しいオブジェクトを返します。

Duration.ofDays(1)とPeriod.ofDays(1)の違いは?

Duration.ofDays(1)は常24時間(86400秒)です。Period.ofDays(1)は1カレンダー日で、DST中は23または25時間になることがあります。正確な時間計算にはDurationを、カレンダー計算にはPeriodを使用します。

Durationをミリ秒に変換する方法は?

toMillis()メソッドを使用します。longを返し、Durationのミリ秒数を表します。ナノ秒にはtoNanos()を使用します。注意:toNanos()は> 292年でlongがオーバーフローする可能性があります。大きなDurationにはtoSeconds()またはtoMinutes()を使用します。

二つのLocalTimeの間のDurationを計算する方法は?

Duration.between(startTime, endTime)を使用します。endTimeがstartTimeより小さい場合(夜勤)、Durationは負になります。endTimeが翌日とみなされる場合は、24時間を追加します:duration.plusHours(24)。

まとめ

  • Duration — ナノ秒精度の時間ベースの続き時間のための不変クラス。間隔測定に最適。
  • Periodとの主な違い—Durationは秒(物理的時間)を測定し、Periodはカレンダー単位を測定すること。
  • Duration.between()で瞬間の差を、またはスタティックファクトリofMinutes、ofHours、ofDaysで作成。
  • 演算をサポート:plus、minus、multipliedBy、dividedBy、Comparableとabsによる比較。
  • AndroidではDurationはタイムアウト、同期間隔、タイマー、パフォーマンス測定に使用。
  • ユーザー表示時はDurationを手動フォーマット—toString()はISO-8601を出力し、人が読めない。
  • Durationは負になることがあるため、isNegative()を確認し、abs()を使用して正しく計算。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください