Tanggal (Date) JavaScript: Mengolah Waktu dengan Benar

Objek Date dipakai untuk membuat, membaca, memformat, dan menghitung tanggal serta waktu. Pahami cara kerjanya, jebakan zona waktu yang sering bikin keliru, dan cara modern menangani tanggal dengan aman.

Diterbitkan 31 Juli 202610 menit bacaOleh ACY Partner Indonesia
Tanggal JavaScript — objek Date, timestamp, dan zona waktu
300 × 250Slot Iklan TersediaPasang iklan Anda di sini

Hampir semua aplikasi pada akhirnya berurusan dengan waktu. Sebuah artikel blog punya tanggal terbit. Sebuah pesanan punya timestamp. Sebuah hitung mundur berjalan menuju tenggat. Label “terakhir online 3 menit lalu” terus berubah di depan matamu. Semua itu lewat objek bawaan JavaScript bernama Date — dan Date memang terkenal jadi salah satu bagian bahasa yang paling membingungkan.

Kabar baiknya: sebagian besar kebingungan itu berasal dari segelintir keanehan yang spesifik. Begitu kamu tahu apa saja keanehannya, mengurus tanggal nggak lagi terasa seperti melewati ranjau. Artikel ini membahas cara membuat tanggal, membaca bagian-bagiannya, memformatnya supaya enak dibaca manusia, melakukan hitungan, dan — yang paling penting — jebakan zona waktu serta parsing yang hampir selalu menjebak orang di percobaan pertama. Sebaiknya kamu sudah nyaman dengan objek sebelum masuk ke sini, karena Date sendiri sebenarnya adalah jenis objek yang istimewa.

Date itu sebenarnya apa

Di balik layar, sebuah Date di JavaScript hanyalah satu angka saja: jumlah milidetik sejak satu titik waktu tetap yang disebut Unix epoch — yaitu tengah malam UTC pada 1 Januari 1970. Setiap tanggal yang kamu buat, sekeren apa pun tampilannya di layar, di dalamnya disimpan sebagai satu angka itu.

Inilah ide paling penting di seluruh artikel ini. Sebuah Date tidak menyimpan “15 Maret di Jakarta.” Yang disimpan adalah satu momen waktu yang persis, dalam bentuk hitungan milidetik, lalu ditampilkan ke kamu dalam zona waktu lokal saat kamu memintanya. Pegang erat-erat model berpikir ini, dan sebagian besar perilaku anehnya akan mulai masuk akal.

const sekarang = new Date();
console.log(sekarang.getTime());   // misalnya 1781827200000 — milidetik sejak 1970

Membuat sebuah Date

Kamu membuat tanggal dengan konstruktor new Date(), dan perilakunya berbeda-beda tergantung apa yang kamu berikan ke dalamnya. Ada empat bentuk utama.

Tanpa argumen — momen saat ini:

const sekarang = new Date();
console.log(sekarang);   // tanggal & waktu persis sekarang

Sebuah timestamp (milidetik sejak epoch):

const epoch = new Date(0);             // 1 Jan 1970, 00:00:00 UTC
const nanti = new Date(1781827200000); // suatu momen di tahun 2026

Bagian-bagian angka (tahun, bulan, tanggal, …):

const d = new Date(2026, 6, 31, 14, 30, 0);
// 31 Juli 2026, 14:30:00 — dalam waktu LOKAL

Sebuah string tanggal:

const d = new Date("2026-07-31");
const d2 = new Date("2026-07-31T14:30:00");

Tiap bentuk punya jebakan yang perlu kamu tahu, dan bentuk bagian-angka punya jebakan yang paling terkenal di antara semuanya.

Bulan dihitung mulai dari nol

Saat kamu menyusun tanggal dari angka, bulan dihitung mulai dari 0, bukan 1. Jadi 0 itu Januari, 1 itu Februari, dan 11 itu Desember. Artinya new Date(2026, 6, 31) adalah Juli tanggal 31, bukan Juni. Anehnya, tanggal dalam bulan justru tetap mulai dari 1 — hanya bulan saja yang berbasis nol. Satu keanehan inilah penyebab bug tanggal paling banyak di JavaScript. Kalau suatu tanggal keluar meleset persis satu bulan, hampir pasti ini biang keladinya.

