kodingup.camp

Beranda/JavaScript Mastery: Prototype, Class, Waktu, Error & Async

Operasi & Format Tanggal

Modul 7 dari 153 menit bacaDate Operations & Formatting

Isi modul

    Kenapa ini penting

    Setelah tahu isi Date, sekarang kamu perlu dua keterampilan praktis: membaca dan mengubah bagian-bagian tanggal (tahun, bulan, jam) serta menampilkannya dengan format yang ramah pengguna Indonesia. Pengguna tidak ingin melihat 2026-10-23T07:30:00.000Z. Mereka ingin "Jumat, 23 Oktober 2026 pukul 14.30". Struk belanja, notifikasi, laporan bulanan, dan undangan acara semuanya butuh format yang tepat.

    Banyak pemula menyusun format sendiri dengan menggabungkan string dan array nama bulan. Cara itu panjang, rawan salah, dan susah diterjemahkan. JavaScript sudah menyediakan Intl.DateTimeFormat, mesin format bawaan yang paham ratusan bahasa termasuk id-ID. Di modul ini kamu belajar memakai alat yang benar.

    Konsep inti

    Getter: membaca bagian tanggal

    Lokal UTC Hasil
    getFullYear() getUTCFullYear() Tahun 4 digit
    getMonth() getUTCMonth() 0-11
    getDate() getUTCDate() Tanggal 1-31
    getDay() getUTCDay() Hari 0 (Minggu)-6 (Sabtu)
    getHours(), getMinutes(), getSeconds(), getMilliseconds() versi UTC Jam dst

    Versi lokal memakai zona waktu komputer/browser yang menjalankan kode. Di server berzona UTC, getHours() akan berbeda dengan di laptopmu yang WIB. Ingat juga: getDate() = tanggal, getDay() = hari dalam minggu. Namanya mirip, artinya berbeda.

    Setter: mengubah bagian tanggal

    setFullYear, setMonth, setDate, setHours, dan seterusnya (plus versi UTC). Dua sifat penting:

    1. Mutable: setter mengubah object aslinya. Salin dulu dengan new Date(d) jika aslinya masih dipakai.
    2. Rollover otomatis: setDate(32) di bulan Oktober otomatis menjadi 1 November. Ini berguna untuk menambah hari, tetapi bisa mengejutkan (31 Januari + 1 bulan = 3 Maret).

    Format bawaan

    Method Contoh hasil
    toISOString() 2026-10-23T07:30:00.000Z (selalu UTC, untuk mesin)
    toJSON() Sama dengan toISOString(), dipakai JSON.stringify
    toString() Format panjang bahasa Inggris, tergantung lingkungan
    toLocaleDateString("id-ID", opsi) 23/10/2026
    toLocaleTimeString("id-ID", opsi) 14.30.00

    Perhatikan format Indonesia memakai titik sebagai pemisah jam (14.30), sesuai kaidah bahasa Indonesia.

    Intl.DateTimeFormat

    const fmt = new Intl.DateTimeFormat("id-ID", { dateStyle: "full", timeZone: "Asia/Jakarta" });
    fmt.format(tanggal);
    

    Opsi yang sering dipakai:

    dateStyle/timeStyle tidak boleh dicampur dengan opsi detail seperti weekday (akan TypeError). Pilih salah satu pendekatan.

    Membuat formatter itu relatif mahal. Jika memformat ribuan tanggal (misalnya tabel transaksi), buat formatter sekali lalu panggil format() berulang kali.

    formatToParts() mengembalikan potongan-potongan (hari, bulan, tahun) sebagai array, berguna jika kamu butuh menyusun tampilan khusus.

    Sebagai bonus, Intl.RelativeTimeFormat menghasilkan teks seperti "kemarin" atau "dalam 3 hari".

    Contoh kode

    const d = new Date("2026-10-23T14:30:00+07:00"); // Jumat, 14.30 WIB
    const TZ = "Asia/Jakarta";
    
    // 1. Getter (hasil di bawah jika komputer berzona WIB)
    console.log(d.getFullYear(), d.getMonth() + 1, d.getDate()); // → 2026 10 23
    console.log(d.getDay());   // → 5 (Jumat; 0 = Minggu)
    console.log(d.getHours(), d.getUTCHours()); // → 14 7
    
    // 2. Setter dengan salinan (jangan ubah aslinya)
    const besok = new Date(d);
    besok.setDate(besok.getDate() + 1);
    console.log(d.getDate(), besok.getDate()); // → 23 24
    
    // 3. Rollover otomatis
    const akhirBulan = new Date(2026, 9, 31);
    akhirBulan.setDate(akhirBulan.getDate() + 1);
    console.log(akhirBulan.toDateString()); // → Sun Nov 01 2026
    
    // Hari terakhir bulan: tanggal 0 bulan berikutnya
    const hariTerakhirFeb = new Date(2026, 2, 0).getDate();
    console.log(hariTerakhirFeb); // → 28
    
    // 4. Format standar Intl dengan berbagai gaya
    for (const gaya of ["full", "long", "medium", "short"]) {
      const f = new Intl.DateTimeFormat("id-ID", { dateStyle: gaya, timeZone: TZ });
      console.log(gaya.padEnd(6), f.format(d));
    }
    // → full   Jumat, 23 Oktober 2026
    // → long   23 Oktober 2026
    // → medium 23 Okt 2026
    // → short  23/10/26
    
    // 5. Tanggal + jam + nama zona
    const lengkap = new Intl.DateTimeFormat("id-ID", {
      weekday: "long", day: "numeric", month: "long", year: "numeric",
      hour: "2-digit", minute: "2-digit", timeZone: TZ, timeZoneName: "short",
    });
    console.log(lengkap.format(d)); // → Jumat, 23 Oktober 2026 pukul 14.30 WIB
    
    // 6. Formatter dipakai ulang untuk banyak data
    const fmtTanggal = new Intl.DateTimeFormat("id-ID", { day: "2-digit", month: "short", year: "numeric", timeZone: TZ });
    const transaksi = [
      { ket: "Gaji", waktu: "2026-10-01T02:00:00Z" },
      { ket: "Listrik", waktu: "2026-10-05T10:15:00Z" },
    ];
    for (const t of transaksi) {
      console.log(fmtTanggal.format(new Date(t.waktu)), t.ket);
    }
    // → 01 Okt 2026 Gaji
    // → 05 Okt 2026 Listrik
    
    // 7. formatToParts untuk tampilan khusus
    const parts = new Intl.DateTimeFormat("id-ID", { day: "numeric", month: "long", timeZone: TZ }).formatToParts(d);
    const ambil = (type) => parts.find((p) => p.type === type).value;
    console.log(`Tanggal ${ambil("day")} bulan ${ambil("month")}`); // → Tanggal 23 bulan Oktober
    
    // 8. Format kunci YYYY-MM-DD sesuai WIB (untuk mengelompokkan transaksi per hari)
    function kunciTanggalWIB(date) {
      // locale en-CA kebetulan memformat sebagai YYYY-MM-DD
      return new Intl.DateTimeFormat("en-CA", { timeZone: TZ }).format(date);
    }
    console.log(kunciTanggalWIB(new Date("2026-10-31T18:00:00Z"))); // → 2026-11-01 (sudah 01.00 WIB)
    
    // 9. Waktu relatif
    const rtf = new Intl.RelativeTimeFormat("id-ID", { numeric: "auto" });
    console.log(rtf.format(-1, "day"), "|", rtf.format(3, "day"), "|", rtf.format(-2, "hour"));
    // → kemarin | dalam 3 hari | 2 jam yang lalu
    

    Contoh 8 sangat penting untuk aplikasi keuangan. Transaksi pada 2026-10-31T18:00:00Z jika dilihat dari UTC masih tanggal 31 Oktober, padahal di Jakarta sudah 1 November pukul 01.00. Jika laporanmu untuk pengguna Indonesia, kelompokkan berdasarkan tanggal WIB, bukan dengan memotong string ISO (toISOString().slice(0, 10)), karena string ISO selalu UTC.

    Kesalahan umum

    1. Memotong toISOString() untuk mendapatkan tanggal lokal. Hasilnya tanggal UTC, bisa mundur satu hari untuk waktu 00.00-06.59 WIB. Gunakan Intl.DateTimeFormat dengan timeZone.
    2. Tertukar getDay() dan getDate(). getDay() hari dalam minggu (0-6), getDate() tanggal (1-31).
    3. Setter mengubah object asli yang masih dipakai di tempat lain. Salin dulu: const salinan = new Date(asli).
    4. Tidak menyebut timeZone. Hasil format berbeda di laptop (WIB) dan server (UTC). Tentukan zona secara eksplisit.
    5. Mencampur dateStyle dengan weekday/month. Kombinasi ini memunculkan TypeError. Pakai salah satu.

    Latihan

    1. Mudah, Format new Date("2026-12-25T09:00:00+07:00") menjadi "Jumat, 25 Desember 2026" memakai Intl.DateTimeFormat.
    2. Sedang, Buat function awalBulan(date) dan akhirBulan(date) yang mengembalikan Date baru untuk tanggal 1 dan tanggal terakhir pada bulan yang sama (waktu lokal 00.00), tanpa mengubah input.
    3. Menantang, Kelompokkan array transaksi { jumlah, waktu (ISO UTC) } berdasarkan tanggal WIB (YYYY-MM-DD) dan hitung total per tanggal.
    Lihat solusi
    // 1
    const natal = new Date("2026-12-25T09:00:00+07:00");
    console.log(new Intl.DateTimeFormat("id-ID", { dateStyle: "full", timeZone: "Asia/Jakarta" }).format(natal));
    // → Jumat, 25 Desember 2026
    
    // 2
    const awalBulan = (date) => new Date(date.getFullYear(), date.getMonth(), 1);
    const akhirBulan = (date) => new Date(date.getFullYear(), date.getMonth() + 1, 0);
    const x = new Date(2028, 1, 10);
    console.log(awalBulan(x).getDate(), akhirBulan(x).getDate(), x.getDate()); // → 1 29 10
    
    // 3
    const kunci = new Intl.DateTimeFormat("en-CA", { timeZone: "Asia/Jakarta" });
    const data = [
      { jumlah: 50000, waktu: "2026-10-31T16:00:00Z" }, // 23.00 WIB tgl 31
      { jumlah: 20000, waktu: "2026-10-31T17:30:00Z" }, // 00.30 WIB tgl 1
      { jumlah: 30000, waktu: "2026-11-01T03:00:00Z" },
    ];
    const perTanggal = data.reduce((acc, { jumlah, waktu }) => {
      const k = kunci.format(new Date(waktu));
      acc[k] = (acc[k] ?? 0) + jumlah;
      return acc;
    }, {});
    console.log(perTanggal); // → { '2026-10-31': 50000, '2026-11-01': 50000 }
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.