Menangani Timezone pada Data Waktu di SQL
Blog/Tutorial SQL/Menangani Timezone pada Data Waktu di SQL

Menangani Timezone pada Data Waktu di SQL

BimaBima
·2 September 2026·9 menit baca

Penulis

Bima

Bima

Founder & Data Professional

Bagikan

TL;DR

Menangani timezone di SQL intinya nyimpan waktu dalam UTC pakai tipe timestamptz, lalu konversi ke zona lokal cuma pas nampilin. Di PostgreSQL, konversi pakai AT TIME ZONE, misalnya kolom AT TIME ZONE 'Asia/Jakarta' buat ngubah UTC ke WIB. Tipe timestamp tanpa zona nggak nyimpan info timezone, jadi rawan salah tafsir. Aturan amannya: simpan UTC, tampilkan lokal.

Menangani timezone di SQL paling aman dengan satu aturan: simpan waktu dalam UTC, konversi ke zona lokal cuma pas nampilin. Ini ngindarin data yang geser tanggal.

Masalahnya nyata. Aplikasi nyimpen transaksi dalam UTC, tapi bos minta laporan jam WIB. Kalau konversinya salah, penjualan jam 11 malam bisa kecatat di tanggal besoknya.

Kamu bakal lihat beda tipe timestamp, cara konversi pakai AT TIME ZONE, plus jebakan laporan harian yang bikin angka meleset.

Apa itu timezone di data waktu SQL?

Timezone adalah info zona waktu yang nempel di sebuah timestamp, yang nentuin waktu itu dibaca sebagai jam berapa di lokasi mana. Jam 10 pagi di Jakarta beda dengan jam 10 pagi di London. Tanpa info zona, satu timestamp bisa ditafsir beda-beda. UTC adalah patokan waktu global yang dipakai buat nyimpan waktu secara netral, dan WIB itu UTC ditambah 7 jam.

Kunci masalahnya, database perlu tau apakah sebuah waktu udah termasuk zona atau belum. Ini yang bedain dua tipe kolom waktu.

Apa beda timestamp dan timestamptz?

Di PostgreSQL, ada dua tipe. timestamp nyimpan tanggal dan jam tanpa info zona, jadi angkanya polos. timestamptz (timestamp with time zone) nyimpan waktu yang sadar zona, dan internalnya selalu disimpan dalam UTC. Waktu kamu masukin data, timestamptz otomatis nyesuain ke UTC berdasarkan zona sesi.

TipeSimpan zona?Cocok buat
timestampNggakWaktu lokal tetap, kayak jadwal buka toko
timestamptzYa (internal UTC)Transaksi, log, event lintas kota

Buat data transaksi yang bisa datang dari mana aja, hampir selalu pakai timestamptz. Buat waktu yang memang lokal dan tetap, kayak jam operasional, timestamp polos cukup. Buat dasar tipe tanggal, cek fungsi EXTRACT di SQL.

Gimana cara konversi UTC ke WIB di PostgreSQL?

Pakai operator AT TIME ZONE dengan nama zona. Buat WIB, nama zonanya 'Asia/Jakarta'. Operator ini ngubah timestamptz yang tersimpan UTC jadi waktu lokal Jakarta. Hasilnya timestamp polos yang udah digeser 7 jam.

SELECT
    id_transaksi,
    waktu_bayar,
    waktu_bayar AT TIME ZONE 'Asia/Jakarta' AS waktu_wib
FROM transaksi;

Kalau waktu_bayar nyimpan 2026-09-01 22:00 UTC, hasil waktu_wib jadi 2026-09-02 05:00. Udah bener, geser 7 jam maju.

Pakai nama zona 'Asia/Jakarta', jangan angka '+07'. Nama zona ngerti aturan khusus tiap wilayah, sedangkan angka offset kaku. Buat Indonesia bagian tengah pakai 'Asia/Makassar', dan timur pakai 'Asia/Jayapura'.

Gimana cara bikin laporan harian jam lokal?

