Aplikasi modern sering harus menjawab pertanyaan yang tidak peduli zona waktu: kejadian mana yang lebih dulu terjadi, berapa lama cache masih sah, dan stempel waktu apa yang dicatat saat baris log ditulis. Jawaban objektif untuk semua itu adalah satu garis waktu bersama yang disepakati dunia — dan Instant dari package java.time adalah titik pada garis waktu tersebut. Sebuah Instant selalu direferensikan ke UTC (Coordinated Universal Time), berpresisi hingga nanodetik, dan dapat dibandingkan dengan Instant lain tanpa perlu tahu di planet mana server berada. Pada Chapter ini kita pelajari cara membuat, menggeser, dan membandingkan objek Instant.

Membuat Objek Instant #

Secara internal, Instant menyimpan dua angka: jumlah detik sejak epoch Unix (1 Januari 1970 pukul 00:00:00 UTC) dan nanodetik pecahan di dalam detik tersebut. Ada empat jalur pembuatan yang lazim: parse teks ISO-8601 berakhiran Z, factory ofEpochSecond(), ofEpochSecond() dengan tambahan nanodetik, dan ofEpochMilli() untuk berinteraksi dengan angka milidetik yang dipakai API lama:

import java.time.Instant;

public class MembuatInstant {
    public static void main(String[] args) {
        // Jalur 1: parse teks ISO-8601 dengan akhiran Z (zona UTC).
        Instant momen = Instant.parse("2026-01-15T01:00:00Z");

        // Jalur 2: dari jumlah detik sejak epoch Unix.
        Instant dariDetik = Instant.ofEpochSecond(1768438800L);

        // Jalur 3: dari detik + nanodetik.
        Instant denganNano = Instant.ofEpochSecond(1768438800L, 500);

        // Jalur 4: dari milidetik sejak epoch.
        Instant dariMillis = Instant.ofEpochMilli(1768438800000L);

        System.out.println("momen      : " + momen);
        System.out.println("dariDetik  : " + dariDetik);
        System.out.println("denganNano : " + denganNano);
        System.out.println("dariMillis : " + dariMillis);

        System.out.println("getEpochSecond() : " + momen.getEpochSecond());
        System.out.println("getNano()        : " + momen.getNano());
        System.out.println("toEpochMilli()   : " + momen.toEpochMilli());
    }
}

Output yang Dihasilkan:

text
momen      : 2026-01-15T01:00:00Z
dariDetik  : 2026-01-15T01:00:00Z
denganNano : 2026-01-15T01:00:00.000000500Z
dariMillis : 2026-01-15T01:00:00Z
getEpochSecond() : 1768438800
getNano()        : 0
toEpochMilli()   : 1768438800000

Mari kita telaah baris-baris kode di atas:

  1. Baris 6 (Instant.parse("2026-01-15T01:00:00Z")): huruf Z di akhir teks berarti offset nol — waktu UTC. Notasi ini berasal dari sebutan militer Zulu untuk zona waktu nol; Instant tidak pernah memakai offset lain.
  2. Baris 9-15: tiga factory ofEpochSecond, ofEpochSecond dengan nanodetik, dan ofEpochMilli menghasilkan objek dari angka mentah — perhatikan bahwa 1768438800 detik dan 1768438800000 milidetik adalah momen yang sama persis.
  3. Baris 18-20: getEpochSecond() dan getNano() membaca kembali kedua angka internal, sedangkan toEpochMilli() mengembalikan milidetik untuk kebutuhan API lama seperti java.util.Date.

Dari keluaran di atas terbaca korespondensi yang berguna dihafal: 2026-01-15T01:00:00Z sama dengan epoch second 1768438800. Nilai nanodetik tampil sebagai pecahan .000000500 — kelima ratus nanodetik — menegaskan bahwa satuan terkecil Instant bukan milidetik seperti pada java.util.Date.

Menggeser dan Membandingkan Titik Waktu #

Karena Instant adalah titik pada garis waktu, operasinya berupa pergeseran durasi fisik: plusSeconds, minusMillis, atau plus(Duration). Method truncatedTo() membulatkan ke bawah dengan membuang komponen di bawah satuan tertentu, dan konstanta Instant.EPOCH menandai titik nol garis waktu:

import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class OperasiInstant {
    public static void main(String[] args) {
        Instant mulai = Instant.parse("2026-01-15T01:00:00Z");

        // Penjumlahan dan pengurangan mengembalikan objek Instant yang baru.
        System.out.println("plusSeconds(90)  : " + mulai.plusSeconds(90));
        System.out.println("minusMillis(1500): " + mulai.minusMillis(1500));
        System.out.println("plus(2 jam)      : " + mulai.plus(Duration.ofHours(2)));

        // Buang komponen di bawah detik untuk perbandingan yang adil.
        Instant bertahap = Instant.ofEpochSecond(1768438800L, 750_000_000);
        System.out.println("sebelum truncate : " + bertahap);
        System.out.println("truncatedTo      : " + bertahap.truncatedTo(ChronoUnit.SECONDS));

        // Perbandingan titik waktu di garis waktu.
        Instant selesai = mulai.plus(Duration.ofMinutes(105));
        System.out.println("isBefore         : " + mulai.isBefore(selesai));
        System.out.println("isAfter(EPOCH)   : " + mulai.isAfter(Instant.EPOCH));
        System.out.println("Duration.between : " + Duration.between(mulai, selesai));
    }
}

Output yang Dihasilkan:

text
plusSeconds(90)  : 2026-01-15T01:01:30Z
minusMillis(1500): 2026-01-15T00:59:58.500Z
plus(2 jam)      : 2026-01-15T03:00:00Z
sebelum truncate : 2026-01-15T01:00:00.750Z
truncatedTo      : 2026-01-15T01:00:00Z
isBefore         : true
isAfter(EPOCH)   : true
Duration.between : PT1H45M

Baris 9-11 menggeser titik waktu maju 90 detik, mundur 1500 milidetik, dan maju dua jam — semuanya dalam hitungan durasi murni tanpa melibatkan kalender. Baris 14-17 memperlihatkan truncatedTo(ChronoUnit.SECONDS) yang mengubah 01:00:00.750 menjadi 01:00:00, teknik yang umum dipakai agar dua stempel waktu dengan selisih milidetik dapat dibandingkan secara adil. Baris 20-23 membandingkan dua titik dan mengukur jaraknya menjadi Duration PT1H45M — satu jam empat puluh lima menit dalam notasi ISO-8601.

Instant adalah jawaban untuk kebutuhan mesin: stempel log, urutan kejadian, kedaluwarsa token, dan sinkronisasi antar server. Namun begitu pengguna manusia masuk ke dalam cerita — “jam berapa di kotanya?” — kita butuh representasi yang membawa informasi zona. Bab berikutnya menghadirkan ZonedDateTime, tipe terkaya di java.time yang menggabungkan tanggal, waktu, dan zona waktu dalam satu objek.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

MembuatInstant.java

Unduh berkas
java
import java.time.Instant;

public class MembuatInstant {
    public static void main(String[] args) {
        // Jalur 1: parse teks ISO-8601 dengan akhiran Z (zona UTC).
        Instant momen = Instant.parse("2026-01-15T01:00:00Z");

        // Jalur 2: dari jumlah detik sejak epoch Unix.
        Instant dariDetik = Instant.ofEpochSecond(1768438800L);

        // Jalur 3: dari detik + nanodetik.
        Instant denganNano = Instant.ofEpochSecond(1768438800L, 500);

        // Jalur 4: dari milidetik sejak epoch.
        Instant dariMillis = Instant.ofEpochMilli(1768438800000L);

        System.out.println("momen      : " + momen);
        System.out.println("dariDetik  : " + dariDetik);
        System.out.println("denganNano : " + denganNano);
        System.out.println("dariMillis : " + dariMillis);

        System.out.println("getEpochSecond() : " + momen.getEpochSecond());
        System.out.println("getNano()        : " + momen.getNano());
        System.out.println("toEpochMilli()   : " + momen.toEpochMilli());
    }
}

OperasiInstant.java

Unduh berkas
java
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;

public class OperasiInstant {
    public static void main(String[] args) {
        Instant mulai = Instant.parse("2026-01-15T01:00:00Z");

        // Penjumlahan dan pengurangan mengembalikan objek Instant yang baru.
        System.out.println("plusSeconds(90)  : " + mulai.plusSeconds(90));
        System.out.println("minusMillis(1500): " + mulai.minusMillis(1500));
        System.out.println("plus(2 jam)      : " + mulai.plus(Duration.ofHours(2)));

        // Buang komponen di bawah detik untuk perbandingan yang adil.
        Instant bertahap = Instant.ofEpochSecond(1768438800L, 750_000_000);
        System.out.println("sebelum truncate : " + bertahap);
        System.out.println("truncatedTo      : " + bertahap.truncatedTo(ChronoUnit.SECONDS));

        // Perbandingan titik waktu di garis waktu.
        Instant selesai = mulai.plus(Duration.ofMinutes(105));
        System.out.println("isBefore         : " + mulai.isBefore(selesai));
        System.out.println("isAfter(EPOCH)   : " + mulai.isAfter(Instant.EPOCH));
        System.out.println("Duration.between : " + Duration.between(mulai, selesai));
    }
}