Membaca bagian-bagian tanggal

Begitu kamu punya sebuah Date, kamu mengambil potongan-potongannya pakai method get. Semua ini mengembalikan nilai dalam zona waktu lokalmu:

const d = new Date(2026, 6, 31, 14, 30, 0);

d.getFullYear();   // 2026
d.getMonth();      // 6  (Juli — ingat, berbasis nol!)
d.getDate();       // 31 (tanggal dalam bulan, 1–31)
d.getDay();        // 5  (hari dalam MINGGU: 0 = Minggu, 6 = Sabtu)
d.getHours();      // 14
d.getMinutes();    // 30
d.getSeconds();    // 0

Beberapa nama ini bikin orang keliru. getDate() memberi kamu tanggal dalam bulan (angka dari 1 sampai 31), sedangkan getDay() memberi hari dalam minggu sebagai angka, dengan hari Minggu bernilai 0. Kedengarannya mirip, padahal sama sekali beda — sering tertukar dan jadi kesalahan klasik.

Ada juga getTime(), yang mengembalikan timestamp milidetik mentah tadi. Inilah cara paling bersih untuk membandingkan dua tanggal, seperti yang sebentar lagi kita lihat.

Memformat tanggal untuk manusia

Sebuah Date mentah yang dicetak ke console kelihatan teknis dan kurang sedap dipandang. Untuk menampilkan sesuatu yang enak dibaca, kamu punya beberapa pilihan — dan pilihan modernnya jauh lebih baik daripada cara-cara lama.

Method bawaan yang serba cepat memberi kamu format yang sudah baku:

const d = new Date(2026, 6, 31, 14, 30);

d.toString();          // "Fri Jul 31 2026 14:30:00 GMT+0700 ..."
d.toDateString();      // "Fri Jul 31 2026"
d.toISOString();       // "2026-07-31T07:30:00.000Z"  (selalu UTC)
d.toLocaleDateString();// "31/7/2026"  (mengikuti locale pengguna)

toISOString() ini istimewa dan layak kamu ingat: ia selalu mengembalikan tanggal dalam UTC memakai format standar ISO 8601. Itulah format yang kamu inginkan saat menyimpan tanggal atau mengirimnya ke server, karena maknanya tunggal dan tak bisa salah tafsir.

Untuk menampilkan tanggal ke orang sungguhan, alat terbaiknya adalah Intl.DateTimeFormat (atau jalan pintasnya, toLocaleDateString dengan opsi). Ia memformat tanggal dengan benar untuk bahasa dan wilayah apa pun tanpa kamu harus merangkai string sendiri:

const d = new Date(2026, 6, 31, 14, 30);

const hasil = new Intl.DateTimeFormat("id-ID", {
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric",
}).format(d);

console.log(hasil);   // "Jumat, 31 Juli 2026"

Berhenti merakit string tanggal manual

Godaannya memang besar untuk menyusun tanggal sendiri pakai sesuatu seperti `${tanggal}/${bulan}/${tahun}`. Tahan dulu. Kamu bakal selamanya bergulat dengan nol di depan, nama bulan, perbedaan locale, dan macam-macam kasus pinggiran. Intl.DateTimeFormat menangani itu semua — nama bulan yang sudah diterjemahkan, pemisah yang tepat, jam 12 vs 24 — secara gratis, dan sudah tertanam di setiap browser modern. Pakai ini setiap kali kamu perlu menampilkan tanggal ke pengguna.

Melakukan hitungan dengan tanggal

Hitungan tanggal adalah saat ide “tanggal itu sebenarnya angka milidetik” tadi mulai membuahkan hasil. Karena setiap tanggal sejatinya adalah angka, kamu bisa membandingkan dan mengurangkannya.

Membandingkan dua tanggal: ubah keduanya jadi timestamp pakai getTime() (atau pakai + di depan), lalu bandingkan angkanya.

