Belajar dengan membaca secara berurutan

Timer dan Tanggal — setTimeout / Date / Intl

Membahas setTimeout untuk memanggil function nanti, cara menghentikan setInterval, bulan Date yang mulai dari 0, format tanggal dengan Intl.DateTimeFormat, dan cara menghitung selisih hari.

Kode yang hanya berjalan dari atas ke bawah tidak bisa menutup notifikasi setelah 3 detik atau mengurangi sisa waktu setiap 1 detik. Selama tanggal masih berupa string, kamu juga tidak bisa menampilkan harinya atau menghitung sisa hari sampai tenggat.

Artikel ini membahas setTimeout dan setInterval untuk membuat timer, serta Date dan Intl.DateTimeFormat untuk mengolah tanggal dan waktu.

Menjadwalkan Panggilan untuk Nanti — setTimeout dan clearTimeout

Misalnya situs berbagi foto menampilkan notifikasi "Upload selesai", dan kamu ingin menutupnya setelah 3 detik. Kode yang berjalan dari atas ke bawah tidak punya cara untuk bilang "tunggu 3 detik, baru jalankan bagian berikutnya". Kalau kamu menghabiskan waktu dengan loop for kosong, selama loop itu berjalan halaman tidak merespons klik dan tampilannya juga tidak diperbarui.

setTimeout(function, milidetik) hanya menjadwalkan kapan function dipanggil, lalu eksekusi langsung lanjut ke baris berikutnya. Value yang dikembalikan adalah timer ID, sama seperti yang kamu pakai untuk timeout fetch. Kalau ID itu kamu berikan ke clearTimeout, jadwalnya dibatalkan.

// Mengembalikan Promise yang fulfilled setelah ms milidetik (delay dari artikel Promise, tanpa argument value)
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Jadwalkan penutupan notifikasi 100ms lagi, lalu langsung lanjut (di halaman sungguhan sekitar 3000ms)
setTimeout(() => console.log("Notifikasi ditutup"), 100);   // Notifikasi ditutup (ke-2)
console.log("Upload selesai");                              // Upload selesai (ke-1)

// Pengguna meninggalkan halaman, jadi batalkan rekomendasinya. Tidak dipanggil walau sudah lewat 100ms
const recommendTimer = setTimeout(() => console.log("Menampilkan foto rekomendasi"), 100);
clearTimeout(recommendTimer);

// Tunggu 200ms di sini sebelum lanjut
await delay(200);
console.log("Sudah menunggu 200ms");                        // Sudah menunggu 200ms (ke-3)
Urutan Penulisan Berbeda dari Urutan Tampil
0msUpload selesaiTampil ke-1baris setTimeouttanpa output0msRekomendasidibatalkanTidak dipanggil,walau lewat 100ms100msNotifikasi ditutupTampil ke-2,selama await200msSudah menunggu200msBaris setelahawait tampil ke-3
Baris setTimeout tidak menampilkan apa pun, dan jadwal yang dibatalkan tidak pernah dipanggil. Function yang dijadwalkan jalan saat 100ms berlalu, selagi await masih menunggu.

Function yang dijadwalkan bisa jalan setelah baris terakhir kodemu selesai. Untuk melihat outputnya di console latihan, akhiri kodemu dengan baris yang menunggu, seperti await delay(…), sama seperti di artikel Promise.

Di aplikasi email, tahan pengiriman sebentar supaya masih bisa dibatalkan. delay sudah dideklarasikan.

① Jadwalkan tampilan "Email 1 terkirim" 150ms lagi, tunggu 50ms, lalu batalkan.

② Tampilkan "Pengiriman email 1 dibatalkan".

③ Jadwalkan tampilan "Email 2 terkirim" 100ms lagi, tunggu 150ms, lalu batalkan.

④ Tampilkan "Email 2 tidak bisa dibatalkan".

(Kalau berjalan dengan benar, penjelasan akan muncul.)

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menghentikan Pengulangan — setInterval dan clearInterval

