Berapa pesanan yang masuk bulan lalu? Kapan jatuh tempo pembayaran pelanggan? SQLite menjawab pertanyaan semacam itu dengan pendekatan yang berbeda dari database lain: engine SQLite tidak menyediakan tipe data DATE atau TIMESTAMP sama sekali. Sebagai gantinya, tanggal disimpan memakai konvensi format teks atau angka, lalu diolah oleh keluarga fungsi khusus. Fleksibilitas ini menguntungkan bila kita patuh aturan — dan berbahaya bila lalai, karena '2025-13-45' pun diterima sebagai teks biasa.
Data Contoh #
Kita memakai tabel pesanan dengan kolom tanggal berformat ISO-8601 (YYYY-MM-DD HH:MM:SS) — konvensi yang akan kita pilih sebagai format utama:
CREATE TABLE pesanan (
id INTEGER PRIMARY KEY,
pelanggan TEXT NOT NULL,
tanggal TEXT NOT NULL,
total REAL NOT NULL
);
INSERT INTO pesanan (id, pelanggan, tanggal, total) VALUES
(1, 'Budi', '2025-06-01 09:15:00', 150000),
(2, 'Siti', '2025-06-03 14:30:00', 75000),
(3, 'Budi', '2025-06-10 10:00:00', 220000),
(4, 'Ani', '2025-07-05 16:45:00', 45000),
(5, 'Siti', '2025-07-12 08:20:00', 130000);Tidak Ada Tipe Date — Hanya Konvensi Penyimpanan #
Meskipun deklarasi kolomnya TEXT, yang tersimpan tetap teks. Kita bisa membuktikannya dengan fungsi typeof():
SELECT typeof(tanggal), tanggal FROM pesanan WHERE id = 1;Output yang Dihasilkan:
text|2025-06-01 09:15:00Dokumentasi resmi SQLite mengakui tiga konvensi penyimpanan yang dipahami oleh fungsi tanggal:
| Konvensi | Tipe | Contoh | Cocok untuk |
|---|---|---|---|
| ISO-8601 | TEXT | '2025-06-15 10:30:00' | Keterbacaan dan perbandingan string |
| Unix epoch | INTEGER | 1749983400 | Berinteraksi dengan sistem lain |
| Julian day | REAL | 2460842.0 | Perhitungan astronomis dan selisih waktu lama |
Praktik terbaik untuk aplikasi umum adalah ISO-8601: formatnya terbaca manusia, dapat dibandingkan langsung sebagai string, dan dikenali semua fungsi tanggal SQLite.
Fungsi Tanggal dan Waktu #
Empat fungsi inti menerima nilai waktu lalu memformatnya kembali: date() menghasilkan tanggal, time() hanya jam, dan datetime() keduanya:
SELECT date('2025-06-15 10:30:00'), time('2025-06-15 10:30:00'), datetime('2025-06-15 10:30:00');Output yang Dihasilkan:
2025-06-15|10:30:00|2025-06-15 10:30:00Ketepatan format dicapai lewat strftime(), yang menyalin tanggal ke template berisi kode format:
SELECT strftime('%Y', '2025-06-15'), strftime('%H:%M', '2025-06-15 10:30:00'),
strftime('%j', '2025-06-15'), strftime('%W', '2025-06-15');Output yang Dihasilkan:
2025|10:30|166|23Kode-kode yang paling sering dipakai:
| Kode | Arti | Contoh hasil |
|---|---|---|
%Y %m %d | Tahun, bulan, tanggal | 2025, 06, 15 |
%H %M %S | Jam, menit, detik | 10, 30, 00 |
%s | Detik Unix | 1749983400 |
%j | Hari ke-n dalam tahun (001-366) | 166 |
%W | Pekan ke-n dalam tahun (00-53) | 23 |
Dua fungsi konversi melengkapi kelompok ini. unixepoch() (hadir sejak SQLite 3.38) menghasilkan detik Unix, sedangkan julianday() menghasilkan bilangan hari Julian — berguna untuk menghitung selisih waktu dalam satuan hari pecahan:
SELECT unixepoch('2025-06-15 10:30:00'), julianday('2025-06-15 12:00:00');Output yang Dihasilkan:
1749983400|2460842.0Keduanya bisa dibalik: tambahkan modifier 'unixepoch' untuk bilangan bulat, atau berikan REAL Julian langsung ke fungsi tanggal:
SELECT datetime(1749983400, 'unixepoch'), date(2460842.0);Output yang Dihasilkan:
2025-06-15 10:30:00|2025-06-15Satu nilai waktu istimewa adalah 'now' — waktu UTC saat query dijalankan:
SELECT datetime('now');Output yang Dihasilkan (berubah mengikuti waktu eksekusi):
2026-10-13 04:26:01Aritmetika Tanggal dengan Modifier #
Fungsi tanggal menerima modifier tambahan yang menggeser atau menyetel nilai waktu. '+7 days' menambah hari, 'start of month' memundurkan ke tanggal satu bulan, dan 'weekday N' maju ke hari-N berikutnya (0 = Minggu):
SELECT date('2025-06-15', '+7 days'), date('2025-06-15', 'start of month'), date('2025-06-15', 'weekday 1');Output yang Dihasilkan:
2025-06-22|2025-06-01|2025-06-16Tanggal 2025-06-15 jatuh hari Minggu, sehingga weekday 1 melompat ke Senin 2025-06-16. Modifier bisa dirangkai dan diproses dari kiri ke kanan:
SELECT datetime('2025-06-15 10:30:00', '+2 hours', '-15 minutes');Output yang Dihasilkan:
2025-06-15 12:15:00Pola paling praktis: menghitung jatuh tempo 14 hari dari setiap pesanan:
SELECT id, pelanggan, tanggal, date(tanggal, '+14 days') AS jatuh_tempo
FROM pesanan ORDER BY id;Output yang Dihasilkan:
1|Budi|2025-06-01 09:15:00|2025-06-15
2|Siti|2025-06-03 14:30:00|2025-06-17
3|Budi|2025-06-10 10:00:00|2025-06-24
4|Ani|2025-07-05 16:45:00|2025-07-19
5|Siti|2025-07-12 08:20:00|2025-07-26Laporan Bulanan dan Rentang Tanggal #
Karena format ISO-8601 tersusun dari satuan terbesar ke terkecil, urutan abjadnya sama dengan urutan waktunya. Itulah sebabnya perbandingan string langsung memadai untuk menyaring rentang:
SELECT id, pelanggan, tanggal FROM pesanan
WHERE tanggal >= '2025-07-01' ORDER BY tanggal;Output yang Dihasilkan:
4|Ani|2025-07-05 16:45:00
5|Siti|2025-07-12 08:20:00Untuk mengelompokkan per bulan, date(tanggal, 'start of month') menjadi kunci GROUP BY yang rapi:
SELECT date(tanggal, 'start of month') AS bulan, SUM(total) AS omzet
FROM pesanan GROUP BY 1 ORDER BY 1;Output yang Dihasilkan:
2025-06-01|445000.0
2025-07-01|175000.0Alternatif yang lebih ringkas untuk label bulan adalah strftime('%Y-%m', ...):
SELECT strftime('%Y-%m', tanggal) AS bulan, COUNT(*) AS jumlah_pesanan
FROM pesanan GROUP BY 1 ORDER BY 1;Output yang Dihasilkan:
2025-06|3
2025-07|2Jebakan Tanggal Tidak Valid #
Engine SQLite tidak memvalidasi isi kolom TEXT — string apa pun lolos. Fungsi tanggal adalah satu-satunya alat pemeriksa, dan jawabannya adalah NULL untuk nilai yang tak bisa dipahami:
SELECT date('2025-13-45'), date('bukan tanggal');Output yang Dihasilkan:
|Kita bisa memaksa kualitas data lewat CHECK constraint. Trik tanggal IS datetime(tanggal) menuntut nilai tersimpan identik dengan bentuk bakunya — operator IS dipakai agar NULL dari datetime() ikut dianggap gagal:
CREATE TABLE pesanan_aman (
id INTEGER PRIMARY KEY,
tanggal TEXT NOT NULL CHECK (tanggal IS datetime(tanggal))
);Kolom ini kini menolak tanggal sampah:
sqlite3 toko.db "INSERT INTO pesanan_aman (id, tanggal) VALUES (2, '2025-13-45 10:00:00');"Output yang Dihasilkan:
Error: stepping, CHECK constraint failed: tanggal IS datetime(tanggal) (19)Angka 19 di akhir adalah kode SQLITE_CONSTRAINT. Perlu dicatat juga bahwa trik ini menuntut format lengkap YYYY-MM-DD HH:MM:SS — nilai '2025-06-15' tanpa jam akan ditolak karena datetime('2025-06-15') menormalkannya menjadi '2025-06-15 00:00:00'.
Skema kolom tanggal kini aman. Fitur lanjutan berikutnya menyimpan data semi-terstruktur di satu kolom: JSON, yang dibahas pada Chapter Memproses JSON dalam SQLite.