Duration — une classe immuable du paquet java.time représentant la durée entre deux moments dans le temps en secondes et nanosecondes. Duration mesure des quantités de temps basées sur le temps — heures, minutes, secondes, millisecondes et nanosecondes. Selon la spécification de Oracle Java 17 (2024), contrairement à Period (qui mesure les années-mois-jours), Duration travaille avec des unités de temps précises et ne dépend pas du calendrier.
Points clés
Duration est une classe qui modélise la quantité de temps en secondes et nanosecondes. Elle représente une durée basée sur le temps, c’est-à-dire un nombre physique de secondes non lié à un calendrier. Duration peut être considérée comme «125 minutes» ou «2 heures 5 minutes» — contrairement à Period, qui dirait «2 mois».
La représentation interne de Duration se compose de deux champs : long seconds (secondes) et int nanos (nanosecondes, de 0 à 999999999). La valeur peut être négative — cela signifie une durée «en arrière» dans le temps. La valeur maximale est ±31557014167219200 secondes.
Selon Baeldung (2024), Duration est une classe clé pour calculer la durée des opérations, définir des timeouts et mesurer les performances. Duration est immuable et thread-safe, ce qui permet son utilisation dans des environnements multithread sans synchronisation.
La classe implémente les interfaces Comparable, TemporalAmount et TemporalUnit. TemporalAmount permet d’utiliser Duration dans les méthodes plus/minus des classes LocalTime, LocalDateTime, Instant et ZonedDateTime.
La principale différence est que Duration mesure le nombre exact de secondes (basé sur le temps), tandis que Period mesure les unités de calendrier (basées sur la date) : années, mois, jours. Duration dit : «86400 secondes se sont écoulées.» Period dit : «1 jour s’est écoulé.» La différence devient apparente lors des changements d’heure d’été — 1 jour dans Period est toujours 1 jour calendaire, tandis que 86400 secondes dans Duration peuvent correspondre à 23 ou 25 heures pendant le DST.
Duration est utilisée pour mesurer le temps physique : timeouts de connexion, temps d’exécution de requête, intervalles entre deux Instant. Period est utilisée pour les calculs calendaires : âge d’une personne (Period.between(dateOfBirth, today)), durée d’un contrat.
Duration travaille avec les secondes et les nanosecondes, elle peut donc être divisée en parties (heures, minutes). Period travaille avec les années, les mois et les jours — des unités calendaires indivisibles. Selon Oracle Java Tutorial (2024), le choix entre Duration et Period dépend du type de tâche : temps précis vs dates calendaires.
La méthode la plus courante est Duration.between(Temporal start, Temporal end). Temporal peut être Instant, LocalTime, LocalDateTime, ZonedDateTime — tout type implémentant Temporal. La méthode retourne une Duration représentant la différence start - end (peut être négative).
Méthodes d’usine statiques : Duration.ofSeconds(long), ofMinutes(long), ofHours(long), ofDays(long), ofMillis(long), ofNanos(long). Il existe aussi of(long amount, TemporalUnit unit) pour des unités arbitraires — ChronoUnit.HOURS, ChronoUnit.MINUTES et autres.
La méthode parse(CharSequence) accepte une chaîne au format ISO-8601 : «PT1H30M» (1 heure 30 minutes), «PT45S» (45 secondes), «P2DT3H» (2 jours 3 heures). La chaîne commence toujours par «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 prend en charge un ensemble complet d’opérations arithmétiques. Les méthodes plus(Duration) et minus(Duration) ajoutent ou soustraient une autre durée. Les méthodes plusDays(), plusHours(), plusMinutes(), plusSeconds(), plusMillis(), plusNanos() — pour ajouter des unités spécifiques.
Pour la multiplication et la division, utilisez multipliedBy(long) et dividedBy(long). Duration.multipliedBy(2) double la durée. Duration.dividedBy(3) divise en trois parties avec arrondi à l’inférieur. La méthode negated() inverse le signe — le positif devient négatif et vice versa.
La méthode abs() retourne une Duration avec une valeur absolue (positive). isNegative() et isZero() sont des vérifications. toDays(), toHours(), toMinutes(), toSeconds(), toMillis(), toNanos() convertissent dans les unités correspondantes.
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 implémente l’interface Comparable, ce qui permet de comparer les durées naturellement. La méthode compareTo() retourne un nombre négatif, zéro ou positif. isNegative() et isZero() sont des vérifications rapides. Pour une comparaison explicite, utilisez equals() — deux Duration sont égales si leurs secondes et nanosecondes coïncident.
Étant donné que Duration peut être négative, les comparaisons «plus grand que» ou «plus petit que» fonctionnent en tenant compte du signe. -5 minutes est inférieur à 2 minutes. La méthode abs() est utile pour comparer les longueurs «absolues» indépendamment de la direction.
En Kotlin, Duration prend en charge les opérateurs de comparaison via la surcharge d’opérateurs : a < b, a > b, a <= b. Plus et minus sont également disponibles comme opérateurs : a + b, a - b.
val short = Duration.ofMinutes(5)
val long = Duration.ofMinutes(10)
if (short < long) {
Log.d("Duration", "5 min est inférieur à 10")
}
val negative = Duration.ofMinutes(-3)
Log.d("Duration", "Négatif : ${negative.isNegative()}")
Le premier exemple est la configuration de la synchronisation périodique avec le serveur. Duration est utilisée pour calculer l’intervalle entre les synchronisations et vérifier si la limite de temps sans mise à jour a été dépassée.
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)
}
Le deuxième exemple est la mesure du temps d’exécution d’une opération pour la journalisation des performances.
fun measureExecution(
tag: String,
block: () -> Unit
) {
val start = Instant.now()
block()
val duration = Duration.between(start, Instant.now())
Log.d(tag, "Exécuté en ${duration.toMillis()} ms")
}
Le troisième exemple est le calcul du temps restant d’un minuteur (par exemple, le compte à rebours jusqu’à la fin d’une promotion).
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
}
La méthode toString() retourne Duration au format ISO-8601 : «PT1H30M» (1 heure 30 minutes), «PT45.5S» (45.5 secondes). Ce format est pratique pour l’échange entre machines mais pas pour l’affichage utilisateur.
Pour un format lisible par l’humain, utilisez toDays(), toHours(), toMinutes(), toSeconds() suivis de la construction manuelle de la chaîne. Par exemple : «${days} j ${hours} h ${minutes} min». Notez que toHours() retourne le nombre total d’heures, pas les heures dans la journée.
Pour décomposer Duration en composants, utilisez la formule : val hours = duration.toHours(); val minutes = duration.toMinutes() % 60; val seconds = duration.seconds % 60. Selon Apache Commons Lang (2024), la bibliothèque DurationFormatUtils fournit des capacités de formatage supplémentaires.
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")
}
}
La première erreur est de confondre Duration et Period lors du travail avec les dates. Duration mesure les secondes, donc Duration.ofDays(1) est toujours 24 heures (86400 secondes), indépendamment des changements d’heure d’été. Si vous avez besoin d’un jour calendaire, utilisez Period.ofDays(1).
La deuxième erreur est la perte de nanosecondes lors de la conversion. Duration peut stocker des nanosecondes, mais toMillis() et toSeconds() les suppriment. Pour des calculs précis, utilisez toNanos() ou travaillez directement avec Duration sans convertir en primitifs.
La troisième erreur est d’ignorer les Duration négatives. Duration.between(start, end) retourne start - end. Si start est après end, Duration sera négative. La méthode abs() aide à obtenir la valeur absolue, et isNegative() vérifie l’ordre des arguments.
La quatrième erreur est un formatage incorrect de Duration pour l’interface utilisateur. Duration.toString() retourne ISO-8601, qui n’est pas lisible. Formatez toujours Duration manuellement pour l’affichage utilisateur en utilisant toHours(), toMinutes() et toSeconds() avec le reste correct de la division.
Questions fréquentes
Oui, Duration peut être négative. Duration.between(start, end) retourne start - end. Si start est après end, Duration sera négative. Utilisez abs() pour obtenir la valeur absolue ou isNegative() pour vérifier.
Utilisez la méthode plus(Duration) ou l’opérateur + en Kotlin : duration1 + duration2. Le résultat est une nouvelle Duration. La méthode minus(Duration) soustrait une durée d’une autre. Toutes les opérations sont immuables et retournent un nouvel objet.
Duration.ofDays(1) est toujours 24 heures (86400 secondes). Period.ofDays(1) est 1 jour calendaire, qui pendant le DST peut être de 23 ou 25 heures. Pour des calculs de temps précis, utilisez Duration ; pour des calculs calendaires, utilisez Period.
Utilisez la méthode toMillis(). Elle retourne un long — le nombre de millisecondes dans la Duration. Pour les nanosecondes, utilisez toNanos(). Attention : toNanos() peut déborder long pour des valeurs > 292 ans. Pour les grandes Durations, utilisez toSeconds() ou toMinutes().
Utilisez Duration.between(startTime, endTime). Si endTime est inférieur à startTime (quart de nuit), Duration sera négative. Ajoutez 24 heures : duration.plusHours(24), si endTime est supposé être le lendemain.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi