Menu

Tanggal dan Waktu di SQLite: strftime, date(), datetime(), dan Modifier

Cara SQLite menyimpan dan mengolah tanggal: lima fungsi tanggal, format string, modifier, dan pilihan penyimpanan yang menjaga query-mu tetap cepat.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

SQLite Sebenarnya Tidak Punya Tipe Tanggal

Hal ini menjebak semua orang yang terbiasa dengan Postgres atau MySQL. SQLite punya lima storage class, yaitu NULL, INTEGER, REAL, TEXT, BLOB, dan hanya itu. Tidak ada DATE, DATETIME, atau TIMESTAMP. Kamu boleh menulis created_at DATETIME di CREATE TABLE, dan SQLite akan menerimanya, tapi nilainya disimpan sebagai teks biasa atau angka.

Yang disediakan SQLite adalah sekumpulan fungsi yang memahami tiga format yang lazim:

  • Teks ISO 8601: '2026-04-23', '2026-04-23 10:15:00', '2026-04-23T10:15:00.123Z'.
  • Unix timestamp: jumlah detik sejak 1970-01-01 UTC, disimpan sebagai integer.
  • Julian day: jumlah hari (bisa pecahan) sejak 4714 SM, disimpan sebagai real.

Pilih satu dan konsistenlah. Teks ISO 8601 paling mudah dibaca dan urutannya benar saat diurutkan sebagai string, itulah sebabnya format ini menjadi bawaan.

Empat cara menanyakan "saat ini": tanggal sebagai teks, tanggal dan waktu sebagai teks, detik Unix, dan Julian day. Semuanya menggambarkan momen yang sama.

Lima Fungsi Tanggal

SQLite menyediakan lima fungsi bawaan yang mencakup hampir semua kebutuhan:

  • date(time, ...): mengembalikan YYYY-MM-DD.
  • time(time, ...): mengembalikan HH:MM:SS.
  • datetime(time, ...): mengembalikan YYYY-MM-DD HH:MM:SS.
  • julianday(time, ...): mengembalikan real (bagus untuk menghitung selisih).
  • strftime(format, time, ...): mengembalikan string dengan format khusus.

Masing-masing menerima nilai waktu sebagai argumen pertama, lalu string modifier sebanyak apa pun.

Perhatikan 'unixepoch': itulah cara memberi tahu fungsi tanggal bahwa integer input-nya adalah Unix timestamp, bukan Julian day. Tanpanya, SQLite menganggap angka itu Julian day.

strftime: Format Tanggal Khusus

strftime adalah fungsi andalan. Kode %-nya sama seperti yang kamu kenal dari C atau Python:

Kode yang paling sering kamu pakai:

  • %Y: tahun empat digit.
  • %m: bulan (01-12).
  • %d: tanggal dalam bulan (01-31).
  • %H, %M, %S: jam, menit, detik.
  • %w: hari dalam minggu (0=Minggu).
  • %j: hari dalam tahun (001-366).
  • %s: Unix timestamp.
  • %f: detik dengan pecahan (SS.SSS).

strftime juga merupakan cara untuk mengambil bagian dari sebuah tanggal, karena tidak ada fungsi EXTRACT atau YEAR() tersendiri. Kamu cukup memformatnya hingga tersisa bagian yang kamu mau, lalu melakukan cast kalau butuh angka:

strftime selalu mengembalikan teks, jadi bungkus dengan CAST(... AS INTEGER) kalau kamu ingin melakukan aritmetika atau membandingkan sebagai angka.

Modifier: Matematika Tanggal Tanpa Operator

Inilah fitur yang membuat pengolahan tanggal di SQLite terasa menyenangkan. Setelah argumen waktu, kamu bisa memberikan string modifier sebanyak apa pun, dan semuanya diterapkan berurutan:

Modifier yang akan terus kamu pakai:

  • '+N days', '-N days', dan bentuk yang sama untuk hours, minutes, seconds, months, years.
  • 'start of day', 'start of month', 'start of year': memotong ke batas itu.
  • 'weekday N': maju ke hari dalam minggu berikutnya yang ditentukan (0=Minggu).
  • 'localtime' dan 'utc': mengonversi antarzona waktu.

Trik "hari terakhir dalam bulan", yaitu awal bulan, tambah satu bulan, kurangi satu hari, layak dihafal. SQLite tidak punya fungsi LAST_DAY, tapi merangkai modifier memberimu hasil yang sama.

UTC vs Waktu Lokal

'now' selalu mengembalikan UTC. Kalau kamu ingin waktu lokal, kamu harus memintanya:

Modifier 'localtime' mengubah nilai UTC ke zona waktu lokal sistem. Modifier 'utc' melakukan kebalikannya: ia menganggap input-nya sebagai waktu lokal dan mengubahnya ke UTC.

Kebiasaan yang aman: simpan semuanya dalam UTC, dan ubah ke waktu lokal hanya saat ditampilkan. Mencampur zona waktu di penyimpanan menimbulkan bug yang muncul dua kali setahun saat daylight saving bergeser.

