Instant : qu'est-ce que c'est, timestamp et application dans le développement

Auteur : IT Sectr Publié le : 2026-07-13 Temps de lecture : 9 min

Instant — une classe immuable du paquetage java.time, représentant un point sur la ligne de temps en UTC avec une précision à la nanoseconde. Contrairement à LocalDateTime, Instant ne contient pas de date et d'heure dans un format lisible par l'humain — c'est une représentation machine d'un instant. Selon la spécification Oracle Java 17 (2024), Instant est conçu pour l'échange machine de timestamps et est un analogue de System.currentTimeMillis(), mais avec une précision à la nanoseconde.

Points Clés

  • Instant — un moment dans le temps en UTC avec une précision à la nanoseconde, immuable et thread-safe.
  • Stocke le temps comme le nombre de secondes depuis l'époque (1970-01-01T00:00:00Z) plus les nanosecondes.
  • Instant.now() renvoie le moment actuel en UTC indépendamment du fuseau horaire de l'appareil.
  • Pour la conversion vers un format lisible, atZone(ZoneId) est utilisé, renvoyant un ZonedDateTime.
  • Instant est le type préféré pour transmettre des timestamps dans les API et les systèmes distribués.

Qu'est-ce qu'Instant ?

Instant est une classe qui modélise un point unique sur la ligne de temps. Sa représentation interne se compose de deux champs : long seconds (le nombre de secondes depuis 1970-01-01T00:00:00Z) et int nanos (nanosecondes dans la seconde actuelle, de 0 à 999999999).

La plage de valeurs d'Instant est de -31557014167219200 à 31556889864403199 secondes depuis l'époque, couvrant environ 292 millions d'années dans les deux directions. C'est suffisant pour toutes les tâches pratiques, y compris les calculs astronomiques.

Selon Baeldung (2024), Instant est un pont entre les types lisibles par l'humain (LocalDateTime, ZonedDateTime) et les formats machine (timestamp en millisecondes). Instant est utilisé pour la journalisation, la mise en cache, la synchronisation et toutes les tâches où un moment absolu dans le temps est important.

