- 1 1. SQL terpendek untuk mendapatkan tanggal/waktu saat ini di MySQL
- 1.1 1.1 Dapatkan tanggal/waktu saat ini (dasar)
- 1.2 1.2 Dapatkan tanggal hari ini saja
- 1.3 1.3 Dapatkan waktu saat ini saja
- 1.4 1.4 Dapatkan waktu saat ini dalam UTC (penting)
- 1.5 1.5 Dapatkan milidetik / mikrodetik
- 1.6 1.6 Fungsi terbaik berdasarkan kasus penggunaan (mulai di sini jika tidak yakin)
- 1.7 Poin penting yang sering terlewat orang
- 2 2. Perbedaan antara NOW() / CURRENT_TIMESTAMP / SYSDATE()
- 3 3. Ubah format tampilan tanggal/waktu saat ini
- 4 4. Perhitungan datetime menggunakan waktu saat ini
- 4.1 4.1 Tambah/kurangi dengan INTERVAL
- 4.2 4.2 Mengambil data dari 24 jam terakhir (pola paling umum)
- 4.3 4.3 Mendapatkan selisih hari dengan DATEDIFF()
- 4.4 4.4 Gunakan TIMESTAMPDIFF() untuk jam/menit/detik
- 4.5 4.5 Mendapatkan awal bulan / akhir bulan (perangkap umum di dunia nyata)
- 4.6 Ringkasan kesalahan umum
- 4.7 Poin penting dari bagian ini
- 5 5. Untuk kueri rentang, ini lebih aman daripada BETWEEN
- 5.1 5.1 Dasar-dasar BETWEEN dan jebakan
- 5.2 5.2 Pola yang lebih aman (direkomendasikan)
- 5.3 5.3 Cara yang benar untuk mendapatkan data hari ini
- 5.4 5.4 Pola aman untuk 7 hari terakhir / 30 hari terakhir
- 5.5 5.5 Aturan kunci untuk menjaga indeks tetap efektif
- 5.6 Ringkasan kesalahan umum
- 5.7 Poin penting dari bagian ini
- 6 6. DEFAULT CURRENT_TIMESTAMP dan ON UPDATE (dasar desain tabel)
- 6.1 6.1 Menetapkan otomatis created_at (DEFAULT CURRENT_TIMESTAMP)
- 6.2 6.2 Pembaruan otomatis updated_at (ON UPDATE)
- 6.3 6.3 DATETIME vs TIMESTAMP (penting)
- 6.4 6.4 CURRENT_TIMESTAMP juga dapat digunakan dengan DATETIME
- 6.5 6.5 Jika Anda ingin menggunakan NOW(): alternatif (trigger)
- 6.6 Kesalahan desain umum
- 6.7 Hal penting yang harus diingat dari bagian ini
- 7 7. Desain zona waktu (simpan dalam UTC, tampilkan dalam waktu lokal)
- 7.1 7.1 Periksa zona waktu saat ini
- 7.2 7.2 Ubah zona waktu per sesi
- 7.3 7.3 Mengapa menyimpan dalam UTC (prinsip dunia nyata)
- 7.4 7.4 Konversi zona waktu dengan CONVERT_TZ()
- 7.5 7.5 Mengapa CONVERT_TZ() mengembalikan NULL
- 7.6 7.6 Ubah zona waktu seluruh server
- 7.7 Kesalahan umum
- 7.8 Hal penting yang harus diingat dari bagian ini
- 8 8. Contoh praktis yang dapat langsung Anda gunakan
- 8.1 8.1 Secara otomatis menyisipkan waktu saat ini ke dalam log
- 8.2 8.2 Memperbarui waktu login terakhir
- 8.3 8.3 Memperbaiki waktu referensi dalam pekerjaan batch
- 8.4 8.4 Agregasi untuk hari ini / kemarin / 7 hari terakhir
- 8.5 8.5 Pemeriksaan kedaluwarsa (sesi/token)
- 8.6 8.6 Mendapatkan baris yang kedaluwarsa dalam N jam
- 8.7 Apa yang harus selalu Anda ingat
- 8.8 Poin utama dari bagian ini
- 9 9. Pertanyaan yang Sering Diajukan (FAQ)
- 9.1 9.1 Apa perbedaan antara NOW() dan CURRENT_TIMESTAMP?
- 9.2 9.2 Haruskah Anda menggunakan SYSDATE()?
- 9.3 9.3 Mengapa waktu bergeser?
- 9.4 9.4 CONVERT_TZ() returns NULL
- 9.5 9.5 Range shifts with BETWEEN
- 9.6 9.6 Bagaimana Anda memilih antara DATETIME dan TIMESTAMP?
- 9.7 9.7 Mikrodetik tidak disimpan
- 9.8 Poin penting dari bagian ini
- 10 10. Ringkasan
1. SQL terpendek untuk mendapatkan tanggal/waktu saat ini di MySQL
Jika Anda ingin mendapatkan tanggal/waktu saat ini di MySQL, fungsi pertama yang harus diingat adalah NOW() dan CURRENT_TIMESTAMP. Di bawah ini contoh SQL terpendek berdasarkan kasus penggunaan.
1.1 Dapatkan tanggal/waktu saat ini (dasar)
SELECT NOW();
atau
SELECT CURRENT_TIMESTAMP;
- Keduanya mengembalikan tanggal/waktu saat ini (YYYY-MM-DD HH:MM:SS).
- Dalam satu query yang sama, waktu tetap pada “waktu mulai query”.
Kasus penggunaan
- Pencatatan log
- Mendapatkan timestamp pembuatan record
- Mendapatkan waktu referensi
Kesalahan umum
- Zona waktu aplikasi dan zona waktu DB berbeda sehingga terjadi “pergeseran waktu.” → Periksa dengan
SELECT @@session.time_zone;
1.2 Dapatkan tanggal hari ini saja
SELECT CURDATE();
- Format yang dikembalikan:
YYYY-MM-DD - Tipe adalah DATE (hanya tanggal, bukan datetime)
Kasus penggunaan
- Mencari data “hari ini”
- Agregasi harian
Catatan
- Tidak seperti
NOW(), tidak menyertakan waktu. - Jika Anda membutuhkan waktu untuk kueri rentang, gunakan
NOW().
1.3 Dapatkan waktu saat ini saja
SELECT CURTIME();
- Format yang dikembalikan:
HH:MM:SS - Tipe adalah TIME (hanya waktu)
Kasus penggunaan
- Menampilkan waktu eksekusi batch
- Mencetak hanya bagian waktu dalam log
Jebakan umum
- Karena tidak menyertakan tanggal, Anda tidak dapat menggunakannya untuk perbandingan datetime.
1.4 Dapatkan waktu saat ini dalam UTC (penting)
SELECT UTC_TIMESTAMP();
- Mengembalikan UTC terlepas dari zona waktu server.
- Disarankan untuk layanan global.
Kebijakan dasar dalam proyek nyata
- Simpan dalam UTC
- Konversi ke waktu lokal saat menampilkan
Catatan
- Jika aplikasi sudah mengonversi ke UTC, waspadai konversi ganda.
1.5 Dapatkan milidetik / mikrodetik
SELECT NOW(3); -- milliseconds (3 digits after the decimal point)
SELECT NOW(6); -- microseconds (6 digits after the decimal point)
- Tersedia di MySQL 5.6.4 dan setelahnya.
- Digunakan untuk log berpresisi tinggi dan audit transaksi.
Kesalahpahaman umum
NOW()saja tidak dapat mengembalikan detik pecahan.- Kolom Anda juga harus menentukan presisi, misalnya
DATETIME(6).
1.6 Fungsi terbaik berdasarkan kasus penggunaan (mulai di sini jika tidak yakin)
| Use case | Recommended function |
|---|---|
| General current datetime | NOW() |
| Table default value | CURRENT_TIMESTAMP |
| Date only | CURDATE() |
| Time only | CURTIME() |
| Unified UTC management | UTC_TIMESTAMP() |
| High-precision logs | NOW(6) |
Poin penting yang sering terlewat orang
NOW()danCURRENT_TIMESTAMPpada dasarnya setara (nilai sama)- Dalam satu query yang sama, waktu tetap
- Nilai yang ditampilkan berubah tergantung pada pengaturan zona waktu
- Untuk mikrodetik, definisi kolom Anda harus menentukan presisi
2. Perbedaan antara NOW() / CURRENT_TIMESTAMP / SYSDATE()
Ada beberapa fungsi untuk mendapatkan waktu saat ini, tetapi bagian yang paling membingungkan adalah perbedaan antara NOW(), CURRENT_TIMESTAMP, dan SYSDATE().
Jika Anda tidak memahaminya dengan benar, Anda dapat mengalami perilaku tak terduga dalam log dan pemrosesan transaksi.
2.1 NOW() dan CURRENT_TIMESTAMP pada dasarnya setara
SELECT NOW(), CURRENT_TIMESTAMP;
- Keduanya mengembalikan datetime saat ini (nilai DATETIME).
- Dalam satu query yang sama, waktu tetap pada “waktu mulai query.”
CURRENT_TIMESTAMPjuga dapat digunakan dengan sintaks pemanggilan fungsi:SELECT CURRENT_TIMESTAMP();
Cara memilih dalam proyek nyata
| Use case | Recommended |
|---|---|
| Simple retrieval | NOW() |
| Table DEFAULT / ON UPDATE | CURRENT_TIMESTAMP |
Poin penting
- Makna nilai yang diambil sama.
- Perbedaan utama terletak pada sintaks/penggunaan (misalnya, diperbolehkan di DEFAULT).
- Bukan perbedaan tipe (mudah disalahpahami).
2.2 SYSDATE() mengembalikan waktu pada “waktu evaluasi”
SYSDATE() terlihat mirip dengan NOW(), tetapi waktu ketika nilai tersebut tetap berbeda.
SELECT NOW(), SLEEP(2), NOW();
Result (example):
2025-02-23 14:00:00
2025-02-23 14:00:00
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Result (example):
2025-02-23 14:00:00
2025-02-23 14:00:02
Perbedaan esensial
| Function | When the time is fixed |
|---|---|
NOW() | Query start time |
SYSDATE() | Evaluation time |
2.3 Catatan untuk transaksi dan replikasi
Karena NOW() ditetapkan pada awal kueri, maka
lebih aman ketika Anda membutuhkan waktu referensi yang konsisten di dalam sebuah transaksi.
Di sisi lain, karena SYSDATE() bergantung pada waktu eksekusi, hal ini dapat memengaruhi reproduktifitas dalam:
- Replikasi
- Pekerjaan batch
- Pemrosesan log massal
Aturan praktis
- Ingin waktu referensi tetap →
NOW() - Membutuhkan momen tepat setiap saat →
SYSDATE()(penggunaan terbatas)
2.4 Catatan: CURRENT_DATE / CURRENT_TIME / LOCALTIME
MySQL juga mendukung:
SELECT CURRENT_DATE;
SELECT CURRENT_TIME;
SELECT LOCALTIME;
CURRENT_DATE→ sama denganCURDATE()CURRENT_TIME→ sama denganCURTIME()LOCALTIME→ sama denganNOW()
Kebingungan umum
- Ini kebanyakan “perbedaan kosmetik”; perbedaannya secara fungsional sangat kecil.
- Untuk keamanan, prioritaskan keterbacaan dan standarisasi dalam proyek.
Poin penting dari bagian ini
NOW()danCURRENT_TIMESTAMPpada dasarnya memiliki arti yang sama.SYSDATE()berperilaku berbeda karena didasarkan pada waktu evaluasi.- Untuk waktu referensi tetap, gunakan
NOW()sebagai default. - Gunakan
CURRENT_TIMESTAMPuntuk DEFAULT dan ON UPDATE.
3. Ubah format tampilan tanggal/waktu saat ini
Waktu saat ini yang Anda dapatkan dengan NOW() secara default ditampilkan sebagai YYYY-MM-DD HH:MM:SS. Dalam pekerjaan nyata, Anda sering membutuhkan hal-hal seperti:
- Tampilkan hanya tanggal
- Gunakan
YYYY/MM/DD - Gunakan format lokal (mis., 23 Feb 2025)
- Tampilkan milidetik
Untuk ini, gunakan DATE_FORMAT() (mengonversi datetime ke format string arbitrer).
3.1 Sintaks dasar DATE_FORMAT()
DATE_FORMAT(datetime, 'format_string')
Contoh: Mengonversi waktu saat ini ke YYYY/MM/DD HH:MM
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');
Contoh output:
2025/02/23 14:35
Spesifikator format umum
| Specifier | Meaning | Example |
|---|---|---|
%Y | 4-digit year | 2025 |
%m | 2-digit month | 02 |
%d | 2-digit day | 23 |
%H | Hour (24-hour) | 14 |
%i | Minutes | 35 |
%s | Seconds | 50 |
%f | Microseconds | 123456 |
Catatan
- Beberapa spesifikator berbeda antara huruf besar/kecil.
%hadalah waktu 12 jam,%Hadalah waktu 24 jam.
3.2 Contoh format umum (sering dalam pekerjaan nyata)
1. Dipisahkan dengan garis miring
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d');
2. Lokal (Inggris)
SELECT DATE_FORMAT(NOW(), '%b %d, %Y');
3. Tanpa detik
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i');
Jebakan umum
- Karena mengembalikan string, Anda tidak dapat menggunakannya untuk perhitungan numerik.
- Untuk perbandingan dan pencarian, Anda sebaiknya menggunakan tipe DATETIME asli.
3.3 Ekstrak hanya bagian tanggal atau waktu
Anda juga dapat mengambil bagian sambil mempertahankan tipe (alih-alih memformat menjadi string).
SELECT DATE(NOW()); -- date only (DATE type)
SELECT TIME(NOW()); -- time only (TIME type)
SELECT YEAR(NOW()); -- year only
SELECT MONTH(NOW()); -- month only
SELECT DAY(NOW()); -- day only
Penggunaan yang direkomendasikan
| Goal | Recommended |
|---|---|
| Formatting for display | DATE_FORMAT |
| Calculation / comparison | DATE() / TIME() |
3.4 Tampilkan dengan mikrodetik
Saat Anda membutuhkan log dengan presisi tinggi:
SELECT NOW(6);
Dengan pemformatan:
SELECT DATE_FORMAT(NOW(6), '%Y-%m-%d %H:%i:%s.%f');
Catatan penting
- Kolom Anda harus
DATETIME(6)atauTIMESTAMP(6), jika tidak presisi tidak akan disimpan. - Tidak tersedia pada versi MySQL yang lebih lama dari 5.6.4 (tergantung lingkungan).
Kesalahan umum
Menggunakan
DATE_FORMAT()dalam klausa WHERE mencegah penggunaan indeks. wp:list /wp:list- Contoh buruk:
WHERE DATE_FORMAT(created_at, '%Y-%m-%d') = '2025-02-23' - Disarankan:
WHERE created_at >= '2025-02-23 00:00:00' AND created_at < '2025-02-24 00:00:00' - Menyimpan string yang diformat untuk tampilan secara langsung (merusak kinerja pencarian)
- Contoh buruk:
Poin penting dari bagian ini
- Gunakan
DATE_FORMAT()untuk mengubah format tampilan. - Untuk perhitungan/perbandingan, pertahankan tipe asli.
- Jika Anda membutuhkan mikrodetik, tentukan presisi dalam definisi kolom.
- Menggunakan fungsi dalam klausa WHERE dapat menyebabkan masalah kinerja.
4. Perhitungan datetime menggunakan waktu saat ini
Di MySQL, biasanya menghitung hal seperti “N jam kemudian,” “N hari yang lalu,” atau “N hari terakhir” berdasarkan waktu saat ini.
Kasus dunia nyata yang paling umum adalah “mengambil data dari 24 jam terakhir.”
Dasar aritmatika datetime adalah INTERVAL (sintaks untuk menambah/mengurangi satuan waktu).
4.1 Tambah/kurangi dengan INTERVAL
Dapatkan 1 jam kemudian
SELECT NOW() + INTERVAL 1 HOUR;
Dapatkan 3 hari yang lalu
SELECT NOW() - INTERVAL 3 DAY;
Dapatkan 1 bulan kemudian
SELECT NOW() + INTERVAL 1 MONTH;
Satuan umum
| Unit | Meaning |
|---|---|
| SECOND | Seconds |
| MINUTE | Minutes |
| HOUR | Hours |
| DAY | Days |
| WEEK | Weeks |
| MONTH | Months |
| YEAR | Years |
Kesalahan umum
DAYdalamINTERVAL 1 DAYberfungsi meskipun huruf kecil, tetapi Anda sebaiknya menstandarkan dalam tim.- Perhitungan akhir bulan dapat berbeda dari harapan karena jumlah hari bervariasi (mis., 31 Jan + 1 bulan).
4.2 Mengambil data dari 24 jam terakhir (pola paling umum)
SELECT *
FROM users
WHERE created_at >= NOW() - INTERVAL 1 DAY;
Makna
- Menargetkan “dari sekarang kembali hingga 24 jam yang lalu.”
Catatan
- Jika Anda menggunakan
CURDATE(), baseline menjadi “hari ini pada 00:00,” yang mengubah maknanya.
Contoh (data hari ini):
SELECT *
FROM users
WHERE created_at >= CURDATE();
Memahami perbedaan sangat penting
| Expression | Meaning |
|---|---|
NOW() - INTERVAL 1 DAY | Past 24 hours |
CURDATE() | Since today 00:00 |
4.3 Mendapatkan selisih hari dengan DATEDIFF()
SELECT DATEDIFF('2025-03-01', '2025-02-23');
Hasil:
6
- Satuannya “hari”
- Bagian waktu diabaikan
Catatan
- Tanda berubah tergantung pada urutan argumen.
- Anda tidak dapat menghitung selisih dalam jam/menit/detik.
4.4 Gunakan TIMESTAMPDIFF() untuk jam/menit/detik
SELECT TIMESTAMPDIFF(HOUR,
'2025-02-23 12:00:00',
'2025-02-23 18:30:00');
Hasil:
6
Menit
SELECT TIMESTAMPDIFF(MINUTE,
'2025-02-23 12:00:00',
'2025-02-23 12:30:00');
Detik
SELECT TIMESTAMPDIFF(SECOND,
'2025-02-23 12:00:00',
'2025-02-23 12:00:45');
Kasus penggunaan
- Perhitungan durasi sesi
- Pemeriksaan kedaluwarsa
- Keputusan timeout
4.5 Mendapatkan awal bulan / akhir bulan (perangkap umum di dunia nyata)
Dapatkan hari pertama bulan ini:
SELECT DATE_FORMAT(NOW(), '%Y-%m-01');
Hari pertama bulan berikutnya:
SELECT DATE_FORMAT(NOW() + INTERVAL 1 MONTH, '%Y-%m-01');
Catatan
- Akhir bulan bukan tanggal tetap.
- Untuk kueri rentang, “>= start AND < hari pertama bulan berikutnya” aman.
Ringkasan kesalahan umum
- Menggunakan
BETWEENdengan nilai hanya tanggal dan melupakan waktu - Menonaktifkan indeks dengan menggunakan
DATE(created_at)dalam klausa WHERE - Terjebak oleh masalah “hari ke-31” dalam perhitungan bulan
- Salah paham perbedaan antara
NOW()danCURDATE()
Poin penting dari bagian ini
INTERVALadalah dasar aritmatika datetime.- 24 jam terakhir =
NOW() - INTERVAL 1 DAY. - Hari =
DATEDIFF(); satuan lebih kecil =TIMESTAMPDIFF(). - Hati-hati dengan kondisi akhir untuk perhitungan berbasis bulan.
5. Untuk kueri rentang, ini lebih aman daripada BETWEEN
Saat melakukan pencarian rentang tanggal di MySQL, banyak pemula menggunakan BETWEEN. Namun, sering menghasilkan hasil yang tidak diinginkan jika Anda salah menangani batas waktu, sehingga pola yang lebih aman direkomendasikan dalam pekerjaan nyata.
5.1 Dasar-dasar BETWEEN dan jebakan
Kuery umum
SELECT *
FROM orders
WHERE order_date BETWEEN '2025-02-01' AND '2025-02-10';
Terlihat baik, tetapi secara internal setara dengan:
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date <= '2025-02-10 00:00:00'
Jadi tidak termasuk data setelah 00:00 pada 10 Feb.
5.2 Pola yang lebih aman (direkomendasikan)
Pola yang direkomendasikan
SELECT *
FROM orders
WHERE order_date >= '2025-02-01 00:00:00'
AND order_date < '2025-02-11 00:00:00';
Poin penting
- Tentukan batas akhir sebagai “kurang dari hari berikutnya pada 00:00”
- Lebih aman daripada
<= 23:59:59(mendukung mikrodetik)
5.3 Cara yang benar untuk mendapatkan data hari ini
Contoh buruk:
WHERE DATE(created_at) = CURDATE();
Masalah:
- Menerapkan fungsi pada kolom menonaktifkan indeks
- Dapat menyebabkan perlambatan serius pada tabel besar
Direkomendasikan:
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
Ini memastikan:
- Indeks dapat digunakan
- Pencarian cepat
- Tidak ada masalah batas
5.4 Pola aman untuk 7 hari terakhir / 30 hari terakhir
7 hari terakhir
WHERE created_at >= NOW() - INTERVAL 7 DAY;
30 hari terakhir
WHERE created_at >= NOW() - INTERVAL 30 DAY;
Catatan
CURDATE() - INTERVAL 7 DAYdidasarkan pada “hari ini 00:00”NOW() - INTERVAL 7 DAYdidasarkan pada “waktu saat ini”- Pilih berdasarkan kebutuhan
5.5 Aturan kunci untuk menjaga indeks tetap efektif
Buruk:
WHERE DATE(created_at) = '2025-02-23';
Baik:
WHERE created_at >= '2025-02-23 00:00:00'
AND created_at < '2025-02-24 00:00:00';
Mengapa:
- Indeks bekerja pada “kolom itu sendiri”
- Menerapkan fungsi mencegah penggunaan indeks (pemindaian penuh)
Ringkasan kesalahan umum
- Lupa menyertakan waktu pada batas akhir dalam
BETWEEN - Kehilangan mikrodetik saat menggunakan
23:59:59 - Menggunakan
DATE()dalam klausa WHERE dan memperlambat query - Meninggalkan “now” vs “today 00:00” ambigu
Poin penting dari bagian ini
- Query rentang paling aman dengan
>= start AND < end. BETWEENmemerlukan penanganan batas yang hati-hati.- Untuk menjaga indeks tetap efektif, jangan membungkus kolom dengan fungsi.
- Pilih dengan jelas antara logika berbasis
NOW()dan berbasisCURDATE().
6. DEFAULT CURRENT_TIMESTAMP dan ON UPDATE (dasar desain tabel)
Dalam desain basis data, biasanya mengelola created_at dan updated_at secara otomatis.
Di MySQL, CURRENT_TIMESTAMP memungkinkan Anda menetapkan waktu saat ini secara otomatis pada saat insert dan update.
6.1 Menetapkan otomatis created_at (DEFAULT CURRENT_TIMESTAMP)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Perilaku:
INSERT INTO users (name) VALUES ('Alice');
→ Waktu saat ini secara otomatis dimasukkan ke dalam created_at.
Poin penting
CURRENT_TIMESTAMPdapat digunakan dalam DEFAULT.NOW()tidak dapat digunakan langsung dalam DEFAULT.
Kesalahan umum
created_at DATETIME DEFAULT NOW(); -- error
Alasan:
- Di MySQL, biasanya Anda tidak dapat menetapkan fungsi sebagai DEFAULT (kecuali CURRENT_TIMESTAMP).
6.2 Pembaruan otomatis updated_at (ON UPDATE)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Perilaku:
UPDATE users SET name = 'Bob' WHERE id = 1;
→ updated_at secara otomatis diperbarui ke waktu saat ini.
Kasus penggunaan
- Pelacakan login terakhir
- Riwayat pembaruan
- Log audit
6.3 DATETIME vs TIMESTAMP (penting)
| Type | Range | Time zone impact |
|---|---|---|
| DATETIME | Year 1000 to 9999 | No |
| TIMESTAMP | 1970 to 2038 | Yes |
Perbedaan penting
TIMESTAMPdisimpan secara internal dalam UTC dan dikonversi ke zona waktu sesi saat ditampilkan.DATETIMEmenyimpan nilai literal (tanpa konversi).
Pedoman
| Case | Recommended type |
|---|---|
| Log management | TIMESTAMP |
| Future dates (after 2038) | DATETIME |
| Fixed values not requiring TZ conversion | DATETIME |
6.4 CURRENT_TIMESTAMP juga dapat digunakan dengan DATETIME
Di MySQL 5.6 dan versi lebih baru, Anda dapat menentukan CURRENT_TIMESTAMP sebagai DEFAULT dan ON UPDATE untuk kolom DATETIME juga.
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
Catatan
- Versi MySQL yang lebih lama memiliki pembatasan (tergantung lingkungan).
- Jika Anda memerlukan presisi:
DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6)
6.5 Jika Anda ingin menggunakan NOW(): alternatif (trigger)
CREATE TRIGGER set_created_at
BEFORE INSERT ON logs
FOR EACH ROW
SET NEW.created_at = NOW();
Kasus penggunaan
- Logika nilai awal yang kompleks
- Penetapan cap waktu bersyarat
Catatan
- Trigger sulit untuk di‑debug.
- Hindari kecuali memang diperlukan.
Kesalahan desain umum
- Menambahkan
ON UPDATEpadacreated_atdanupdated_atsekaligus - Membingungkan perilaku
DATETIMEdanTIMESTAMP - Menunda keputusan zona waktu
Hal penting yang harus diingat dari bagian ini
- Gunakan
CURRENT_TIMESTAMPuntukDEFAULT. - Gunakan
ON UPDATE CURRENT_TIMESTAMPuntuk pelacakan pembaruan. - Pilih tipe berdasarkan perilaku zona waktu dan masalah tahun 2038.
- Jika Anda memerlukan presisi, jangan lupa
(6).
7. Desain zona waktu (simpan dalam UTC, tampilkan dalam waktu lokal)
Saat menangani waktu saat ini, desain zona waktu yang buruk menyebabkan drift waktu dan konversi ganda.
Dalam praktiknya, default yang paling aman adalah “simpan dalam UTC, konversi ke waktu lokal untuk tampilan.”

