Duration — clasĄ imuabilĄ din pachetul java.time, care reprezintĄ durata dintre două momente de timp în secunde și nanosecunde. Duration măsoară cantitatea de timp bazată pe timp — ore, minute, secunde, milisecunde și nanosecunde. Conform specificației Oracle Java 17 (2024), spre deosebire de Period (care măsoară ani-luni-zile), Duration lucrează cu unități exacte de timp și nu depinde de calendar.
Principalele puncte
Duration — este o clasă care modelează cantitatea de timp în secunde și nanosecunde. Reprezintă durata bazată pe timp, adică numărul fizic de secunde, nelegat de calendar. Duration poate fi reprezentat ca „125 de minute” sau „2 ore și 5 minute” — spre deosebire de Period, care va spune „2 luni”.
Reprezentarea internĄ a Duration constă din două câmpuri: long seconds (secunde) și int nanos (nanosecunde, de la 0 la 999999999). Valoarea poate fi negativă — aceasta înseamnă durata „înapoi” în timp. Valoarea maximă este ±31557014167219200 secunde.
Conform Baeldung (2024), Duration este clasa cheie pentru calcularea duratei operațiilor, setarea timeout-urilor și măsurarea performanței. Duration este imuabilă și thread-safe, ceea ce permite utilizarea sa în medii multi-thread fără sincronizare.
Clasa implementează interfețele Comparable, TemporalAmount și TemporalUnit. TemporalAmount permite utilizarea Duration în metodele plus/minus ale claselor LocalTime, LocalDateTime, Instant și ZonedDateTime.
Diferența principală — Duration măsoară numărul exact de secunde (time-based), iar Period măsoară unitățile calendaristice (date-based): ani, luni, zile. Duration spune: „au trecut 86400 de secunde”. Period spune: „a trecut 1 zi”. Diferența se manifestă la trecerea la ora de vară — 1 zi în Period este întotdeauna egală cu 1 zi în calendar, iar 86400 de secunde în Duration pot corespunde la 23 sau 25 de ore în DST.
Duration este folosită pentru măsurarea timpului fizic: timeout-uri de conexiune, timpul de execuție a cererii, intervalul dintre două Instant. Period este folosită pentru calcule calendaristice: vârsta unei persoane (Period.between(dataNașterii, azi)), perioada de valabilitate a contractului.
Duration lucrează cu secunde și nanosecunde, deci poate fi împărțită în părți (ore, minute). Period lucrează cu ani, luni și zile — unități calendaristice indivizibile. Conform Oracle Java Tutorial (2024), alegerea între Duration și Period depinde de tipul sarcinii: timp exact vs date calendaristice.
Cel mai frecvent mod — Duration.between(Temporal start, Temporal end). Temporal poate fi Instant, LocalTime, LocalDateTime, ZonedDateTime — orice tip care implementează Temporal. Metoda returnează o Duration reprezentând diferența start - end (poate fi negativă).
Metode de fabrică statice: Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). Există și of(long amount, TemporalUnit unit) pentru unități arbitrare — ChronoUnit.HOURS, ChronoUnit.MINUTES și altele.
Metoda parse(CharSequence) acceptă un șir în format ISO-8601: „PT1H30M” (1 oră 30 minute), „PT45S” (45 secunde), „P2DT3H” (2 zile 3 ore). Șirul începe întotdeauna cu „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 suportă un set complet de operații aritmetice. Metodele plus(Duration) și minus(Duration) adaugă sau scad o altă durată. Metodele plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() — pentru adăugarea precisă a unităților.
Pentru înmulțire și împărțire se folosesc multipliedBy(long) și dividedBy(long). Duration.multipliedBy(2) dublează durata. Duration.dividedBy(3) împarte în trei părți cu rotunjire în jos. Metoda negated() inversează semnul — pozitivă devine negativă și invers.
Metoda abs() returnează Duration cu valoarea absolută (pozitivă). isNegative() și isZero() — verificări. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos() — conversia în unitățile corespunzătoare.
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 implementează interfața Comparable, ceea ce permite compararea naturală a duratelor. Metoda compareTo() returnează un număr negativ, zero sau pozitiv. Metodele isNegative() și isZero() — verificări rapide. Pentru comparare explicită folosiți equals() — două Duration sunt egale dacă au aceleași secunde și nanosecunde.
Deoarece Duration poate fi negativă, compararea „mai mare” sau „mai mic” funcționează ținând cont de semn. -5 minute este mai mic decât 2 minute. Metoda abs() este utilă dacă trebuie să comparați lungimi „absolute” independent de direcție.
În Kotlin, Duration suportă operatorii de comparare prin supraîncărcarea operatorilor: a < b, a > b, a <= b. De asemenea, plus și minus sunt disponibili ca operatori: a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5 min este mai puțin de 10")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "Negativ: ${negative.isNegative()}")
Primul exemplu — configurarea sincronizării periodice cu serverul. Duration este folosită pentru calcularea intervalului între sincronizări și verificarea dacă limita de timp fără actualizare a fost depășită.
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)
}
Al doilea exemplu — măsurarea timpului de execuție a operației pentru logarea performanței.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "Executat în ${duration.toMillis()} ms")
}
Al treilea exemplu — calcularea timpului rămas al timer-ului (de exemplu, pentru numărătoarea inversă până la sfârșitul unei promoții).
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() returnează Duration în format ISO-8601: „PT1H30M” (1 oră 30 minute), „PT45.5S” (45.5 secunde). Acest format este convenabil pentru schimbul mașină-mașină, dar nu pentru afișarea utilizatorului.
Pentru un format lizibil de către om, folosiți toDays(), toHours(), toMinutes(), toSeconds() cu construirea manuală a șirului. De exemplu: „${days} z ${hours} h ${minutes} min”. Rețineți că toHours() returnează numărul total de ore, nu orele din zi.
Pentru descompunerea Duration în componente se folosește formula: val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. Conform Apache Commons Lang (2024), biblioteca DurationFormatUtils oferă capacități suplimentare de formatare.
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")
}
}
Prima eroare — confuzia între Duration și Period la lucrul cu datele. Duration măsoară secunde, deci Duration.ofDays(1) este întotdeauna 24 de ore (86400 secunde), indiferent de trecerea la ora de vară. Dacă aveți nevoie de o zi calendaristică, folosiți Period.ofDays(1).
A doua eroare — pierderea nanosecundelor la conversie. Duration poate stoca nanosecunde, dar toMillis() și toSeconds() le elimină. Pentru calcule precise, folosiți toNanos() sau lucrați direct cu Duration, fără conversie în tipuri primitive.
A treia eroare — ignorarea Duration negative. Duration.between(start, end) returnează start - end. Dacă start este după end, Duration va fi negativă. Metoda abs() ajută la obținerea valorii absolute, iar isNegative() — la verificarea ordinii argumentelor.
A patra eroare — formatarea incorectă a Duration pentru UI. Duration.toString() returnează ISO-8601, care este ilizibil. Formatați întotdeauna Duration manual pentru afișarea utilizatorului, folosind toHours(), toMinutes() și toSeconds() cu restul corect al împărțirii.
Întrebări frecvente
Da, Duration poate fi negativă. Duration.between(start, end) returnează start - end. Dacă start este după end, Duration va fi negativă. Folosiți abs() pentru a obține valoarea absolută sau isNegative() pentru verificare.
Folosiți metoda plus(Duration) sau operatorul + în Kotlin: duration1 + duration2. Rezultatul — o nouă Duration. Metoda minus(Duration) scade o durată din alta. Toate operațiile sunt imuabile și returnează un obiect nou.
Duration.ofDays(1) este întotdeauna 24 de ore (86400 secunde). Period.ofDays(1) este 1 zi calendaristică, care în DST poate fi de 23 sau 25 de ore. Pentru calcule cu timp exact folosiți Duration, pentru cele calendaristice — Period.
Folosiți metoda toMillis(). Returnează un long — numărul de milisecunde în Duration. Pentru nanosecunde folosiți toNanos(). Atenție: toNanos() poate depăși domeniul long la valori > 292 de ani. Pentru Duration mari folosiți toSeconds() sau toMinutes().
Folosiți Duration.between(startTime, endTime). Dacă endTime este mai mic decât startTime (tura de noapte), Duration va fi negativă. Adăugați 24 de ore: duration.plusHours(24), dacă presupuneți că endTime este ziua următoare.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și