Ini bagian yang sering salah. Buat ngelompokkan transaksi per hari WIB, konversi dulu ke zona Jakarta, baru ambil tanggalnya. Kalau kamu grup langsung dari UTC, batas harinya jam 7 pagi WIB, bukan tengah malam.

SELECT
    (waktu_bayar AT TIME ZONE 'Asia/Jakarta')::date AS tanggal_wib,
    COUNT(*) AS jumlah_transaksi,
    SUM(nominal) AS total
FROM transaksi
GROUP BY tanggal_wib
ORDER BY tanggal_wib;

Urutannya penting: konversi zona dulu, baru cast ke date. Kalau kebalik, tanggalnya diambil dari UTC dan hasilnya geser. Buat teknik ngelompokkan waktu lanjutan, ada bahasan fungsi DATE_TRUNC di SQL.

Contoh kasus: laporan penjualan malam toko_berkah

Toko_berkah punya toko online yang aktif sampai larut. Server nyimpen 18.400 transaksi dalam UTC. Pemiliknya bingung: laporan penjualan harian dari tim dev angkanya beda dengan feeling dia soal penjualan malam. Ternyata laporan lama ngelompokkan pakai UTC.

Setelah konversi ke WIB dulu baru dikelompokkan, angkanya berubah. Transaksi antara jam 5 sore sampai tengah malam WIB ternyata 41% dari total harian, jauh lebih gede dari laporan lama yang cuma nunjukin 28%. Selisihnya gara-gara transaksi malam UTC kelempar ke tanggal berikutnya.

SELECT
    EXTRACT(HOUR FROM waktu_bayar AT TIME ZONE 'Asia/Jakarta') AS jam_wib,
    COUNT(*) AS jumlah
FROM transaksi
GROUP BY jam_wib
ORDER BY jam_wib;

Query ini ngasih sebaran transaksi per jam WIB. Puncaknya ketemu jam 8 malam. Temuan ini bikin pemiliknya majuin jadwal promo flash sale dari jam 3 sore ke jam 7 malam, ngikutin jam ramai asli.

Kesalahan umum saat handle timezone

Jebakan pertama: nyimpan waktu lokal di kolom timestamp polos. Begitu server pindah zona atau data digabung dari kota lain, kamu nggak bisa tau lagi waktu itu zona apa. Simpan UTC pakai timestamptz dari awal.

Jebakan kedua: grouping harian langsung dari UTC. Ini yang bikin laporan geser kayak kasus toko_berkah. Selalu konversi ke zona lokal sebelum ambil tanggal.

Jebakan ketiga: pakai offset angka, bukan nama zona. Angka +07 kelihatan gampang, tapi nggak ngerti perubahan aturan waktu di masa lalu. Nama zona kayak 'Asia/Jakarta' selalu benar. Detail soal ini ada di dokumentasi tipe tanggal PostgreSQL.

Jebakan keempat: nyampur timestamp dan timestamptz di satu query. Bandingin dua tipe ini bikin PostgreSQL nebak zona, dan tebakannya belum tentu yang kamu mau. Samain tipe kolomnya dulu.

FAQ

Kenapa harus simpan waktu dalam UTC?

Karena UTC itu patokan netral yang nggak berubah tergantung lokasi server atau pengguna. Kalau kamu simpan waktu lokal, data dari kota berbeda jadi susah dibandingin dan rawan salah tafsir pas server pindah. Dengan nyimpan UTC lalu konversi ke zona lokal cuma pas nampilin, kamu punya satu sumber waktu yang konsisten buat semua laporan.

Kapan pakai timestamp, kapan timestamptz?

Pakai timestamptz buat waktu kejadian nyata kayak transaksi, log, atau event yang bisa datang dari zona berbeda, karena tipe ini nyimpan info zona secara internal. Pakai timestamp polos buat waktu lokal yang memang tetap dan nggak tergantung lokasi, misalnya jam buka toko atau jadwal harian. Buat kebanyakan data bisnis, timestamptz lebih aman.