Figure: Arsitektur dasar untuk menyimpan UTC di MySQL dan menampilkan waktu lokal
7.1 Periksa zona waktu saat ini
Pertama, periksa zona waktu mana yang sedang dijalankan MySQL.
SELECT @@global.time_zone, @@session.time_zone;
@@global.time_zone→ pengaturan untuk seluruh server@@session.time_zone→ pengaturan koneksi/sesi saat ini- Jika menampilkan
SYSTEM, maka bergantung pada pengaturan OS
Masalah umum
- Server produksi dan pengembangan memiliki zona waktu OS yang berbeda
- Aplikasi mengonversi ke UTC, lalu DB mengonversi lagi (konversi ganda)
7.2 Ubah zona waktu per sesi
SET time_zone = 'Asia/Tokyo';
atau seragamkan ke UTC:
SET time_zone = '+00:00';
Poin penting
- Akan kembali ke semula ketika koneksi ditutup
- Jika Anda menggunakan connection pooling, periksa pengaturan aplikasi Anda
7.3 Mengapa menyimpan dalam UTC (prinsip dunia nyata)
Kebijakan yang direkomendasikan
- Simpan data dalam UTC
- Konversi ke zona waktu pengguna saat menampilkan
Alasan:
- Dukungan internasional yang lebih mudah
- Menghindari masalah daylight saving time (DST)
- Meminimalkan dampak saat memindahkan server
Dapatkan UTC:
SELECT UTC_TIMESTAMP();
7.4 Konversi zona waktu dengan CONVERT_TZ()
Contoh: UTC → JST
SELECT CONVERT_TZ('2025-02-23 05:35:00', '+00:00', '+09:00');
Menggunakan nama zona waktu:
SELECT CONVERT_TZ('2025-02-23 05:35:00', 'UTC', 'Asia/Tokyo');
Contoh dunia nyata
SELECT CONVERT_TZ(created_at, 'UTC', 'Asia/Tokyo')
FROM users;
7.5 Mengapa CONVERT_TZ() mengembalikan NULL
Jika mengembalikan NULL, penyebab umum meliputi:
- Tabel zona waktu MySQL belum dimuat
- Nama zona waktu yang diberikan tidak ada
Contoh pemuatan di Linux:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Catatan
- Di produksi, pastikan izin dan apakah restart diperlukan
- Di Docker, zoneinfo mungkin tidak termasuk tergantung pada image
7.6 Ubah zona waktu seluruh server
File konfigurasi (my.cnf / my.ini):
[mysqld]
default_time_zone = '+00:00'
Verifikasi setelah restart:
SELECT @@global.time_zone;
Penting
- Untuk perubahan produksi, pastikan ruang lingkup dampaknya
- Hati‑hati dengan data yang sudah ada (kadang hanya perubahan tampilan)
Kesalahan umum
- Menyimpan waktu lokal alih‑alih UTC, lalu menambahkan dukungan internasional belakangan
- Konversi ganda antara aplikasi dan DB
- Mendesain dengan
DATETIMEtanpa mempertimbangkan zona waktu - Pengaturan TZ yang berbeda antara pengujian dan produksi
Hal penting yang harus diingat dari bagian ini
- Simpan dalam UTC dan konversi saat menampilkan.
- Gunakan
UTC_TIMESTAMP(). - Saat menggunakan
CONVERT_TZ(), verifikasi tabel TZ. - Selalu perhitungkan perbedaan lingkungan pada zona waktu.
8. Contoh praktis yang dapat langsung Anda gunakan
Berikut contoh SQL konkret yang menunjukkan cara menggunakan waktu saat ini MySQL dalam pengembangan/operasi nyata.
Ditulis agar Anda dapat menyalin dan menempelkannya langsung.
8.1 Secara otomatis menyisipkan waktu saat ini ke dalam log
Buat tabel
CREATE TABLE system_logs (
id INT AUTO_INCREMENT PRIMARY KEY,
level VARCHAR(50),
message TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Memasukkan log
INSERT INTO system_logs (level, message)
VALUES ('ERROR', 'Failed to connect to the DB');
Poin kunci
created_atdimasukkan secara otomatis- Tidak perlu mengirim timestamp dari aplikasi
- Desain esensial untuk audit dan investigasi insiden
Kesalahan umum
- Mengelola waktu di aplikasi dan DB
- Ketidakkonsistenan waktu karena zona waktu yang tidak seragam
8.2 Memperbarui waktu login terakhir
Desain tabel
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255),
last_login TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
);
Pembaruan saat login
UPDATE users
SET last_login = NOW()
WHERE id = 1;
Catatan
ON UPDATEhanya dipicu ketika kolom berubah- Beberapa pernyataan UPDATE mungkin tidak mengubah nilai dan sehingga tidak memperbarui
8.3 Memperbaiki waktu referensi dalam pekerjaan batch
Untuk proses yang berjalan lama, lebih aman untuk memperbaiki waktu referensi.
SET @base_time = NOW();
SELECT *
FROM orders
WHERE created_at >= @base_time - INTERVAL 1 DAY;
Mengapa
- Waktu tidak bergeser di tengah proses
- Konsistensi tetap terjaga
8.4 Agregasi untuk hari ini / kemarin / 7 hari terakhir
Penjualan hari ini
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE()
AND created_at < CURDATE() + INTERVAL 1 DAY;
Penjualan kemarin
SELECT SUM(amount)
FROM orders
WHERE created_at >= CURDATE() - INTERVAL 1 DAY
AND created_at < CURDATE();
7 hari terakhir
SELECT COUNT(*)
FROM users
WHERE created_at >= NOW() - INTERVAL 7 DAY;
Penting
- Jangan terapkan fungsi pada kolom dalam klausa WHERE
- Tulis kondisi yang menjaga indeks tetap dapat digunakan
8.5 Pemeriksaan kedaluwarsa (sesi/token)
SELECT *
FROM sessions
WHERE expires_at > NOW();
Hapus baris yang kedaluwarsa
DELETE FROM sessions
WHERE expires_at <= NOW();
Kesalahan umum
- Menggunakan
CURDATE()dan mengabaikan waktu - Menyimpan UTC tetapi membandingkan dengan
NOW()lokal
8.6 Mendapatkan baris yang kedaluwarsa dalam N jam
SELECT *
FROM coupons
WHERE expires_at <= NOW() + INTERVAL 1 HOUR;
Kasus penggunaan:
- Peringatan kedaluwarsa
- Notifikasi kedaluwarsa
Apa yang harus selalu Anda ingat
- Jadilah eksplisit apakah baseline Anda adalah “sekarang” atau “hari ini 00:00”
- Tulis predikat yang menjaga indeks efektif
- Putuskan desain zona waktu di awal
- Jangan campur
NOW()danUTC_TIMESTAMP()tanpa kebijakan yang jelas
Poin utama dari bagian ini
- Untuk log/audit/pelacakan pembaruan, gunakan
CURRENT_TIMESTAMP - Untuk agregasi, gunakan pola aman
>= DAN < - Untuk manajemen sesi, bandingkan dengan
NOW() - Perbaiki waktu baseline untuk menjaga pemrosesan tetap konsisten
9. Pertanyaan yang Sering Diajukan (FAQ)
Berikut adalah pertanyaan umum tentang waktu saat ini di MySQL, terutama jebakan yang muncul dalam pekerjaan nyata.
9.1 Apa perbedaan antara NOW() dan CURRENT_TIMESTAMP?
Kesimpulan: arti nilai yang dikembalikan sama.
SELECT NOW(), CURRENT_TIMESTAMP;
Keduanya mengembalikan datetime saat ini.
Perbedaan utama adalah penggunaan sintaksis
CURRENT_TIMESTAMPdapat digunakan dalamDEFAULTdanON UPDATENOW()tidak dapat digunakan langsung dalam DEFAULT
Catatan
- Ini bukan perbedaan tipe
- Anda dapat menentukan presisi dengan argumen seperti
(6)
9.2 Haruskah Anda menggunakan SYSDATE()?
SYSDATE() mengembalikan waktu pada “waktu evaluasi.”
SELECT SYSDATE(), SLEEP(2), SYSDATE();
Nilai dapat berubah bahkan dalam query yang sama.
Kapan menggunakannya
- Ketika Anda perlu mencatat instan waktu nyata yang tepat
Kapan menghindarinya
- Replikasi
- Pemrosesan transaksi di mana konsistensi penting
Dalam kebanyakan kasus, menggunakan NOW() sudah cukup.
9.3 Mengapa waktu bergeser?
Penyebab utama:
- Pengaturan zona waktu server
- Pengaturan zona waktu sesi
- Konversi ganda dengan aplikasi
- Perilaku konversi otomatis tipe TIMESTAMP
Periksa dengan:
SELECT @@global.time_zone, @@session.time_zone;
Mitigasi
- Simpan dalam UTC secara default
- Konversi hanya saat menampilkan
- Samakan kebijakan antara aplikasi dan DB
9.4 CONVERT_TZ() returns NULL
Penyebab:
- Tabel zona waktu tidak dimuat
- Nama zona waktu tidak tepat
Perbaikan:
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Berhati-hatilah terutama di lingkungan Docker.
9.5 Range shifts with BETWEEN
Buruk:
WHERE created_at BETWEEN '2025-02-01' AND '2025-02-10';
Aman:
WHERE created_at >= '2025-02-01 00:00:00'
AND created_at < '2025-02-11 00:00:00';
Alasan:
- Masalah waktu batas akhir
- Kebocoran mikrodetik
- Efisiensi indeks
9.6 Bagaimana Anda memilih antara DATETIME dan TIMESTAMP?
- Dukungan internasional / manajemen UTC → TIMESTAMP
- Setelah 2038 atau datetime tetap → DATETIME
Putuskan ini saat perancangan.
9.7 Mikrodetik tidak disimpan
Penyebab:
- Tidak ada presisi yang ditentukan dalam definisi kolom
Perbaikan:
created_at DATETIME(6)
Poin penting dari bagian ini
- Mulai dengan
NOW()danCURRENT_TIMESTAMP - Untuk kueri rentang, gunakan
>= AND < - Penyimpanan UTC adalah default paling aman
- Jangan lupa pemilihan tipe dan presisi
10. Ringkasan
Artikel ini menyusun cara praktis untuk mengambil, memformat, menghitung, dan mengelola waktu saat ini di MySQL.
Akhirnya, berikut esensial minimum yang harus Anda ketahui untuk tetap aman.
10.1 Mendapatkan waktu saat ini (dasar)
- Pengambilan umum →
NOW() - DEFAULT tabel / pelacakan pembaruan →
CURRENT_TIMESTAMP - Hanya tanggal →
CURDATE() - Hanya waktu →
CURTIME() - UTC →
UTC_TIMESTAMP() - Presisi tinggi →
NOW(6)
Aturan praktis
- Jika ragu, menggunakan
NOW()baik dalam kebanyakan kasus. - Untuk desain skema, gunakan
CURRENT_TIMESTAMP.
10.2 Kueri rentang: “>= AND <” adalah aturan emas
Pola aman:
WHERE created_at >= 'START'
AND created_at < 'END'
Mengapa:
- Mencegah baris yang hilang pada batas akhir
- Bekerja dengan mikrodetik
- Menjaga indeks tetap dapat digunakan
Contoh buruk
WHERE DATE(created_at) = CURDATE();
Jangan membungkus kolom dengan fungsi.
10.3 Dasar aritmetika datetime
- Tambah/kurangi →
INTERVAL - Selisih hari →
DATEDIFF() - Selisih waktu →
TIMESTAMPDIFF()
Selalu ingat apakah dasar Anda adalah “now” atau “today 00:00.”
10.4 Prinsip desain zona waktu
- Simpan dalam UTC
- Konversi saat ditampilkan
- Samakan kebijakan antara aplikasi dan DB
Periksa dengan:
SELECT @@global.time_zone, @@session.time_zone;
10.5 Praktik terbaik desain tabel
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
ON UPDATE CURRENT_TIMESTAMP
- Peralatan standar untuk audit/pencatatan/pelacakan pembaruan
- Jika Anda membutuhkan presisi, tentukan
(6)
4 poin paling penting dalam dunia nyata
- Jangan salah mengartikan perbedaan antara
NOW()danCURRENT_TIMESTAMP - Untuk kueri rentang, gunakan
>= AND < - Simpan dalam UTC secara default
- Tentukan tipe (DATETIME vs TIMESTAMP) saat perancangan
Penanganan waktu saat ini di MySQL merupakan dasar untuk pencatatan, agregasi penjualan, manajemen otentikasi/sesi, pekerjaan batch, dan lainnya.
Jika Anda mengikuti prinsip-prinsip dalam artikel ini, Anda dapat menghindari banyak masalah umum seperti pergeseran waktu, bug batas, dan penurunan kinerja.


