Postgresql Timezone

Mengatasi Masalah Zona Waktu dalam Aplikasi Full-Stack: Strategi UTC yang Konsisten#
Dalam pengembangan aplikasi modern, mengelola data berbasis waktu di berbagai lapisan (frontend, backend, dan database) seringkali menjadi sumber bug yang sulit dideteksi. Perbedaan asumsi zona waktu antar sistem dapat menyebabkan inkonsistensi data, laporan yang tidak akurat, dan pengalaman pengguna yang membingungkan. Artikel ini akan membahas masalah umum ini dan menyajikan strategi yang konsisten menggunakan UTC (Coordinated Universal Time) untuk memastikan integritas data waktu.
Masalah Umum: Inkonsistensi Zona Waktu#
Bayangkan skenario berikut:
- Frontend (Browser): Berjalan di perangkat pengguna, yang mungkin berada di zona waktu
Asia/Jakarta
(UTC+7). - Backend (AWS Lambda di Singapore): Meskipun server fisik di Singapore, lingkungan eksekusi Node.js mungkin secara default menggunakan UTC.
- Database (PostgreSQL di AWS RDS): Server database mungkin dikonfigurasi untuk zona waktu
Asia/Jakarta
atau UTC.
Tanpa strategi yang jelas, ini bisa menjadi kacau:
- Pengguna di Jakarta mencatat aktivitas pada
2025-08-08 01:00 AM
(waktu Jakarta). - Backend menerima ini, tetapi jika tidak hati-hati, bisa menginterpretasikannya sebagai
2025-08-07 06:00 PM UTC
. - Database, jika menggunakan
NOW()
atauCURRENT_DATE
tanpa penyesuaian, akan mencatat waktu berdasarkan zona waktunya sendiri, yang mungkin berbeda dari yang dimaksudkan aplikasi atau pengguna.
Contoh nyata dari proyek kita adalah query
seperti WHERE moved_at::date = CURRENT_DATE
. Jika moved_at
disimpan dalam UTC dan CURRENT_DATE
diinterpretasikan dalam Asia/Jakarta
, sebuah event yang terjadi pada 2025-08-08 01:00 AM
Jakarta (yang sebenarnya 2025-08-07 06:00 PM UTC
) akan salah dikelompokkan ke tanggal 2025-08-07
jika CURRENT_DATE
juga diinterpretasikan dalam UTC, atau ke 2025-08-08
jika CURRENT_DATE
diinterpretasikan dalam Asia/Jakarta
. Ini adalah resep untuk laporan yang tidak akurat.
Solusi Terbaik: Standardisasi pada UTC#
Prinsip dasarnya sederhana: Selalu simpan dan proses semua data waktu di backend dalam format UTC. Konversi ke zona waktu lokal hanya dilakukan di lapisan presentasi (frontend) saat data akan ditampilkan kepada pengguna.
Implementasi Strategi UTC#
Mari kita lihat bagaimana strategi ini diterapkan di setiap lapisan aplikasi kita:
1. Frontend (Client-side)#
- Mengirim Data: Ketika pengguna memasukkan tanggal atau waktu, frontend harus mengonversinya ke string ISO 8601 dalam format UTC sebelum mengirimkannya ke backend.
// Contoh di JavaScript frontend const localDate = new Date(); // Waktu lokal pengguna const utcString = localDate.toISOString(); // Contoh: "2025-08-08T10:00:00.000Z" // Kirim utcString ke backend
- Menampilkan Data: Ketika menerima timestamp dari backend (yang selalu dalam UTC), frontend mengonversinya kembali ke zona waktu lokal pengguna untuk ditampilkan.
// Contoh di JavaScript frontend const utcTimestampFromBackend = "2025-08-08T10:00:00.000Z"; const localDate = new Date(utcTimestampFromBackend); // Otomatis dikonversi ke zona waktu lokal browser console.log(localDate.toLocaleString()); // Contoh: "8/8/2025, 5:00:00 PM" (jika di Jakarta)
2. Backend (Node.js / AWS Lambda)#
- Menerima Data: Asumsikan semua timestamp yang diterima dari frontend sudah dalam format UTC ISO 8601.
- Membuat Timestamp Baru: Saat membuat timestamp baru (misalnya,
moved_at
untuk history bookmark), selalu gunakannew Date().toISOString()
. Ini akan menghasilkan string timestamp dalam UTC.// Contoh di updateBookmarkAndSaveHistory function const historyData = { // ... data lainnya movedAt: new Date().toISOString(), // Selalu UTC }; await saveBookmarkHistoryInDb(pgClient, historyData);
- Mengelola Rentang Tanggal: Ketika menerima
startDate
danfinishDate
(misalnya,YYYY-MM-DD
) dari query parameter, ubah menjadi rentang timestamp UTC yang eksplisit.// Contoh di handler GET /quran/bookmarks/history const { startDate, finishDate } = event.queryStringParameters || {}; // Contoh: "2025-08-08" // Buat rentang UTC: dari awal hari startDate hingga awal hari setelah finishDate const utcStart = new Date(`${startDate}T00:00:00.000Z`); // "2025-08-08T00:00:00.000Z" const utcEnd = new Date(`${finishDate}T00:00:00.000Z`); utcEnd.setDate(utcEnd.getDate() + 1); // "2025-08-09T00:00:00.000Z" // Teruskan ke service function const history = await getHistoryByDateRange(userId, utcStart.toISOString(), utcEnd.toISOString());
3. Database (PostgreSQL dengan TIMESTAMP WITH TIME ZONE
)#
- Penyimpanan: Tipe data
TIMESTAMP WITH TIME ZONE
(atauTIMESTAMPTZ
) di PostgreSQL secara internal selalu menyimpan nilai dalam UTC. Ketika Anda mengirimkan string timestamp dengan informasi zona waktu (sepertiZ
untuk UTC, atau+07:00
), PostgreSQL akan mengonversinya ke UTC sebelum menyimpannya. Jika Anda mengirimkan string UTC, tidak ada konversi yang diperlukan.-- Contoh INSERT di saveBookmarkHistoryInDb INSERT INTO bookmark_history (user_id, bookmark_id, previous_global_ayah_number, new_global_ayah_number, moved_at) VALUES ($1, $2, $3, $4, $5); -- $5 akan berisi string ISO UTC dari backend
- Query Rentang Tanggal: Gunakan perbandingan
timestamp
langsung (>=
dan<
) dengan nilai UTC yang disediakan oleh backend. HindariCAST
kedate
atauCURRENT_DATE
jika Anda ingin presisi lintas zona waktu.Ini memastikan bahwa Anda selalu memfilter berdasarkan titik waktu yang sama di seluruh dunia, terlepas dari zona waktu server database.-- Contoh SELECT di getBookmarkHistoryByDateRangeFromDb SELECT ... FROM bookmark_history WHERE user_id = $1 AND moved_at >= $2 AND moved_at < $3; -- $2 dan $3 adalah string ISO UTC
Manfaat Pendekatan Ini#
- Integritas Data: Data waktu Anda konsisten dan tidak ambigu, terlepas dari lokasi geografis pengguna, server, atau database.
- Debugging Lebih Mudah: Ketika semua timestamp dalam UTC, melacak event di log atau database menjadi jauh lebih mudah.
- Skalabilitas Global: Aplikasi Anda siap untuk melayani pengguna di berbagai zona waktu tanpa perlu perubahan kode yang signifikan.
- Fleksibilitas Tampilan: Pengguna dapat melihat data dalam zona waktu lokal mereka, sementara data mentah tetap bersih dan konsisten.
Kesimpulan#
Mengadopsi strategi UTC yang konsisten di seluruh stack aplikasi Anda adalah investasi waktu yang kecil di awal, tetapi akan menghemat banyak masalah dan headache di kemudian hari. Ini adalah praktik terbaik yang direkomendasikan untuk aplikasi yang beroperasi secara global atau yang memerlukan pelaporan waktu yang akurat.