Siti menetapkan jadwal lokakarya komunitas: dibuka 17 Agustus 2026 pukul 09.30. Angka yang sederhana ini ternyata menyimpan sejumlah pertanyaan teknis. Pukul 09.30 menurut jam siapa — Jakarta, UTC, atau jam komputer pengunjung dari luar negeri? Bagaimana menyimpannya, membandingkannya, dan menambah satu hari padanya? JavaScript menjawab semuanya lewat satu tipe bawaan: Date.

Date menyimpan satu nilai saja di dalamnya — jumlah milidetik sejak 1 Januari 1970 UTC (disebut timestamp). Segala hal lain, seperti tahun, bulan, dan jam, adalah hasil perhitungan dari angka itu. Karena perhitungan tampilnya bergantung pada zona waktu, chapter ini menyusun kebiasaan yang aman: tahu kapan kita bekerja dengan waktu lokal dan kapan dengan UTC, serta selalu menguji keluaran lewat bentuk yang deterministik.

Membuat Date dan Membaca Isinya #

Ada dua cara utama membuat Date: dari komponen (tahun, bulan, tanggal, jam, …) yang ditafsirkan sebagai waktu lokal mesin, atau dari string ISO yang membawa zona eksplisit. Berkas berikut memakai keduanya, ditambah deteksi tanggal yang tidak valid:

// jadwal-lokakarya.js — membuat dan membaca tanggal dengan Date
// Catatan: keluaran chapter ini memakai toISOString (zona UTC eksplisit)
// sehingga hasilnya sama di mesin dengan pengaturan zona waktu apa pun.

// --- 1. membuat tanggal dari komponen (waktu lokal mesin) ---
const daftar = new Date(2026, 7, 17, 9, 30, 0); // 17 Agustus 2026, pukul 09.30
console.log(daftar.getFullYear()); // 2026
console.log(daftar.getMonth());    // 7 -> Agustus (mulai dari 0)
console.log(daftar.getDate());     // 17
console.log(daftar.getDay());      // 1 -> Senin (0 = Minggu)
console.log(daftar.getHours());    // 9

// --- 2. tanggal dari string ISO dengan zona eksplisit ---
const mulai = new Date("2026-08-17T02:00:00Z");
console.log(mulai.toISOString());
console.log(mulai.getTime()); // timestamp: milidetik sejak 1 Januari 1970 UTC
console.log(new Date(1786932000000).toISOString()); // timestamp kembali jadi tanggal

// --- 3. jebakan: tanggal tanpa jam dianggap UTC ---
const dariTanggalSaja = new Date("2026-08-17");
console.log(dariTanggalSaja.toISOString());

// --- 4. string non-ISO menghasilkan Invalid Date ---
const rusak = new Date("17 Agustus 2026");
console.log(String(rusak));
console.log(rusak.getTime());
console.log(isNaN(rusak.getTime()));
console.log(typeof Date.now()); // timestamp "sekarang" dalam milidetik

Output yang Dihasilkan:

text
2026
7
17
1
9
2026-08-17T02:00:00.000Z
1786932000000
2026-08-17T02:00:00.000Z
2026-08-17T00:00:00.000Z
Invalid Date
NaN
true
number

Mari kita telaah baris-baris pentingnya:

  1. Baris 6 (new Date(2026, 7, 17, 9, 30, 0)): urutan argumennya tahun, bulan, tanggal, jam, menit, detik. Perhatikan bulannya: 7 untuk Agustus — angka bulan pada constructor Date dimulai dari 0, bukan 1.
  2. Baris 7–11 (getter): getFullYear() mengembalikan 2026, getMonth() mengembalikan 7 (bukan 8!), getDate() mengembalikan 17, dan getDay() mengembalikan 1 — 17 Agustus 2026 jatuh pada hari Senin, dengan konvensi 0 = Minggu. Hati-hati membedakan getDate (tanggal bulan) dan getDay (hari dalam pekan).
  3. Baris 14–17 (ISO dan timestamp): string "2026-08-17T02:00:00Z" diakhiri Z, tanda UTC — jadi waktunya absolut, tidak bergantung mesin. toISOString() mengembalikan bentuk ISO yang sama, dan getTime() mengungkap nilai yang sesungguhnya disimpan Date: milidetik. Baris berikutnya membuktikan kebalikannya — angka 1786932000000 dibuat kembali menjadi Date yang sama.
  4. Baris 20–21 (jebakan tanggal tanpa jam): string ISO yang hanya berisi tanggal, "2026-08-17", ditafsirkan sebagai tengah malam UTC — terlihat dari 2026-08-17T00:00:00.000Z, bukan pukul 00.00 waktu lokal. Aturan ini sering mengejutkan.
  5. Baris 24–27 (tanggal tidak valid): format "17 Agustus 2026" bukan ISO, dan format non-ISO tidak dijamin oleh spesifikasi. Hasilnya object Date berisi Invalid Date: dicetak sebagai Invalid Date, getTime()-nya NaN, dan isNaN(...) menjadi cara andal mendeteksinya.
  6. Baris 28 (Date.now()): method ini mengembalikan timestamp saat kode berjalan — nilainya berbeda setiap pemanggilan, sehingga di sini kita hanya memeriksa tipenya: number.

Bulan Dimulai dari Nol #

Jebakan bulan 0-indexed layak porsi tersendiri, karena nyaris semua pemula pernah tertipu olehnya. Manusia menyebut Agustus bulan ke-8; Date menghitung bulan dari 0:

js
const benar = new Date(2026, 7, 17);  // 7 = Agustus
const keliru = new Date(2026, 8, 17); // maksudnya Agustus -> ternyata September
console.log(benar.getMonth());
console.log(keliru.getMonth());

Output yang Dihasilkan:

