Instant — eine unveränderliche Klasse aus dem Paket java.time, die einen Punkt auf der Zeitachse in UTC mit Nanosekundengenauigkeit darstellt. Im Gegensatz zu LocalDateTime enthält Instant kein Datum und keine Uhrzeit in einem menschenlesbaren Format — es ist eine maschinelle Darstellung eines Moments. Laut der Spezifikation Oracle Java 17 (2024) ist Instant für den maschinellen Austausch von Zeitstempeln konzipiert und ein Analogon von System.currentTimeMillis(), jedoch mit Nanosekundengenauigkeit.
Wichtige Punkte
Instant ist eine Klasse, die einen einzelnen Punkt auf der Zeitachse modelliert. Ihre interne Darstellung besteht aus zwei Feldern: long seconds (die Anzahl der Sekunden seit 1970-01-01T00:00:00Z) und int nanos (Nanosekunden innerhalb der aktuellen Sekunde, von 0 bis 999999999).
Der Wertebereich von Instant reicht von -31557014167219200 bis 31556889864403199 Sekunden seit der Epoche und deckt etwa 292 Millionen Jahre in beide Richtungen ab. Dies ist für alle praktischen Aufgaben ausreichend, einschließlich astronomischer Berechnungen.
Laut Baeldung (2024) ist Instant eine Brücke zwischen menschenlesbaren Typen (LocalDateTime, ZonedDateTime) und Maschinenformaten (Zeitstempel in Millisekunden). Instant wird für Protokollierung, Caching, Synchronisation und alle Aufgaben verwendet, bei denen ein absoluter Zeitpunkt wichtig ist.
Die Klasse implementiert die Schnittstellen Comparable (zum Vergleichen von Zeitpunkten) und Temporal (zur Verwendung in der gemeinsamen java.time-API). Instant ist unveränderlich — alle Methoden geben ein neues Objekt zurück.
Vor Java 8 wurden java.util.Date und System.currentTimeMillis() verwendet, um mit Zeitpunkten zu arbeiten. Beide Ansätze haben Nachteile. Date ist veränderlich, nicht threadsicher, speichert die Zeit in Millisekunden seit der Epoche, aber seine Methodennamen sind veraltet (getYear() gibt 116 für 2016 zurück).
Long (ein einfacher Zeitstempel) ist schnell und kompakt, hat aber keine integrierte Nanosekundenunterstützung, wird nicht in einem lesbaren Format angezeigt und erfordert manuelles Parsen beim Debuggen. Der Long-Ansatz unterscheidet auch keine Datentypen — ein Entwickler könnte einen falschen Wert übergeben.
Instant löst all diese Probleme. Es ist unveränderlich, enthält explizite Genauigkeitsinformationen (Sekunden + Nanosekunden), serialisiert in das ISO-8601-Format „2026-07-21T15:00:00Z“ und verfügt über eine umfangreiche API für Konvertierungen. Laut SonarSource (2024) ist Instant der empfohlene Ersatz für Date in allen neuen Projekten.
Der aktuelle Moment wird über Instant.now() ermittelt. Im Gegensatz zu LocalDateTime.now() gibt Instant.now() immer die Zeit in UTC zurück, unabhängig von der Zeitzone des Geräts. Dies macht es ideal für Server-Zeitstempel.
Aus vorhandenen Werten: Instant.ofEpochSecond(long epochSecond) — aus Sekunden seit der Epoche, Instant.ofEpochMilli(long epochMilli) — aus Millisekunden, Instant.parse(CharSequence) — aus einem ISO-8601-String („2026-07-21T15:00:00Z“).
Zum Lesen: getEpochSecond() — die Anzahl der Sekunden seit der Epoche, toEpochMilli() — die Anzahl der Millisekunden, getNano() — Nanosekunden. Die Methode toString() gibt einen String im ISO-8601-Format zurück.
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()
Instant wird über atZone(ZoneId) in ZonedDateTime konvertiert. Zum Beispiel gibt Instant.now().atZone(ZoneId.of(„Europe/Moscow“)) eine ZonedDateTime für Moskau zurück. Ohne eine Zone ist eine Konvertierung unmöglich — Instant enthält keine Kalenderinformationen.
Um Instant in LocalDateTime zu konvertieren: atZone(ZoneId).toLocalDateTime(). Dieser Ansatz ist explizit und verliert keine Informationen. Rückwärtskonvertierung: LocalDateTime.atZone(ZoneId).toInstant().
Für die Kompatibilität mit java.util.Date: Date.from(instant) und date.toInstant(). Dies ist eine bidirektionale Konvertierung, die die Genauigkeit bis zu Millisekunden bewahrt (Date unterstützt keine Nanosekunden). Für java.sql.Timestamp verwenden Sie Timestamp.from(instant) mit Nanosekundenunterstützung.
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()
Das Hauptmerkmal von Instant ist, dass es völlig unabhängig von Zeitzonen ist. Instant.now() liefert auf jedem Gerät überall auf der Welt das gleiche Ergebnis. Dies wird durch die Fixierung der Zeit in UTC erreicht.
Eine Zeitzone wird nur benötigt, um Instant einem Menschen anzuzeigen. Dazu wird atZone(ZoneId) verwendet. ZoneId.systemDefault() gibt die im Betriebssystem eingestellte Zeitzone des Geräts zurück. ZoneOffset.UTC ist die Konstante für UTC.
In verteilten Systemen wird empfohlen, alle Zeitstempel in Instant (oder OffsetDateTime mit ZoneOffset.UTC) zu speichern und zu übertragen. Die Konvertierung in die lokale Zeit wird nur auf dem Client durchgeführt, bevor sie dem Benutzer angezeigt wird. Dies verhindert Verwirrung mit Zeitzonen.
In verteilten Android-Anwendungen ist die Zeitsynchronisation für korrektes Caching, Benachrichtigungen und gemeinsame Bearbeitung entscheidend. Instant ist aufgrund seiner UTC-Verankerung die natürliche Wahl für diese Aufgabe.
Beim Vergleich von Zeitstempeln von verschiedenen Geräten muss berücksichtigt werden, dass Systemuhren voneinander abweichen können. Es wird empfohlen, die Serverzeit als Referenz zu verwenden. Der Server gibt Instant in UTC zurück, und der Client vergleicht es nur für relative Berechnungen mit dem lokalen Instant.
Um die Differenz zwischen zwei Zeitpunkten zu berechnen, verwenden Sie Duration.between(Instant start, Instant end). Diese Methode gibt eine Duration zurück, die in Stunden, Minuten, Sekunden umgewandelt werden kann. Die Methoden isAfter() und isBefore() ermöglichen den Vergleich von Zeitpunkten.
fun isCacheExpired(
cachedAt: Instant,
ttlMinutes: Long
): Boolean {
val elapsed = Duration.between(cachedAt, Instant.now())
return elapsed.toMinutes() >= ttlMinutes
}
Das erste Beispiel ist die Protokollierung von Ereignissen mit einem Zeitstempel. Instant wird in der Room-Datenbank gespeichert und an den Server gesendet. Der Zeitstempel wird zur eindeutigen Interpretation in UTC protokolliert.
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) }
}
}
Das zweite Beispiel ist die Bestimmung der seit einem Ereignis vergangenen Zeit. Wir verwenden Duration.between, um „vor 5 Minuten“, „vor 2 Stunden“ anzuzeigen — ein Format, das in Messengern und sozialen Netzwerken üblich ist.
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"
}
}
Das dritte Beispiel ist die Datensynchronisation zwischen Server und Client. Wir verwenden Instant, um die letzte Aktualisierungszeit zu verfolgen.
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
}
}
Der erste Fehler ist die Verwendung von Instant.now().toString() zur Anzeige für den Benutzer. Instant gibt im UTC-Format „2026-07-21T15:00:00Z“ aus, das für Menschen unlesbar ist. Konvertieren Sie Instant immer über atZone() in die lokale Zeitzone, bevor Sie es anzeigen.
Der zweite Fehler ist der Verlust von Nanosekunden bei der Konvertierung in java.util.Date. Date unterstützt nur Millisekunden. Wenn Instant Nanosekunden hat, werden sie in Date.from(instant) verworfen. Verwenden Sie Instant.truncatedTo(ChronoUnit.MILLIS), um die Genauigkeit explizit anzugeben.
Der dritte Fehler ist die Verwechslung von toEpochMilli() und getEpochSecond(). toEpochMilli() gibt die Anzahl der Millisekunden seit der Epoche (long) zurück, während getEpochSecond() die Anzahl der Sekunden (long) zurückgibt. Die Verwechslung dieser Methoden kann zu einem 1000-fachen Fehler führen.
Der vierte Fehler ist die Annahme, dass Instant.now() auf allen Geräten synchronisiert ist. Systemuhren können um Minuten oder sogar Stunden abweichen. Verwenden Sie für zeitkritische Vorgänge (Authentifizierung, Zahlungen) Server-Instant als Quelle der Wahrheit.
Häufig gestellte Fragen
System.currentTimeMillis() gibt einen long zurück — die Anzahl der Millisekunden seit der Epoche ohne Zeitzonenbindung. Instant bietet die gleiche Funktionalität, aber mit Nanosekundengenauigkeit und einer umfangreichen API für Konvertierungen, Vergleiche und Kompatibilität mit java.time.
Room unterstützt Instant nicht direkt. Verwenden Sie TypeConverter, der Instant in Long (toEpochMilli) und zurück (Instant.ofEpochMilli) konvertiert. Für Nanosekundengenauigkeit speichern Sie zwei Felder: Epochen-Sekunden und Nanosekunden.
Ja, Instant ist unveränderlich und implementiert equals() und hashCode() korrekt. Zwei Instants mit demselben Wert sind gleich. Dies macht es zu einem zuverlässigen Schlüssel für HashMap und andere Sammlungen, im Gegensatz zum veränderlichen java.util.Date.
Verwenden Sie Duration.between(start, end), um eine Duration zu erhalten, oder ChronoUnit.SECONDS.between(start, end) für die Differenz in Sekunden (long). Duration bietet die Methoden toMinutes(), toHours(), toDays() und toNanos().
Instant ist als absoluter Punkt auf der Zeitachse konzipiert. Ohne Angabe einer Zeitzone oder UTC ist das Parsen unmöglich, da Instant keine Kalenderinformationen enthält. Das Suffix „Z“ bezeichnet Null-Offset (UTC) und ist für das ISO-8601-Format obligatorisch.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch