Kotlin の Duration は、時間の長さ(経過時間)を 型安全かつ可読性高く 扱うために設計された標準ライブラリのクラスです。
Android、サーバーサイド、Coroutine を用いた非同期処理において、現在では 事実上の標準 と言ってよい存在になっています。
本記事では、単なる使い方紹介に留まらず、
- Duration が解決する問題
- 正確な内部仕様(誤解されやすいポイント)
- Coroutine・Java との関係
- 実務での注意点・落とし穴
まで踏み込んで解説します。
目次
Duration とは何か
Duration は kotlin.time パッケージ に含まれるクラスで、「◯秒」「◯分」といった 時間の長さそのもの を表します。
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
なぜ Duration が必要なのか
従来のコードでは、以下のような問題がありました。
Thread.sleep(1000)
- 1000 は「秒」なのか「ミリ秒」なのか分からない
- 単位の取り違えが起こりやすい
- 型安全でない(Long や Int のまま渡してしまう)
Duration は 単位を型として持たせる ことで、これらの問題を根本から解決します。
Duration の基本的な生成方法
拡張プロパティ(最も一般的)
val d1 = 1.seconds
val d2 = 500.milliseconds
val d3 = 2.minutes
val d4 = 1.hours
利用できる主な単位は以下の通りです。
| 単位 | プロパティ |
|---|---|
| ナノ秒 | nanoseconds |
| マイクロ秒 | microseconds |
| ミリ秒 | milliseconds |
| 秒 | seconds |
| 分 | minutes |
| 時間 | hours |
| 日 | days |
1.secondsのように コードを読めば意味が分かる ことが、Duration 最大のメリットです。
文字列からの生成(設定ファイル向け)
val d = Duration.parse("1h 30m")
"10s","500ms","1h 30m"などが利用可能toString()が出力する形式と互換
※ Kotlin 1.6 以降で安定利用可能です。
Duration の内部表現(重要)
Duration は「単純にナノ秒数を Long で持っている」わけではありません。
正確な説明
Durationは 1つの Long にエンコードされた内部表現を持つ- 値の大きさに応じて
- ナノ秒精度
- ミリ秒精度
を自動的に切り替えて保持する
- 表現可能な範囲を超えると
Duration.INFINITEとして扱われる
この設計により、
- 小さい時間は高精度に
- 非常に大きい時間も効率的に
扱えるようになっています。
Duration の計算(四則演算)
加算・減算
val total = 1.seconds + 500.milliseconds
val remain = 5.minutes - 30.seconds
乗算・除算
val doubled = 2.seconds * 2
val half = 10.seconds / 2
比較
if (1.seconds > 500.milliseconds) {
println("長い")
}
すべて 単位を意識せず安全に計算可能 です。
単位変換
val d = 1500.milliseconds
d.inSeconds // 1.5 (Double)
d.inWholeSeconds // 1 (Long)
d.inMilliseconds // 1500
注意点
inSecondsはDouble(小数あり)inWholeSecondsは切り捨てLongDuration.INFINITEを変換するとLong.MAX_VALUE/Long.MIN_VALUEが返る場合がある
Coroutine との統合(必須知識)
Duration は Coroutine API と完全に統合 されています。
delay
delay(1.seconds)
withTimeout
withTimeout(3.seconds) {
// 処理
}
withTimeoutOrNull
val result = withTimeoutOrNull(2.seconds) {
heavyTask()
}
注意点
withTimeoutに 0 以下の Duration を渡すと即タイムアウト- 処理がキャンセル可能である必要がある
Java との相互運用
Kotlin Duration と Java Duration は別物
| Kotlin | Java |
|---|---|
kotlin.time.Duration | java.time.Duration |
| 拡張プロパティあり | なし |
| Coroutine と親和性高 | 低い |
相互変換
import java.time.Duration as JavaDuration
val kotlinDuration = 5.seconds
val javaDuration = kotlinDuration.toJavaDuration()
val back = javaDuration.toKotlinDuration()
重要な注意点
- ±146年以内:ナノ秒精度で変換
- それ以上:ミリ秒精度に丸めが発生する可能性あり
特殊な Duration 値
Duration.ZERO
Duration.INFINITE
(-5).seconds
ZERO:0秒INFINITE:無限時間(タイムアウト無効化などに使用)- 負の Duration:比較・計算可能だが用途は慎重に
実務でよくある利用例
リトライ処理
val retryInterval = 500.milliseconds
repeat(3) {
if (tryConnect()) return
delay(retryInterval)
}
キャッシュの有効期限
val ttl = 10.minutes
if (now - cacheTime > ttl) {
refresh()
}
よくある落とし穴
Double 経由で Thread.sleep する
Thread.sleep(duration.inSeconds.toLong()) // 危険
正しい方法
Thread.sleep(duration.inWholeMilliseconds)
days の注意点(見落とされがち)
1.days
これは 常に 24時間 を意味します。
- 暦日
- サマータイム(DST)
- 日付境界
などは一切考慮されません。
「日付」ではなく「時間長」として理解する必要があります。
Duration を使うべき理由まとめ
- 単位ミスを防げる
- 可読性が圧倒的に高い
- Coroutine と自然に連携できる
- 保守性・レビュー性が向上する
まとめ
Kotlin の Duration は単なる便利クラスではなく、
- 型安全な時間表現
- 非同期処理の基盤
- Java との橋渡し
という重要な役割を担っています。
以上、KotlinのDurationについてでした。
最後までお読みいただき、ありがとうございました。