const mulai = new Date("2026-01-01");
const akhir = new Date("2026-12-31");

console.log(akhir.getTime() > mulai.getTime());   // true — akhir lebih belakangan

Mencari selisih antara dua tanggal: kurangkan timestamp keduanya supaya dapat milidetik, lalu ubah ke satuan apa pun yang kamu mau.

const mulai = new Date("2026-07-01");
const akhir = new Date("2026-07-31");

const selisihMs = akhir - mulai;                       // selisih dalam milidetik
const selisihHari = selisihMs / (1000 * 60 * 60 * 24); // ms → detik → menit → jam → hari

console.log(selisihHari);   // 30

Angka 1000 * 60 * 60 * 24 itu adalah jumlah milidetik dalam satu hari, dan kamu bakal sering menuliskannya (atau menyimpannya sebagai konstanta).

Menambah atau mengurangi waktu sedikit lebih rumit. Cara yang bersih dan bisa diandalkan adalah memakai method set, karena method-method ini otomatis menangani pergantian batas bulan dan tahun:

const d = new Date(2026, 6, 31);   // 31 Juli 2026

d.setDate(d.getDate() + 7);        // tambah 7 hari
console.log(d);                    // 7 Agustus 2026 — berpindah ke bulan berikutnya dengan benar

Perhatikan, menambah 7 hari ke 31 Juli tidak menghasilkan “Juli tanggal 38” — ia dengan benar maju ke Agustus. Method set mengerjakan hitungan itu untukmu, termasuk tahun kabisat, dan justru inilah alasannya kamu sebaiknya memilih method ini ketimbang mengutak-atik penjumlahan milidetik mentah untuk menambah hari, bulan, atau tahun.

Jebakan mutability

Ada satu jebakan halus yang benar-benar memicu bug: objek Date itu mutable. Method seperti setDate() dan setMonth() tidak mengembalikan tanggal baru — mereka mengubah tanggal aslinya langsung di tempat.

const asli = new Date(2026, 6, 31);
const salinan = asli;       // BUKAN salinan — objek yang sama!

salinan.setDate(1);
console.log(asli.getDate());   // 1  — yang "asli" ikut berubah!

Menyalin Date tidak benar-benar menggandakannya

Karena Date adalah objek, menulis const salinan = tanggalTertentu cuma membuat salinan menunjuk ke tanggal yang sama. Mengubah satu berarti mengubah keduanya. Kalau kamu butuh salinan yang benar-benar mandiri sebelum mengubahnya, buat tanggal baru dari timestamp-nya: const salinan = new Date(asli.getTime()). Lupa soal ini adalah sumber umum dari bug “lho kok variabel satunya ikut berubah?” — dan ini perilaku referensi yang sama seperti yang mungkin sudah kamu temui pada objek dan array secara umum.

Jebakan zona waktu

Yang satu ini cepat atau lambat menjebak semua orang, jadi pantas dapat bagian sendiri. Ingat lagi bahwa Date menyimpan satu momen dalam UTC dan menampilkannya dalam waktu lokal. Di celah itulah kejutan-kejutan bersembunyi.

Contoh yang paling terkenal adalah saat mem-parsing sebuah string tanggal saja:

const d = new Date("2026-07-31");
console.log(d.toISOString());   // "2026-07-31T00:00:00.000Z"

String dengan format "YYYY-MM-DD" di-parsing sebagai tengah malam UTC. Kalau kamu berada di zona waktu yang lebih maju dari UTC — misalnya Jakarta, UTC+7 — momen yang sama itu berarti jam 7 pagi tanggal 31 Juli secara lokal, yang kelihatannya aman-aman saja. Tapi di zona waktu yang lebih mundur dari UTC, seperti New York, tengah malam UTC tanggal 31 Juli sebenarnya adalah jam 7 malam tanggal 30 Juli. Jadi new Date("2026-07-31").getDate() bisa mengembalikan 30 untuk sebagian penggunamu. Sebuah tanggal yang kelihatan benar di komputermu diam-diam bergeser sehari untuk orang lain.

