Duration — uma classe imutável do pacote java.time que representa a duração entre dois momentos no tempo em segundos e nanossegundos. Duration mede quantidades de tempo baseadas em tempo — horas, minutos, segundos, milissegundos e nanossegundos. De acordo com a especificação da Oracle Java 17 (2024), ao contrário de Period (que mede anos-meses-dias), Duration trabalha com unidades de tempo precisas e não depende do calendário.
Pontos principais
Duration é uma classe que modela a quantidade de tempo em segundos e nanossegundos. Ela representa uma duração baseada em tempo, ou seja, um número físico de segundos não vinculado a um calendário. Duration pode ser pensada como “125 minutos” ou “2 horas 5 minutos” — ao contrário de Period, que diria “2 meses”.
A representação interna de Duration consiste em dois campos: long seconds (segundos) e int nanos (nanossegundos, de 0 a 999999999). O valor pode ser negativo — o que significa uma duração “para trás” no tempo. O valor máximo é ±31557014167219200 segundos.
De acordo com Baeldung (2024), Duration é uma classe chave para calcular duração de operações, configurar timeouts e medir desempenho. Duration é imutável e thread-safe, permitindo seu uso em ambientes multithread sem sincronização.
A classe implementa as interfaces Comparable, TemporalAmount e TemporalUnit. TemporalAmount permite usar Duration nos métodos plus/minus das classes LocalTime, LocalDateTime, Instant e ZonedDateTime.
A principal diferença é que Duration mede o número exato de segundos (baseado em tempo), enquanto Period mede unidades de calendário (baseado em data): anos, meses, dias. Duration diz: “86400 segundos se passaram.” Period diz: “1 dia se passou.” A diferença torna-se aparente durante as mudanças de horário de verão — 1 dia em Period é sempre 1 dia de calendário, enquanto 86400 segundos em Duration podem corresponder a 23 ou 25 horas durante o DST.
Duration é usado para medir tempo físico: timeouts de conexão, tempo de execução de consultas, intervalos entre dois Instant. Period é usado para cálculos de calendário: idade de uma pessoa (Period.between(dateOfBirth, today)), duração de um contrato.
Duration trabalha com segundos e nanossegundos, portanto pode ser dividida em partes (horas, minutos). Period trabalha com anos, meses e dias — unidades de calendário indivisíveis. De acordo com o Oracle Java Tutorial (2024), a escolha entre Duration e Period depende do tipo de tarefa: tempo preciso vs datas de calendário.
A forma mais comum é Duration.between(Temporal start, Temporal end). Temporal pode ser Instant, LocalTime, LocalDateTime, ZonedDateTime — qualquer tipo que implemente Temporal. O método retorna uma Duration representando a diferença start - end (pode ser negativa).
Métodos de fábrica estáticos: Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). Também existe of(long amount, TemporalUnit unit) para unidades arbitrárias — ChronoUnit.HOURS, ChronoUnit.MINUTES e outras.
O método parse(CharSequence) aceita uma string no formato ISO-8601: “PT1H30M” (1 hora 30 minutos), “PT45S” (45 segundos), “P2DT3H” (2 dias 3 horas). A string sempre começa com “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 suporta um conjunto completo de operações aritméticas. Os métodos plus(Duration) e minus(Duration) adicionam ou subtraem outra duração. Os métodos plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() — para adicionar unidades específicas.
Para multiplicação e divisão, use multipliedBy(long) e dividedBy(long). Duration.multipliedBy(2) duplica a duração. Duration.dividedBy(3) divide em três partes com arredondamento para baixo. O método negated() inverte o sinal — positivo torna-se negativo e vice-versa.
O método abs() retorna uma Duration com valor absoluto (positivo). isNegative() e isZero() são verificações. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos() convertem para as unidades correspondentes.
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 implementa a interface Comparable, permitindo comparar durações naturalmente. O método compareTo() retorna um número negativo, zero ou positivo. isNegative() e isZero() são verificações rápidas. Para comparação explícita, use equals() — duas Duration são iguais se seus segundos e nanossegundos coincidirem.
Como Duration pode ser negativa, comparações “maior que” ou “menor que” funcionam considerando o sinal. -5 minutos é menor que 2 minutos. O método abs() é útil para comparar comprimentos “absolutos” independentemente da direção.
Em Kotlin, Duration suporta operadores de comparação através de sobrecarga de operadores: a < b, a > b, a <= b. Plus e minus também estão disponíveis como operadores: a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5 min é menor que 10")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "Negativo: ${negative.isNegative()}")
O primeiro exemplo é configurar a sincronização periódica com o servidor. Duration é usada para calcular o intervalo entre sincronizações e verificar se o limite de tempo sem atualização foi excedido.
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)
}
O segundo exemplo é medir o tempo de execução de uma operação para registro de desempenho.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "Executado em ${duration.toMillis()} ms")
}
O terceiro exemplo é calcular o tempo restante de um temporizador (por exemplo, contagem regressiva até o fim de uma promoção).
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
}
O método toString() retorna Duration no formato ISO-8601: “PT1H30M” (1 hora 30 minutos), “PT45.5S” (45.5 segundos). Este formato é conveniente para troca entre máquinas, mas não para exibição ao usuário.
Para formato legível por humanos, use toDays(), toHours(), toMinutes(), toSeconds() seguido de montagem manual da string. Por exemplo: “${days} d ${hours} h ${minutes} min”. Note que toHours() retorna o número total de horas, não as horas dentro do dia.
Para decompor Duration em componentes, use a fórmula: val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. De acordo com Apache Commons Lang (2024), a biblioteca DurationFormatUtils fornece capacidades adicionais de formatação.
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")
}
}
O primeiro erro é confundir Duration e Period ao trabalhar com datas. Duration mede segundos, portanto Duration.ofDays(1) é sempre 24 horas (86400 segundos), independentemente das mudanças de horário de verão. Se precisar de um dia de calendário, use Period.ofDays(1).
O segundo erro é perder nanossegundos durante a conversão. Duration pode armazenar nanossegundos, mas toMillis() e toSeconds() os descartam. Para cálculos precisos, use toNanos() ou trabalhe com Duration diretamente sem converter para primitivos.
O terceiro erro é ignorar Duration negativa. Duration.between(start, end) retorna start - end. Se start estiver depois de end, Duration será negativa. O método abs() ajuda a obter o valor absoluto, e isNegative() verifica a ordem dos argumentos.
O quarto erro é formatação incorreta de Duration para a interface do usuário. Duration.toString() retorna ISO-8601, que não é legível. Sempre formate Duration manualmente para exibição ao usuário usando toHours(), toMinutes() e toSeconds() com o resto correto da divisão.
Perguntas frequentes
Sim, Duration pode ser negativa. Duration.between(start, end) retorna start - end. Se start estiver depois de end, Duration será negativa. Use abs() para obter o valor absoluto ou isNegative() para verificar.
Use o método plus(Duration) ou o operador + em Kotlin: duration1 + duration2. O resultado é uma nova Duration. O método minus(Duration) subtrai uma duração de outra. Todas as operações são imutáveis e retornam um novo objeto.
Duration.ofDays(1) é sempre 24 horas (86400 segundos). Period.ofDays(1) é 1 dia de calendário, que durante o DST pode ser 23 ou 25 horas. Para cálculos de tempo precisos, use Duration; para cálculos de calendário, use Period.
Use o método toMillis(). Ele retorna um long — o número de milissegundos na Duration. Para nanossegundos, use toNanos(). Atenção: toNanos() pode estourar long em valores > 292 anos. Para Durations grandes, use toSeconds() ou toMinutes().
Use Duration.between(startTime, endTime). Se endTime for menor que startTime (turno noturno), Duration será negativa. Adicione 24 horas: duration.plusHours(24), se endTime for considerado o dia seguinte.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também