Kenapa laporan harian saya geser satu hari?

Biasanya karena kamu ngelompokkan transaksi berdasarkan tanggal UTC, bukan tanggal lokal. Transaksi jam 9 malam WIB tercatat jam 2 siang UTC di hari yang sama, tapi transaksi jam 11 malam WIB tercatat jam 4 sore UTC. Masalah muncul di sekitar tengah malam. Solusinya, konversi ke zona lokal dulu pakai AT TIME ZONE, baru ambil tanggalnya.

Apa nama zona waktu buat WIB, WITA, dan WIT?

Buat WIB pakai 'Asia/Jakarta', buat WITA pakai 'Asia/Makassar', dan buat WIT pakai 'Asia/Jayapura'. Nama-nama ini bagian dari database zona waktu standar yang dipakai PostgreSQL. Lebih aman pakai nama wilayah ini dibanding angka offset seperti +07, karena nama zona ngerti aturan waktu tiap daerah dengan benar.

Gimana cara ubah zona sesi di PostgreSQL?

Pakai perintah SET TIME ZONE 'Asia/Jakarta' di awal sesi, dan semua tampilan timestamptz bakal otomatis dikonversi ke zona itu. Ini berguna kalau kamu mau semua query di satu sesi nampil dalam WIB tanpa nulis AT TIME ZONE berulang. Tapi buat laporan yang dipakai banyak orang, mending konversi eksplisit di query biar hasilnya pasti.

Penutup

Aturan emasnya cuma satu: simpan UTC pakai timestamptz, tampilkan lokal pakai AT TIME ZONE. Ingat konversi zona dulu sebelum ambil tanggal, dan selalu pakai nama zona bukan angka offset.

Mau latihan query waktu sampai lancar tanpa takut ngerusak data? Coba di NgulikSQL.

Lanjut baca: fungsi DATE_TRUNC buat ringkas tanggal dan operasi interval dan aritmetika tanggal di SQL.

Coba Langsung

Mau praktek langsung? Mulai latihan SQL gratis

Latihan interaktif, langsung di browser.

Buka NgulikSQL →
Bagikan:
Bima
Ditulis oleh

Bima

Founder & Data Professional

Founder Ngulik Data. Passionate about making data analysis accessible for everyone.

Artikel terkait

Composite Index di SQL: Cara Kerja dan Urutan Kolom
Tutorial SQL
8 Oktober 2026•8 menit baca

Composite Index di SQL: Cara Kerja dan Urutan Kolom

Composite index itu index atas beberapa kolom sekaligus. Urutan kolomnya nentuin query mana yang kebantu, lewat aturan leftmost prefix.

BimaBima
Menghitung Stickiness (DAU/MAU) di SQL
Tutorial SQL
5 Oktober 2026•10 menit baca

Menghitung Stickiness (DAU/MAU) di SQL

Stickiness ngukur seberapa sering user balik lagi. Ini cara hitung DAU, MAU, dan rasio stickiness pakai SQL, plus contoh aplikasi UMKM.

BimaBima
Menghitung DAU dan MAU dengan SQL
Tutorial SQL
3 Oktober 2026•9 menit baca

Menghitung DAU dan MAU dengan SQL

DAU dan MAU dua metrik wajib buat produk digital. Ini cara hitungnya pakai SQL, lengkap query DISTINCT, per bulan, sampai rasio stickiness.

BimaBima
Kembali ke Blog
Ngulik Data logoNgulik Data

Platform edukasi data lengkap untuk professionals Indonesia. Belajar SQL, Data Analysis, dan lebih banyak lagi dengan praktek langsung dan feedback real-time.

© 2026 Ngulik Data. Semua hak dilindungi.

TAUTAN
BantuanHargaDatasetBlogAfiliasi
LEGAL
Syarat & KetentuanKebijakan Privasi
Ngulik Data
DatasetLeaderboardBlogStore