String tanggal-saja di-parsing sebagai UTC; string tanggal-waktu sebagai lokal

Ada satu ketidakkonsistenan yang sudah tertanam di spesifikasi dan layak kamu hafalkan. new Date("2026-07-31") (tanggal saja) diperlakukan sebagai UTC. Tapi new Date("2026-07-31T14:30") (ada waktunya, tanpa Z atau offset) diperlakukan sebagai waktu lokal. String yang kelihatan mirip, aturannya berbeda. Untuk menghindari kerepotan ini sama sekali, selalu sertakan offset zona waktu yang eksplisit (huruf Z untuk UTC, atau +07:00), atau bangun tanggalnya dari bagian-angka pakai new Date(tahun, bulan, hari), yang selalu ditafsirkan secara lokal.

Intinya secara praktis: kalau sebuah tanggal meleset sehari dan hanya untuk sebagian pengguna, curigai parsing yang berbasis zona waktu. Simpan dan kirim tanggal sebagai string ISO penuh dalam UTC, dan baru ubah ke waktu lokal tepat di saat kamu menampilkannya.

Contoh realistis

Mari kita rangkai semuanya lewat sebuah helper “berapa lama lalu” kecil — jenis fungsi yang mengubah timestamp jadi “3 hari lalu”, yang sudah sering kamu lihat di banyak situs:

function berapaLamaLalu(tanggal) {
  const detik = Math.floor((new Date() - tanggal) / 1000);

  const satuan = {
    tahun: 31536000,
    bulan: 2592000,
    hari: 86400,
    jam: 3600,
    menit: 60,
  };

  for (const [nama, detikPerSatuan] of Object.entries(satuan)) {
    const jumlah = Math.floor(detik / detikPerSatuan);
    if (jumlah >= 1) {
      return `${jumlah} ${nama} lalu`;
    }
  }
  return "baru saja";
}

const diposting = new Date("2026-07-28T10:00:00Z");
console.log(berapaLamaLalu(diposting));   // misalnya "3 hari lalu"

Fungsi ini merangkum semua yang ada di artikel: mengurangkan dua tanggal untuk dapat selisih milidetik, mengubahnya ke satuan yang lebih besar, lalu melakukan perulangan atas entry sebuah objek (yang sudah kamu kenal di artikel perulangan) untuk memilih satuan yang pas. Ini benar-benar fungsi berguna yang bisa langsung kamu pasang di proyek nyata.

Saat Date bawaan tidak lagi cukup

Untuk banyak pekerjaan, Date bawaan sudah lebih dari memadai. Tapi begitu kamu mulai banyak menjungkir-balikkan zona waktu, mem-parsing yang rumit, atau memformat dalam jumlah besar, sisi-sisi kasarnya jadi menumpuk. Dulu orang mengandalkan library seperti Moment.js, tapi sekarang Moment dianggap warisan lama. Pilihan modern yang ringan seperti date-fns dan Day.js sudah menutupi sebagian besar kebutuhan.

Kabar yang lebih besar adalah Temporal, sebuah API bawaan baru yang dirancang untuk memperbaiki masalah-masalah lama Date — objek yang immutable, pemisahan yang jelas antara tanggal dan waktu, serta dukungan zona waktu sebagai fitur utama. Inilah masa depan tanggal di JavaScript, dan ia sedang bergulir masuk ke berbagai browser. Kalau kamu mulai dari nol hari ini, Date bawaan masih jadi yang paling sering kamu pakai, tapi ada baiknya kamu tahu Temporal itu ada untuk saat ia nanti tersedia luas.

Penutup

