Soal 1Apa yang terjadi kalau kamu mendeklarasikan let count = 0; di dalam function yang diberikan ke setInterval, lalu mencoba menghentikannya saat count mencapai 3?
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)
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.
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
- Tidak lanjut ke baris berikutnya sampai Promise yang dikembalikan fulfilled
Promo sudah berakhirtampil setelah resolve
let remaining = seconds— hanya sekali dibuat di sini, berisi 3const timerId = setInterval(...)— ID yang dipakai untuk menghentikannya
remaining -= 1— mengurangi variabel luar: 2 → 1 → 0- Di panggilan yang mencapai 0,
clearInterval(timerId)danresolve()
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.
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)
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.
| Method | Value publishedAt | Saat ditampilkan |
|---|---|---|
| getFullYear() | 2026 | Langsung dipakai |
| getMonth() | 8 | Januari = 0; tambah 1 jadi 9 |
| getDate() | 2 | Mulai dari 1; langsung dipakai |
| getDay() | 3 | Minggu = 0, jadi 3 = Rabu |
| getHours() | 9 | Format 24 jam, 0–23 |
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
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.
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
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)?