Duration — neměnná třída z balíčku java.time, představující dobu trvání mezi dvěma okamžiky v sekundách a nanosekundách. Duration měří časově založené množství času — hodiny, minuty, sekundy, milisekundy a nanosekundy. Podle specifikace Oracle Java 17 (2024), na rozdíl od Period (který měří roky-měsíce-dny), Duration pracuje s přesnými časovými jednotkami a nezávisí na kalendáři.
Hlavní body
Duration — je třída, která modeluje množství času v sekundách a nanosekundách. Představuje časově založenou dobu trvání, tedy fyzický počet sekund, který není vázán na kalendář. Duration lze reprezentovat jako „125 minut” nebo „2 hodiny 5 minut” — na rozdíl od Period, který řekne „2 měsíce”.
Vnitřní reprezentace Duration se skládá ze dvou polí: long seconds (sekundy) a int nanos (nanosekundy, od 0 do 999999999). Hodnota může být záporná — to znamená dobu trvání „zpět” v čase. Maximální hodnota je ±31557014167219200 sekund.
Podle Baeldung (2024), Duration je klíčovou třídou pro výpočet doby trvání operací, nastavení časových limitů a měření výkonu. Duration je neměnná a thread-safe, což umožňuje její použití ve vícevláknovém prostředí bez synchronizace.
Třída implementuje rozhraní Comparable, TemporalAmount a TemporalUnit. TemporalAmount umožňuje použití Duration v metodách plus/minus tříd LocalTime, LocalDateTime, Instant a ZonedDateTime.
Hlavní rozdíl — Duration měří přesný počet sekund (time-based), zatímco Period měří kalendářní jednotky (date-based): roky, měsíce, dny. Duration říká: „uběhlo 86400 sekund”. Period říká: „uběhl 1 den”. Rozdíl se projevuje při přechodu na letní čas — 1 den v Period je vždy roven 1 dni v kalendáři, zatímco 86400 sekund v Duration může odpovídat 23 nebo 25 hodinám při DST.
Duration se používá pro měření fyzického času: časové limity připojení, doba provedení požadavku, interval mezi dvěma Instant. Period se používá pro kalendářní výpočty: věk osoby (Period.between(datumNarození, dnes)), doba platnosti smlouvy.
Duration pracuje se sekundami a nanosekundami, proto jej lze dělit na části (hodiny, minuty). Period pracuje s roky, měsíci a dny — nedělitelnými kalendářními jednotkami. Podle Oracle Java Tutorial (2024), výběr mezi Duration a Period závisí na typu úkolu: přesný čas vs kalendářní data.
Nejběžnější způsob — Duration.between(Temporal start, Temporal end). Temporal může být Instant, LocalTime, LocalDateTime, ZonedDateTime — jakýkoli typ implementující Temporal. Metoda vrátí Duration představující rozdíl start - end (může být záporná).
Statické tovární metody: Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). Existuje také of(long amount, TemporalUnit unit) pro libovolné jednotky — ChronoUnit.HOURS, ChronoUnit.MINUTES a další.
Metoda parse(CharSequence) přijímá řetězec ve formátu ISO-8601: „PT1H30M” (1 hodina 30 minut), „PT45S” (45 sekund), „P2DT3H” (2 dny 3 hodiny). Řetězec vždy začíná „PT” (Period of Time).
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 podporuje kompletní sadu aritmetických operací. Metody plus(Duration) a minus(Duration) přidávají nebo odebírají jinou dobu trvání. Metody plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() — pro přesné přidávání jednotek.
Pro násobení a dělení se používají multipliedBy(long) a dividedBy(long). Duration.multipliedBy(2) zdvojnásobí dobu trvání. Duration.dividedBy(3) rozdělí na tři části se zaokrouhlením dolů. Metoda negated() obrátí znaménko — kladná se stane zápornou a naopak.
Metoda abs() vrátí Duration s absolutní (kladnou) hodnotou. isNegative() a isZero() — kontroly. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos() — převod do odpovídajících jednotek.
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 implementuje rozhraní Comparable, což umožňuje přirozené porovnávání dob trvání. Metoda compareTo() vrátí záporné číslo, nulu nebo kladné číslo. Metody isNegative() a isZero() — rychlé kontroly. Pro explicitní porovnání použijte equals() — dvě Duration jsou stejná, pokud mají stejné sekundy a nanosekundy.
Protože Duration může být záporné, porovnání „větší” nebo „menší” funguje s ohledem na znaménko. -5 minut je menší než 2 minuty. Metoda abs() je užitečná, pokud potřebujete porovnávat „absolutní” délky bez ohledu na směr.
V Kotlinu Duration podporuje operátory porovnání pomocí přetěžování operátorů: a < b, a > b, a <= b. Také plus a minus jsou k dispozici jako operátory: a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5 min je méně než 10")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "Záporný: ${negative.isNegative()}")
První příklad — nastavení periodické synchronizace se serverem. Duration se používá pro výpočet intervalu mezi synchronizacemi a kontrolu, zda nebyl překročen časový limit bez aktualizace.
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)
}
Druhý příklad — měření doby provedení operace pro protokolování výkonu.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "Provedeno za ${duration.toMillis()} ms")
}
Třetí příklad — výpočet zbývajícího času časovače (například pro odpočet do konce akce).
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
}
Metoda toString() vrátí Duration ve formátu ISO-8601: „PT1H30M” (1 hodina 30 minut), „PT45.5S” (45.5 sekund). Tento formát je vhodný pro strojovou výměnu, ale ne pro zobrazení uživateli.
Pro formát čitelný pro člověka použijte toDays(), toHours(), toMinutes(), toSeconds() s ručním sestavením řetězce. Například: „${days} d ${hours} h ${minutes} min”. Všimněte si, že toHours() vrátí celkový počet hodin, nikoli hodiny v rámci dne.
Pro rozdělení Duration na součásti se používá vzorec: val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. Podle Apache Commons Lang (2024), knihovna DurationFormatUtils poskytuje další možnosti formátování.
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")
}
}
První chyba — záměna Duration a Period při práci s daty. Duration měří sekundy, proto Duration.ofDays(1) je vždy 24 hodin (86400 sekund), bez ohledu na přechod na letní čas. Pokud potřebujete kalendářní den, použijte Period.ofDays(1).
Druhá chyba — ztráta nanosekund při převodu. Duration může ukládat nanosekundy, ale toMillis() a toSeconds() je zahazují. Pro přesné výpočty použijte toNanos() nebo pracujte přímo s Duration, bez převodu na primitivní typy.
Třetí chyba — ignorování záporných Duration. Duration.between(start, end) vrátí start - end. Pokud je start po end, Duration bude záporné. Metoda abs() pomáhá získat absolutní hodnotu a isNegative() — zkontrolovat pořadí argumentů.
Čtvrtá chyba — nesprávné formátování Duration pro UI. Duration.toString() vrátí ISO-8601, který je nečitelný. Vždy formátujte Duration ručně pro zobrazení uživateli, pomocí toHours(), toMinutes() a toSeconds() se správným zbytkem po dělení.
Často kladené otázky
Ano, Duration může být záporné. Duration.between(start, end) vrátí start - end. Pokud je start po end, Duration bude záporné. Použijte abs() pro získání absolutní hodnoty nebo isNegative() pro kontrolu.
Použijte metodu plus(Duration) nebo operátor + v Kotlinu: duration1 + duration2. Výsledek — nové Duration. Metoda minus(Duration) odečítá jednu dobu trvání od druhé. Všechny operace jsou neměnné a vracejí nový objekt.
Duration.ofDays(1) je vždy 24 hodin (86400 sekund). Period.ofDays(1) je 1 kalendářní den, který při DST může být 23 nebo 25 hodin. Pro výpočty s přesným časem použijte Duration, pro kalendářní — Period.
Použijte metodu toMillis(). Vrátí long — počet milisekund v Duration. Pro nanosekundy použijte toNanos(). Pozor: toNanos() může přetéct long při hodnotách > 292 let. Pro velké Duration použijte toSeconds() nebo toMinutes().
Použijte Duration.between(startTime, endTime). Pokud je endTime menší než startTime (noční směna), Duration bude záporné. Přidejte 24 hodin: duration.plusHours(24), pokud předpokládáte, že endTime je následující den.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také