Tanggal terasa menakutkan terutama gara-gara beberapa sisi tajamnya. Kenali sisi-sisi itu dan kamu beres:

  • Sebuah Date di dalamnya adalah jumlah milidetik sejak Unix epoch (1 Jan 1970 UTC). Ia menyimpan satu momen dan menampilkannya dalam waktu lokal.
  • Buat tanggal dengan new Date() — tanpa argumen untuk sekarang, sebuah timestamp, bagian-angka, atau string. Bulan berbasis nol (6 = Juli).
  • Baca bagiannya dengan method get. Hati-hati pasangan ini: getDate() itu tanggal dalam bulan (1–31); getDay() itu hari dalam minggu (0 = Minggu).
  • Format untuk manusia pakai Intl.DateTimeFormat, bukan merakit string sendiri. Pakai toISOString() untuk menyimpan dan mengirim.
  • Lakukan hitungan dengan memperlakukan tanggal sebagai angka: kurangkan timestamp untuk dapat selisih, dan pakai method set untuk menambah/mengurangi hari dengan aman.
  • Objek Date itu mutable — salin dengan new Date(d.getTime()) sebelum mengubahnya.
  • Waspadai jebakan zona waktu: string tanggal-saja di-parsing sebagai UTC, string tanggal-waktu sebagai lokal. Simpan dalam UTC, tampilkan dalam lokal.

Begitu kamu nyaman dengan aturan-aturan ini, reputasi “seram” tanggal JavaScript langsung memudar. Sekarang kamu sudah punya semua bekal untuk membuat hitung mundur, timestamp, dan tampilan tanggal yang ramah manusia dengan percaya diri.

Tag:javascriptfrontenddatewaktumenengah
728 × 90Slot Iklan TersediaPasang iklan Anda di sini

Artikel Terkait

Lihat Semua Artikel

Artikel yang Mungkin Kamu Suka

Apa Itu Framework Frontend? — chip kode dengan tag komponen
Frontend / Dasar

Apa Itu Framework Frontend?

Penjelasan ramah untuk pemula tentang apa itu framework frontend, kenapa mereka ada, masalah apa yang mereka selesaikan dibanding JavaScript biasa, dan kapan kamu memang sebaiknya memakainya.

20 Sep 20268 menit baca
Sampul fundamentals frontend bertuliskan Apa Itu Frontend dan HTML + CSS + JS
Frontend / Dasar

Apa Itu Frontend Development?

Panduan ramah pemula tentang frontend development: bagian website yang kamu lihat dan klik secara langsung. Pahami cara kerja HTML, CSS, dan JavaScript, serta bedanya frontend dengan backend.

20 Sep 20268 menit baca
Ilustrasi sampul untuk Apa yang Dikerjakan Frontend Developer
Frontend / Dasar

Apa yang Dikerjakan Frontend Developer: Panduan untuk Pemula

Penjelasan ramah pemula tentang apa yang sebenarnya dikerjakan frontend developer setiap hari: mengubah desain jadi antarmuka yang berfungsi, membangun UI yang bisa dipakai ulang, sampai urusan responsif, aksesibilitas, dan kecepatan.

20 Sep 20269 menit baca
Kartu judul bertuliskan Styling dan Interaktivitas di atas latar biru gelap ACY Partner
Frontend / Dasar

Cara Kerja Styling dan Interaktivitas

Penjelasan ramah pemula soal bagaimana CSS menyulap HTML polos jadi tampilan rapi, dan bagaimana JavaScript menambahkan perilaku — pola berpikir struktur, gaya, perilaku saat membangun halaman web.

20 Sep 20268 menit baca
Tiga lapisan front-end menyatu di satu halaman web
Frontend / Dasar

Cara HTML, CSS, dan JavaScript Bekerja Bersama

Panduan praktis untuk pemula: bikin satu tombol kecil, beri struktur dengan HTML, tampilan dengan CSS, dan perilaku dengan JavaScript, lalu lihat ketiga lapisan ini bekerja sama di halaman nyata.

20 Sep 20268 menit baca
Sampul ikhtisar praktik terbaik frontend
Frontend / Dasar

Ikhtisar Praktik Terbaik Frontend

Peta ringkas tentang apa itu frontend yang baik — HTML bermakna, CSS rapi, JavaScript secukupnya, desain responsif, performa, dan progressive enhancement, lengkap dengan arahan untuk mendalaminya.

20 Sep 20268 menit baca