La classe implémente les interfaces Comparable (pour comparer des instants) et Temporal (pour utilisation dans l'API commune java.time). Instant est immuable — toutes les méthodes renvoient un nouvel objet.

Instant vs Date vs Long

Avant Java 8, java.util.Date et System.currentTimeMillis() étaient utilisés pour travailler avec des instants temporels. Les deux approches ont des inconvénients. Date est mutable, non thread-safe, stocke le temps en millisecondes depuis l'époque, mais ses noms de méthodes sont obsolètes (getYear() renvoie 116 pour 2016).

Long (un timestamp simple) est rapide et compact, mais n'a pas de support intégré pour les nanosecondes, ne s'affiche pas dans un format lisible et nécessite une analyse manuelle lors du débogage. L'approche Long ne distingue pas non plus les types de données — un développeur pourrait passer une valeur incorrecte.

Instant résout tous ces problèmes. Il est immuable, contient des informations explicites de précision (secondes + nanosecondes), se sérialise au format ISO-8601 « 2026-07-21T15:00:00Z » et possède une API riche pour les conversions. Selon SonarSource (2024), Instant est le remplacement recommandé de Date dans tous les nouveaux projets.

Créer et Lire Instant

Le moment actuel est obtenu via Instant.now(). Contrairement à LocalDateTime.now(), Instant.now() renvoie toujours l'heure en UTC, ignorant le fuseau horaire de l'appareil. Cela le rend idéal pour les timestamps de serveur.

À partir de valeurs existantes : Instant.ofEpochSecond(long epochSecond) — depuis les secondes depuis l'époque, Instant.ofEpochMilli(long epochMilli) — depuis les millisecondes, Instant.parse(CharSequence) — depuis une chaîne ISO-8601 (« 2026-07-21T15:00:00Z »).

Pour la lecture : getEpochSecond() — le nombre de secondes depuis l'époque, toEpochMilli() — le nombre de millisecondes, getNano() — les nanosecondes. La méthode toString() renvoie une chaîne au format ISO-8601.

kotlin
val now = Instant.now()

val fromSeconds = Instant.ofEpochSecond(1784700000)
val fromMillis = Instant.ofEpochMilli(1784700000000)
val parsed = Instant.parse("2026-07-21T15:00:00Z")

val epochSecond = now.getEpochSecond()
val epochMilli = now.toEpochMilli()
val nanos = now.getNano()

Convertir Instant vers d'Autres Formats

Instant est converti en ZonedDateTime via atZone(ZoneId). Par exemple, Instant.now().atZone(ZoneId.of(« Europe/Moscow »)) renvoie un ZonedDateTime pour Moscou. Sans zone, la conversion est impossible — Instant ne contient pas d'informations calendaires.

Pour convertir Instant en LocalDateTime : atZone(ZoneId).toLocalDateTime(). Cette approche est explicite et ne perd pas d'informations. Conversion inverse : LocalDateTime.atZone(ZoneId).toInstant().

Pour la compatibilité avec java.util.Date : Date.from(instant) et date.toInstant(). C'est une conversion bidirectionnelle qui préserve la précision jusqu'aux millisecondes (Date ne supporte pas les nanosecondes). Pour java.sql.Timestamp, utilisez Timestamp.from(instant) avec le support des nanosecondes.

kotlin
val instant = Instant.now()

val zoned = instant.atZone(ZoneId.of("Europe/Moscow"))
val localDateTime = instant
    .atZone(ZoneId.systemDefault())
    .toLocalDateTime()

val oldDate = Date.from(instant)
val backToInstant = oldDate.toInstant()

Instant et Fuseaux Horaires

La caractéristique clé d'Instant est qu'il est complètement indépendant des fuseaux horaires. Instant.now() renvoie le même résultat sur n'importe quel appareil, n'importe où dans le monde. Ceci est réalisé en fixant le temps en UTC.

Un fuseau horaire n'est nécessaire que pour afficher Instant à un humain. Pour cela, atZone(ZoneId) est utilisé. ZoneId.systemDefault() renvoie le fuseau horaire de l'appareil défini dans le système d'exploitation. ZoneOffset.UTC est la constante pour UTC.

Dans les systèmes distribués, il est recommandé de stocker et transmettre tous les timestamps en Instant (ou OffsetDateTime avec ZoneOffset.UTC). La conversion vers l'heure locale est effectuée uniquement sur le client avant l'affichage à l'utilisateur. Cela évite toute confusion avec les fuseaux horaires.

Synchronisation Temporelle via Instant

Dans les applications Android distribuées, la synchronisation temporelle est critique pour une mise en cache correcte, les notifications et l'édition collaborative. Instant est le choix naturel pour cette tâche grâce à son ancrage en UTC.

Lors de la comparaison de timestamps provenant de différents appareils, il faut considérer que les horloges système peuvent diverger. Il est recommandé d'utiliser l'heure du serveur comme référence. Le serveur renvoie Instant en UTC, et le client le compare avec l'Instant local uniquement pour les calculs relatifs.

Pour calculer la différence entre deux instants, utilisez Duration.between(Instant start, Instant end). Cette méthode renvoie une Duration qui peut être convertie en heures, minutes, secondes. Les méthodes isAfter() et isBefore() permettent de comparer des instants.

kotlin
fun isCacheExpired(
    cachedAt: Instant,
    ttlMinutes: Long
): Boolean {
    val elapsed = Duration.between(cachedAt, Instant.now())
    return elapsed.toMinutes() >= ttlMinutes
}

Exemples Pratiques dans Android

Le premier exemple est la journalisation d'événements avec un timestamp. Instant est sauvegardé dans la base de données Room et envoyé au serveur. Le timestamp est journalisé en UTC pour une interprétation sans ambiguïté.

kotlin
data class EventLog(
    val id: Long = 0,
    val eventName: String,
    val timestamp: Instant
)

class Converters {
    @TypeConverter
    fun fromInstant(value: Instant?): Long? {
        return value?.toEpochMilli()
    }

    @TypeConverter
    fun toInstant(value: Long?): Instant? {
        return value?.let { Instant.ofEpochMilli(it) }
    }
}

Le deuxième exemple est la détermination du temps écoulé depuis un événement. Nous utilisons Duration.between pour afficher « il y a 5 minutes », « il y a 2 heures » — un format courant dans les messageries et les réseaux sociaux.

kotlin
fun timeAgo(instant: Instant): String {
    val duration = Duration.between(instant, Instant.now())
    return when {
        duration.toMinutes() < 1 -> "just now"
        duration.toHours() < 1 -> "${duration.toMinutes()} min ago"
        duration.toDays() < 1 -> "${duration.toHours()} h ago"
        else -> "${duration.toDays()} d ago"
    }
}

Le troisième exemple est la synchronisation de données entre le serveur et le client. Nous utilisons Instant pour suivre l'heure de la dernière mise à jour.

kotlin
class SyncManager {
    private var lastSyncAt: Instant? = null

    fun sync() {
        val syncStart = Instant.now()
        // server request with lastSyncAt
        lastSyncAt = syncStart
    }

    fun shouldSync(intervalMinutes: Long): Boolean {
        val last = lastSyncAt ?: return true
        return Duration.between(last, Instant.now())
            .toMinutes() >= intervalMinutes
    }
}

Erreurs Courantes

La première erreur est d'utiliser Instant.now().toString() pour l'affichage à l'utilisateur. Instant produit au format UTC « 2026-07-21T15:00:00Z », qui est illisible pour les humains. Convertissez toujours Instant via atZone() vers le fuseau horaire local avant de l'afficher.

La deuxième erreur est de perdre les nanosecondes lors de la conversion vers java.util.Date. Date ne supporte que les millisecondes. Si Instant a des nanosecondes, elles seront supprimées dans Date.from(instant). Utilisez Instant.truncatedTo(ChronoUnit.MILLIS) pour spécifier explicitement la précision.

La troisième erreur est la confusion entre toEpochMilli() et getEpochSecond(). toEpochMilli() renvoie le nombre de millisecondes depuis l'époque (long), tandis que getEpochSecond() renvoie le nombre de secondes (long). Confondre ces méthodes peut entraîner une erreur de 1000x.

La quatrième erreur est de supposer qu'Instant.now() est synchronisé sur tous les appareils. Les horloges système peuvent différer de minutes, voire d'heures. Pour les opérations critiques en termes de temps (authentification, paiements), utilisez l'Instant du serveur comme source de vérité.

Foire Aux Questions

En quoi Instant diffère-t-il de System.currentTimeMillis() ?

System.currentTimeMillis() renvoie un long — le nombre de millisecondes depuis l'époque sans lien avec le fuseau horaire. Instant fournit la même fonctionnalité mais avec une précision à la nanoseconde et une API riche pour les conversions, comparaisons et la compatibilité avec java.time.

Comment sauvegarder Instant dans Room Database ?

Room ne supporte pas Instant directement. Utilisez TypeConverter qui convertit Instant en Long (toEpochMilli) et inversement (Instant.ofEpochMilli). Pour la précision à la nanoseconde, sauvegardez deux champs : époque-secondes et nanosecondes.

Peut-on utiliser Instant comme clé dans HashMap ?

Oui, Instant est immuable et implémente correctement equals() et hashCode(). Deux Instants avec la même valeur seront égaux. Cela en fait une clé fiable pour HashMap et autres collections, contrairement à java.util.Date qui est mutable.

Comment obtenir la différence entre deux Instants ?

Utilisez Duration.between(start, end) pour obtenir une Duration ou ChronoUnit.SECONDS.between(start, end) pour la différence en secondes (long). Duration fournit les méthodes toMinutes(), toHours(), toDays() et toNanos().

Pourquoi Instant.parse() nécessite-t-il un suffixe Z ou un décalage ?

Instant est conçu comme un point absolu sur la ligne de temps. Sans spécifier de fuseau horaire ou UTC, l'analyse est impossible car Instant ne contient pas d'informations calendaires. Le suffixe « Z » désigne un décalage zéro (UTC) et est obligatoire pour le format ISO-8601.

Résumé

  • Instant — une classe immuable pour un moment absolu dans le temps en UTC avec une précision à la nanoseconde, préférée pour les timestamps dans les systèmes distribués.
  • Contrairement à java.util.Date, Instant est immuable, thread-safe et a une précision à la nanoseconde. Contrairement à Long — il est explicitement typé et ne permet pas la confusion avec d'autres valeurs numériques.
  • Pour l'affichage à l'utilisateur, Instant est converti via atZone(ZoneId) en ZonedDateTime, sinon l'heure sera affichée en UTC.
  • Pour la transmission dans l'API, utilisez Instant.toString() (ISO-8601) ou toEpochMilli() pour la compatibilité avec les anciens formats.
  • Lorsque vous travaillez avec Room, sauvegardez Instant comme Long via TypeConverter en utilisant la méthode toEpochMilli().
  • Pour calculer le temps écoulé, utilisez Duration.between(), qui gère correctement les nanosecondes.
  • Ne vous fiez pas à la synchronisation des horloges des appareils — pour les opérations critiques, utilisez l'Instant du serveur comme source de vérité.

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.

Discuter du projet

Lisez aussi