Misalnya kamu ingin menampilkan sisa detik sampai promo berakhir, berkurang setiap 1 detik. setTimeout hanya memanggil function yang dijadwalkan satu kali, jadi untuk mengulangnya, function itu harus menjadwalkan dirinya lagi di setiap panggilan, dan kondisi berhentinya ikut tercampur di kode yang sama.

setInterval (function yang memanggil function lain berulang-ulang setiap sekian milidetik) terus memanggilnya sampai kamu memberikan timer ID yang dikembalikannya ke clearInterval.

Kalau baris berikutnya baru boleh jalan setelah pengulangan selesai, bungkus semuanya dengan Promise, lalu panggil resolve tepat setelah clearInterval, di dalam if yang sama.

// Kurangi sisa detik sebanyak 1 setiap 100ms (di halaman sungguhan setiap 1000ms)
function startCountdown(seconds) {
  return new Promise((resolve) => {
    let remaining = seconds;                  // Dideklarasikan di luar callback, jadi value-nya bertahan antar panggilan
    const timerId = setInterval(() => {
      remaining -= 1;
      console.log(`Sisa ${remaining} detik`);   // Sisa 2 detik → Sisa 1 detik → Sisa 0 detik
      if (remaining === 0) {
        clearInterval(timerId);               // Berhenti di panggilan yang mencapai 0 (saat itu timerId sudah terisi)
        resolve();                            // Beri tahu baris await bahwa sudah selesai
      }
    }, 100);
  });
}

await startCountdown(3);
console.log("Promo sudah berakhir");          // Promo sudah berakhir
resolve Membuat await Lanjut
Pemanggil — baris await startCountdown(3)
  • Tidak lanjut ke baris berikutnya sampai Promise yang dikembalikan fulfilled
  • Promo sudah berakhir tampil setelah resolve
Di dalam startCountdown(3) — jalan sekali
  • let remaining = secondshanya sekali dibuat di sini, berisi 3
  • const timerId = setInterval(...) — ID yang dipakai untuk menghentikannya
Function tiap 100ms — jalan 3 kali
  • remaining -= 1 — mengurangi variabel luar: 2 → 1 → 0
  • Di panggilan yang mencapai 0, clearInterval(timerId) dan resolve()
Variabel luar remaining hanya dibuat sekali dan berkurang 1 di setiap panggilan. resolve di panggilan yang mencapai 0 membuat await di pihak pemanggil lanjut.

Kalau let remaining = seconds kamu pindahkan ke dalam callback, value-nya mulai lagi dari 3 di setiap panggilan dan tidak pernah turun di bawah 2, jadi clearInterval maupun resolve tidak pernah dipanggil. Setelah 15 detik, console latihan berhenti dan melaporkan timeout.

Interval yang Tidak Dihentikan Bocor ke Eksekusi Berikutnya

Di artikel ini, console latihan menjalankan semua latihan di halaman yang sama. Kalau eksekusi selesai tanpa memanggil clearInterval, callback-nya terus dipanggil sampai halaman dimuat ulang, dan outputnya ikut masuk ke hasil latihan lain yang dijalankan kemudian dan menunggu dengan await, sehingga kode yang benar pun dianggap salah. Kalau itu terjadi, muat ulang halaman artikel ini.

Baca jumlah stok gudang setiap 100ms dan berhenti setelah 3 kali. Kerangka watchStock, array jumlah stok readings, dan delay sudah dideklarasikan.

① Setiap 100ms, baca value berikutnya di readings dan tampilkan dalam bentuk "Pembacaan ke-1: stok 12 unit".

② Berhenti setelah pembacaan ke-3 dan buat Promise-nya fulfilled.

③ Tunggu sampai selesai, lalu tunggu 200ms lagi untuk memastikan pembacaan ke-4 tidak muncul.

④ Tampilkan "Pengecekan stok selesai".

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Mengubah Tanggal Menjadi Teks Tampilan — getMonth dan Intl

Misalnya daftar video menampilkan tanggal publikasi dalam bentuk "Rab, 2 September 2026". Kalau kamu memotong bulan dari string API seperti "2026-09-02T09:00:00" dengan slice, yang kamu dapat adalah string "09". Nama harinya juga tidak tertulis di mana pun, jadi tidak bisa dicari dari string itu saja.

Date (object bawaan yang mewakili tanggal dan waktu) membaca "2026-09-02T09:00:00" sebagai jam 9.00 di zona waktu perangkat (waktu lokal suatu wilayah, yang ditentukan oleh selisihnya dari waktu acuan UTC). Method yang diawali get mengembalikan bulan, hari, dan lainnya dalam bentuk angka.

Intl.DateTimeFormat (class yang mengubah tanggal dan waktu menjadi string sesuai bahasa tertentu) dibuat dengan memberikan locale seperti "id-ID" (bahasa Indonesia).

const publishedAt = new Date("2026-09-02T09:00:00");

// Method yang diawali get mengembalikan angka. Bulan Januari = 0, hari Minggu = 0
console.log(publishedAt.getMonth(), publishedAt.getDate(), publishedAt.getDay());   // 8 2 3

// Buat formatter dengan memberikan bahasa dan bentuk tiap bagian yang ditampilkan
const dateFormat = new Intl.DateTimeFormat("id-ID", {
  year: "numeric",     // Tahun sebagai angka
  month: "long",       // Bulan sebagai nama, seperti "September"
  day: "numeric",      // Tanggal sebagai angka
  weekday: "short",    // Hari sebagai nama pendek
});
console.log(dateFormat.format(publishedAt));   // Rab, 2 September 2026
console.log(new Intl.DateTimeFormat("id-ID", { hour: "numeric", minute: "2-digit" }).format(publishedAt));   // 9.00

// String tanpa jam dibaca sebagai jam 0.00 UTC
const dateOnly = new Date("2026-09-02");
console.log(dateOnly.getDate());   // 2 di Jepang, 1 di New York (jam 20.00 hari sebelumnya)
Tanpa Jam, Tanggal Dibaca sebagai 0.00 UTC
"2026-09-02T09:00:00"Dibaca jam 9.00waktu lokalDi New York juga:2 Sep, 9.00getDate() = 2sama dengan Tokyo"2026-09-02"tanpa jamDibaca sebagai0.00 UTCDi New York:1 Sep, 20.00getDate() = 1hari sebelumnya
Kalau jamnya ditulis, string itu berarti 2 September jam 9.00 di zona waktu mana pun yang dipakai perangkat. Kalau jamnya dihilangkan, string dibaca sebagai UTC, dan bisa jatuh di hari sebelumnya, tergantung selisih waktunya.

Di zona waktu yang lebih cepat dari UTC, seperti Jepang atau Indonesia, hasilnya tetap 2, jadi masalah ini mudah terlewat. Kalau API mengirim string yang hanya berisi tanggal, tambahkan "T00:00:00" sebelum memberikannya ke new Date, supaya dibaca sebagai jam 0.00 waktu lokal. Tabel di bawah merangkum value yang dikembalikan method get untuk publishedAt.

MethodValue publishedAtSaat ditampilkan
getFullYear()2026Langsung dipakai
getMonth()8Januari = 0; tambah 1 jadi 9
getDate()2Mulai dari 1; langsung dipakai
getDay()3Minggu = 0, jadi 3 = Rabu
getHours()9Format 24 jam, 0–23

Di halaman booking klinik gigi, ubah tanggal dan jam janji temu menjadi teks tampilan. Tanggal dan jam janji temu sudah disimpan di reservedAt.

① Dengan method yang diawali get, tampilkan tanggal janji temu dalam bentuk "5/10".

② Buat formatter bahasa Indonesia yang menampilkan tanggal, bulan, dan hari dalam bentuk "Sen, 5 Oktober".

③ Tampilkan tanggal janji temu dengan formatter dari ②.

④ Buat formatter yang menampilkan jam dan menit dalam bentuk "14.30", lalu tampilkan jam janji temunya.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output

Menghitung Hari sampai Tenggat — Mengurangkan Date