Membandingkan Tanggal dan Memfilter Rentang

Kalau kamu menyimpan tanggal sebagai teks ISO 8601, perbandingan dan BETWEEN langsung bekerja, karena urutan leksikografis ISO 8601 sama dengan urutan kronologisnya. Itulah alasan utama format ini menjadi bawaan.

Rentang setengah terbuka (>= start, < end) adalah kebiasaan yang berguna, karena sepenuhnya menghindari pertanyaan "tengah malam tanggal 30 ikut terhitung atau tidak?".

Untuk "7 hari terakhir", biarkan SQLite yang menghitung batasnya:

Selisih Tanggal

SQLite tidak punya DATEDIFF. Dua pola ini mencakup semuanya:

Selisih julianday() dihitung dalam hari (dengan presisi pecahan), jadi mengalikannya dengan 24 menghasilkan jam, dan dengan 1440 menghasilkan menit. Selisih strftime('%s', ...) dihitung dalam detik, praktis kalau kamu ingin integer.

CAST(... AS INTEGER) memotong pecahan hari kalau kamu ingin hitungan hari yang utuh:

Menyimpan Tanggal: Pilih Satu Format dan Konsistenlah

Ada tiga pilihan yang masuk akal, diurutkan dari yang paling sering sebaiknya kamu pilih:

  1. Teks ISO 8601 (TEXT). Mudah dibaca di hasil dump, urutannya benar, dan cocok dengan semua fungsi tanggal. Pilihan bawaan.
  2. Detik Unix (INTEGER). Ringkas, perbandingannya cepat, dan tidak ada keraguan soal zona waktu. Bagus kalau kamu punya jutaan baris. Kamu butuh datetime(col, 'unixepoch') untuk membacanya kembali.
  3. Julian day (REAL). Jarang sepadan, kecuali kamu banyak melakukan aritmetika tanggal dan ingin presisi di bawah satu detik dalam satu kolom.

Yang tidak boleh kamu lakukan adalah mencampur format dalam kolom yang sama. Fungsi tanggal akan diam-diam menerima keduanya, tapi index, pengurutan, dan perbandingan akan menghasilkan hal yang tidak masuk akal.

DEFAULT (datetime('now')) adalah padanan DEFAULT CURRENT_TIMESTAMP di SQLite: setiap baris baru diberi cap waktu UTC saat ini tanpa melibatkan kode aplikasi sama sekali.

Mengelompokkan Berdasarkan Periode Waktu

strftime unggul saat kamu ingin mengelompokkan baris per bulan, minggu, atau jam:

Idenya sama untuk "pesanan per jam dalam sehari," "pendaftaran per hari dalam minggu," atau "event per menit": pilih format string yang hanya menangkap tingkat detail yang kamu inginkan, kelompokkan berdasarkan itu, lalu lakukan agregasi.

Berikutnya: Fungsi Agregat

Omong-omong soal pengelompokan, COUNT(*) tadi adalah fungsi agregat SQLite yang paling sederhana. Berikutnya kita akan melihat semuanya: SUM, AVG, MIN, MAX, dan cara fungsi-fungsi itu meringkas banyak baris menjadi satu nilai.

Pertanyaan yang sering diajukan

Apakah SQLite punya tipe data DATE atau DATETIME?

Tidak. SQLite tidak punya tipe khusus untuk tanggal. Kamu menyimpan tanggal sebagai TEXT dalam format ISO 8601 ('2026-04-23 10:15:00'), sebagai INTEGER berupa Unix timestamp, atau sebagai REAL berupa Julian day. Fungsi tanggal bawaannya menerima ketiga format itu dan secara bawaan mengembalikan teks ISO 8601.

Bagaimana cara mendapatkan tanggal dan waktu saat ini di SQLite?

Pakai date('now') untuk tanggal saat ini, time('now') untuk waktu saat ini, datetime('now') untuk keduanya, dan strftime('%s', 'now') untuk Unix timestamp. Secara bawaan, fungsi ini mengembalikan UTC. Berikan 'localtime' sebagai modifier untuk mengubahnya: datetime('now', 'localtime').

Bagaimana cara menambahkan hari atau bulan ke sebuah tanggal di SQLite?

Berikan string modifier ke fungsi tanggal mana pun: date('2026-04-23', '+7 days'), date('now', '-1 month'), datetime('now', '+2 hours', '+30 minutes'). Modifier diterapkan berurutan, dan satuannya mencakup days, hours, minutes, seconds, months, dan years.

Bagaimana cara menghitung selisih antara dua tanggal?

Untuk hari, pakai julianday(end) - julianday(start). Julian day berupa floating-point, jadi hasilnya mencakup pecahan hari. Untuk detik, kurangkan Unix timestamp: strftime('%s', end) - strftime('%s', start). SQLite tidak punya fungsi DATEDIFF; kedua pola ini mencakup hampir semua kasus.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai