Tanggal & Waktu: DATE, TIMESTAMP, EXTRACT, TO_CHAR, DATE_TRUNC
Bekerja dengan tanggal di PostgreSQL: CURRENT_DATE, NOW(), INTERVAL, EXTRACT, TO_CHAR untuk format, DATE_TRUNC untuk pengelompokan, serta menghitung selisih.
Analogi: DATE dan TIMESTAMP itu seperti kalender dan jam dinding. EXTRACT adalah menyobek satu bagian kalender (ambil bulannya saja), TO_CHAR adalah mencetak tanggal dengan gaya yang kamu mau, dan DATE_TRUNC adalah "membulatkan ke awal bulan" supaya semua transaksi bulan yang sama dikumpulkan di satu laci.
Tipe tanggal dan waktu
| Tipe | Isi | Contoh |
|---|---|---|
DATE | Tanggal saja | '2025-03-01' |
TIME | Jam saja | '14:30:00' |
TIMESTAMP | Tanggal + jam | '2025-03-01 14:30:00' |
TIMESTAMPTZ | Tanggal + jam + zona waktu (disarankan untuk aplikasi) | '2025-03-01 14:30:00+07' |
Tanggal ditulis sebagai teks berformat YYYY-MM-DD (tahun-bulan-hari), format internasional yang tidak membingungkan.
Waktu sekarang
SELECT CURRENT_DATE; -- tanggal hari ini
SELECT NOW(); -- tanggal + jam saat ini
SELECT CURRENT_TIMESTAMP; -- sama dengan NOW()
Menghitung dengan tanggal
Di PostgreSQL tanggal bisa dijumlah dan dikurangi langsung, dan ada tipe INTERVAL untuk rentang waktu:
SELECT CURRENT_DATE + 7; -- 7 hari lagi
SELECT CURRENT_DATE - INTERVAL '1 month'; -- sebulan lalu
SELECT '2025-03-01'::date - '2025-01-01'::date; -- 59 (selisih hari, bilangan bulat)
SELECT AGE('2025-03-01', '2000-05-20'); -- 24 years 9 mons 11 days
Catatan simulator: penghitungan dengan INTERVAL dan AGE hanya bisa kamu coba di PostgreSQL asli. Di editor latihan, fokuslah pada EXTRACT, TO_CHAR, DATE_TRUNC, dan perbandingan tanggal.
EXTRACT: mengambil bagian tanggal
SELECT EXTRACT(YEAR FROM tgl_daftar) AS tahun,
EXTRACT(MONTH FROM tgl_daftar) AS bulan,
EXTRACT(DAY FROM tgl_daftar) AS hari
FROM pelanggan;
Bagian lain yang tersedia: QUARTER, WEEK, DOW (hari dalam pekan, 0 = Minggu), HOUR, MINUTE.
TO_CHAR: mengubah tanggal menjadi teks berformat
SELECT TO_CHAR(tanggal, 'DD Mon YYYY') FROM pesanan; -- 05 Jan 2025
SELECT TO_CHAR(tanggal, 'YYYY-MM') FROM pesanan; -- 2025-01
SELECT TO_CHAR(tanggal, 'Day, DD Month YYYY') FROM pesanan;
| Kode | Arti | Kode | Arti |
|---|---|---|---|
YYYY | tahun 4 digit | MM | bulan 2 digit |
DD | tanggal 2 digit | Mon | nama bulan singkat |
HH24 | jam 00-23 | MI / SS | menit / detik |
DATE_TRUNC: "memotong" ke awal periode
SELECT DATE_TRUNC('month', DATE '2025-03-15'); -- 2025-03-01
SELECT DATE_TRUNC('year', tgl_daftar) FROM pelanggan;
Sangat berguna untuk laporan bulanan: semua tanggal dalam bulan yang sama "dibulatkan" ke tanggal 1, sehingga mudah dikelompokkan (kita pakai di bab GROUP BY).
Menyaring berdasarkan rentang tanggal
SELECT * FROM pesanan
WHERE tanggal >= '2025-02-01' AND tanggal < '2025-03-01'; -- semua pesanan Februari
Pola aman: batas awal dengan >= dan batas akhir dengan < (tanggal 1 bulan berikutnya). Cara ini benar untuk DATE maupun TIMESTAMP.
Kasus nyata: laporan penjualan bulanan dan pelanggan baru
Bos meminta jumlah pesanan per bulan. Kuncinya memotong tanggal ke bulan:
SELECT DATE_TRUNC('month', tanggal) AS bulan, COUNT(*) AS jumlah_pesanan
FROM pesanan
GROUP BY 1 ORDER BY 1;
-- pelanggan yang mendaftar dalam 30 hari terakhir
SELECT nama FROM pelanggan WHERE tgl_daftar >= CURRENT_DATE - 30;
Kesalahan yang sering terjadi
- Menyimpan tanggal sebagai teks sehingga tidak bisa dipakai di fungsi tanggal.
- Mengabaikan zona waktu. Untuk waktu kejadian lintas negara, pakai
TIMESTAMPTZ. - Membandingkan
TIMESTAMPdengan= '2026-10-13'; jamnya ikut dihitung. Gunakan rentang (>= hari ini dan < besok) atau cast ke::date.