text
7
8

Baris pertama mengonfirmasi: constructor dengan 7 menghasilkan getMonth() bernilai 7. Baris kedua memperlihatkan kesalahan klasiknya — menulis 8 dengan niat “Agustus” menghasilkan September. Kebiasaan yang aman: selalu tulis komentar nama bulannya, dan ingat getter getMonth() pun mengembalikan angka 0–11.

Zona Waktu: Lokal, UTC, dan Offset #

Ketiga bentuk string ISO berikut membawa makna zona yang berbeda:

js
console.log(new Date("2026-08-17T02:00:00+07:00").toISOString());

Output yang Dihasilkan:

text
2026-08-16T19:00:00.000Z

String "2026-08-17T02:00:00+07:00" menyatakan pukul 02.00 di zona +07:00 (WIB). Hasil toISOString() memperlihatkan waktunya dalam UTC: pukul 19.00 tanggal 16 Agustus — satu hari sebelumnya. Dua pukul 02.00 pada tanggal yang sama bisa jadi dua saat yang berbeda bila zonanya berbeda; itulah mengapa string ISO dengan Z atau offset eksplisit (+07:00) jauh lebih aman daripada string yang tidak menyebut zona.

Kontrasnya ada pada constructor komponen. new Date(2026, 7, 17) membuat pukul 00.00 menurut jam mesin yang menjalankan kode:

Tanggal sebagai Angka: Timestamp #

Karena Date pada dasarnya angka, operasi waktunya menjadi operasi aritmetika sederhana. Satu hari adalah 24 × 60 × 60 × 1000 milidetik:

js
const mulai = new Date("2026-08-17T02:00:00Z");
const satuHari = 24 * 60 * 60 * 1000;
const hariKedua = new Date(mulai.getTime() + satuHari);
console.log(hariKedua.toISOString());

Output yang Dihasilkan:

text
2026-08-18T02:00:00.000Z

Menambah satu hari cukup menambah 86.400.000 milidetik pada getTime(), lalu membuat Date baru dari angka itu. Titik nolnya adalah new Date(0), yang menghasilkan 1970-01-01T00:00:00.000Z — dan Date.now() adalah kebalikannya: mengambil timestamp dari saat ini. Dengan dua arah ini (tanggal → angka, angka → tanggal), membandingkan dua jadwal cukup membandingkan dua angka:

js
const jadwalA = new Date("2026-08-17T02:00:00Z");
const jadwalB = new Date("2026-08-18T02:00:00Z");
console.log(jadwalA.getTime() < jadwalB.getTime());
console.log(jadwalA.getTime() === jadwalB.getTime());

Output yang Dihasilkan:

text
true
false

Perbandingan langsung antar object Date memang juga bisa (jadwalA < jadwalB), tetapi lewat getTime() pertanyaannya eksplisit: mana yang lebih dekat ke titik nol. Kebiasaan ini membantu saat mencari jadwal terdekat dari sebuah daftar — urutkan berdasarkan timestamp, bukan berdasarkan teksnya. Date.now() sendiri lazim dipakai untuk mengukur durasi: catat nilainya sebelum dan sesudah pekerjaan, lalu selisih kedua angka itulah lamanya dalam milidetik.

Satu hal yang perlu diingat: setter seperti setFullYear(), setMonth(), dan setHours() juga tersedia untuk mengubah Date yang sudah ada. Method-method ini mengubah object di tempat — bukan membuat salinan — dan menafsirkan angka yang dikirim sebagai komponen waktu lokal, dengan konsekuensi zona waktu yang sama seperti constructor komponen. Untuk pengujian yang stabil antar mesin, gaya “buat Date baru dari timestamp” seperti di atas lebih mudah dilacak.

Sampai di sini tanggal kita akurat tetapi tampilannya masih mesiniah: 2026-08-17T02:00:00.000Z bukan bentuk yang nyaman dibaca pengunjung lokakarya. Untuk menampilkan “Senin, 17 Agustus 2026 pukul 09.00” sesuai kaidah Indonesia, kita perlu Intl — bahasan chapter berikutnya.

Berkas Sumber

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

jadwal-lokakarya.js

Unduh berkas
javascript
// jadwal-lokakarya.js — membuat dan membaca tanggal dengan Date
// Catatan: keluaran chapter ini memakai toISOString (zona UTC eksplisit)
// sehingga hasilnya sama di mesin dengan pengaturan zona waktu apa pun.

// --- 1. membuat tanggal dari komponen (waktu lokal mesin) ---
const daftar = new Date(2026, 7, 17, 9, 30, 0); // 17 Agustus 2026, pukul 09.30
console.log(daftar.getFullYear()); // 2026
console.log(daftar.getMonth());    // 7 -> Agustus (mulai dari 0)
console.log(daftar.getDate());     // 17
console.log(daftar.getDay());      // 1 -> Senin (0 = Minggu)
console.log(daftar.getHours());    // 9

// --- 2. tanggal dari string ISO dengan zona eksplisit ---
const mulai = new Date("2026-08-17T02:00:00Z");
console.log(mulai.toISOString());
console.log(mulai.getTime()); // timestamp: milidetik sejak 1 Januari 1970 UTC
console.log(new Date(1786932000000).toISOString()); // timestamp kembali jadi tanggal

// --- 3. jebakan: tanggal tanpa jam dianggap UTC ---
const dariTanggalSaja = new Date("2026-08-17");
console.log(dariTanggalSaja.toISOString());

// --- 4. string non-ISO menghasilkan Invalid Date ---
const rusak = new Date("17 Agustus 2026");
console.log(String(rusak));
console.log(rusak.getTime());
console.log(isNaN(rusak.getTime()));
console.log(typeof Date.now()); // timestamp "sekarang" dalam milidetik