Misalnya situs perpustakaan menampilkan sisa hari sampai buku harus dikembalikan. Kalau kamu hanya mengurangkan angka tanggalnya, buku yang dipinjam 2 September dan jatuh tempo 3 Oktober jadi 3 - 2 = 1 hari, karena hari-hari di bulan September yang ada di antaranya tidak ikut dihitung.

Di dalamnya, Date menyimpan sebuah angka: jumlah milidetik sejak 1 Januari 1970 jam 0.00 UTC. Mengurangkan satu Date dengan Date lain menghasilkan selisihnya dalam milidetik, jadi kalau dibagi dengan jumlah milidetik dalam sehari, 24 * 60 * 60 * 1000, hasilnya adalah jumlah hari.

new Date(tahun, bulan, tanggal) membuat jam 0.00 waktu lokal di tanggal itu, dan di sini pun bulan dihitung mulai dari 0.

// Jumlah milidetik dalam sehari (24 jam × 60 menit × 60 detik × 1000)
const DAY_MS = 24 * 60 * 60 * 1000;

// Tanggal pinjam dan tanggal jatuh tempo. Walaupun dibuat dari angka, bulan tetap dihitung dari 0
const borrowedAt = new Date(2026, 8, 2);     // 2 September 2026
const dueDate = new Date(2026, 9, 3);        // 3 Oktober 2026

// Mengurangkan satu Date dengan Date lain menghasilkan selisih dalam milidetik
const diffMs = dueDate - borrowedAt;
console.log(Math.round(diffMs / DAY_MS));    // 31

// Tanggal 31, yang tidak ada di bulan September, tidak menimbulkan error, tapi bergeser ke bulan berikutnya
const overflowDate = new Date(2026, 8, 31);
console.log(overflowDate.getMonth() + 1, overflowDate.getDate());   // 10 1
Tiga Cara Menulis 30 September
Selisih hari darinew Date(2026,8,2)ke jatuh temponew Date(2026, 8, 30)new Date(2026, 9, 30)new Date(2026, 8, 31)Menghasilkan30 September30 Oktoberbulan 9 = Oktober1 Oktober31 Septembertidak ada28 hari58 harikelebihan 30 hari29 harikelebihan 1 hari
Ketiganya dimaksudkan untuk membuat tanggal jatuh tempo 30 September. Memberikan 9 sebagai bulan atau 31 sebagai tanggal tidak menimbulkan error; hanya jumlah harinya yang salah.

Kode ini membulatkan dengan Math.round karena daylight saving time (memajukan jam 1 jam selama musim panas). Di wilayah yang memakainya, ada hari yang panjangnya 23 atau 25 jam, jadi hasil pembagiannya tidak selalu bilangan bulat; kamu bisa mendapat angka seperti 30.958…. Di tempat yang tidak memakainya, seperti Jepang dan Indonesia, pembagiannya selalu pas, jadi pembulatan ini mudah terlupa.

Di situs booking tempat berkemah, hitung jumlah malam menginap. Kerangka toDate dan countNights serta DAY_MS sudah dideklarasikan.

① Di toDate, terima tahun, bulan, dan tanggal (bulan dihitung mulai dari 1), lalu kembalikan sebuah Date.

② Di countNights, kembalikan jumlah malam dari selisih dua Date.

③ Tampilkan jumlah malam dari 28 September sampai 2 Oktober 2026 dalam bentuk "4 malam".

④ Tampilkan jumlah malam dari 29 Desember 2026 sampai 3 Januari tahun berikutnya dalam bentuk yang sama.

JavaScript / TypeScript Editor

Jalankan kode untuk melihat output
QUIZ

Cek Pemahaman

Jawab setiap pertanyaan satu per satu.

Soal 1Apa yang terjadi kalau kamu mendeklarasikan let count = 0; di dalam function yang diberikan ke setInterval, lalu mencoba menghentikannya saat count mencapai 3?

Soal 2Apa value yang dikembalikan new Date("2026-09-02T09:00:00").getMonth()?

Soal 3Apa yang dikembalikan getDate() untuk Date yang dibuat dengan new Date(2026, 8, 31)?