2026-08-09veri3 dk

UTC saklamak yetmiyor: zaman dilimi hatalarının kaynağı

"Her şeyi UTC sakla" doğru ama eksik bir tavsiye. Randevu, rapor ve tekrarlayan işlerde saat hatalarının gerçek kaynağı ve doğru veri modeli.

Zaman dilimi konusunda ekiplere verilen standart tavsiye şu: "Her şeyi UTC olarak sakla, gösterirken kullanıcının saatine çevir." Doğru bir tavsiye — ama yalnızca bir tür zaman için doğru.

Uygulamalarda aslında üç farklı zaman kavramı var ve üçü farklı saklanmalı.

Üç tür zaman

1. Anlık olay (instant)

"Bu sipariş ne zaman oluştu?" Evrende tek bir andır; nerede olursanız olun aynı ana karşılık gelir.

Saklama: UTC zaman damgası. timestamptz (PostgreSQL) ya da eşdeğeri. Burada standart tavsiye tamamen geçerli.

2. Yerel takvim zamanı

"Doğum günü 12 Mart." "Fatura vadesi ayın 15'i." Bunların bir saat karşılığı yok; bir takvim ifadesi.

Saklama: date — zaman dilimi olmadan. Bunu UTC zaman damgası olarak saklamak, en yaygın hata kaynağıdır: doğum günü, kullanıcı farklı bir zaman diliminde görüntülediğinde bir gün kayar.

Bu hata Türkiye'de bile görülüyor, çünkü sunucu UTC, kullanıcı UTC+3 ve gece yarısına yakın kaydedilen bir tarih ertesi gün olarak görünüyor.

3. Gelecekteki yerel zaman

"Her salı saat 14:00'te toplantı." "Bu randevu 3 Eylül 15:30'da."

Bu, en zor olanı — ve UTC saklamanın yanlış olduğu durum.

Neden: gelecekteki bir yerel saat, o tarihe kadar zaman dilimi kuralları değişirse kayar. Yaz saati uygulamaları ülkeler tarafından değiştirilebiliyor; Türkiye'nin 2016'da kalıcı UTC+3'e geçmesi buna örnek. Randevuyu UTC olarak saklayan sistemlerde bu tür bir değişiklikten sonra bütün gelecek randevular yanlış saate kayar.

Saklama: Yerel tarih-saat ve zaman dilimi kimliği (Europe/Istanbul) ayrı alanlar olarak. UTC karşılığını gerektiğinde hesaplayın, saklamayın — ya da saklıyorsanız bunu bir önbellek olarak görün ve kural değişikliğinde yeniden hesaplayın.

Zaman dilimi kimliği, ofset değildir

+03:00 bir ofsettir; Europe/Istanbul bir zaman dilimi kimliğidir. İkisi aynı şey değil.

Ofset, tek bir andaki farkı söyler. Kimlik, o bölgenin tarih boyunca değişen kurallarını taşır. Kullanıcının zaman dilimini ofset olarak saklarsanız, altı ay sonra yaz saati uygulaması olan bir ülkede yanlış hesap yaparsınız.

Kullanıcı ayarlarında saklanacak değer her zaman IANA kimliğidir.

Raporlarda "gün" nedir?

Bir günlük satış raporu hazırlarken gün sınırı nerede başlıyor? Sunucunun UTC gecesinde mi, işletmenin bulunduğu yerin gecesinde mi?

Türkiye'de faaliyet gösteren bir işletme için doğru cevap ikincisi. Yani rapor sorgusu şuna benzemeli:

WHERE olusturma_zamani >= '2026-08-09 00:00:00 Europe/Istanbul'
  AND olusturma_zamani <  '2026-08-10 00:00:00 Europe/Istanbul'

Bunu UTC gün sınırıyla yapan sistemlerde gece 00:00-03:00 arasındaki satışlar bir önceki güne yazılıyor ve muhasebe ile rapor tutmuyor. Bu, e-ticarette gerçekten yaşanan bir uyuşmazlık.

Gece geç saatlere kadar çalışan işletmelerde (restoran, bar) bir adım daha var: işletmenin "iş günü" gece yarısında değil, sabah 04:00'te bitiyor olabilir. Bu, veri modelinde ayrı bir tanım gerektirir.

Tekrarlayan işler

"Her gün saat 09:00'da rapor gönder" gibi bir zamanlanmış iş, UTC olarak tanımlandığında yaz saati uygulaması olan ülkelerde yılda iki kez bir saat kayar. Zamanlayıcınızın zaman dilimi desteği varsa kullanın; yoksa işi UTC'de tanımlamak yerine, çalıştığında yerel saati kontrol eden bir koruma ekleyin.

Test edilmesi gereken üç durum

Zaman kodu yazan her ekibin test kümesinde bulunması gerekenler:

  1. Gece yarısına 5 dakika kala oluşturulan kayıt, kullanıcının gününde doğru yerde mi?
  2. Yaz saati geçişi olan bir bölge (örn. Europe/Berlin) için, geçiş gününde 24 saatlik aralık doğru hesaplanıyor mu?
  3. Var olmayan yerel saat. Yaz saatine geçişte bazı yerel saatler hiç yaşanmaz. O saate randevu kaydedilmeye çalışıldığında sisteminiz ne yapıyor?

Üçüncüsü çoğu sistemde hiç düşünülmemiş oluyor ve sessizce yanlış bir saate kaydediyor.

Özet kural

Zaman türü Saklama Örnek
Olan bir şey UTC zaman damgası sipariş oluşturma
Takvim ifadesi tarih (dilimsiz) doğum günü, vade
Gelecekteki yerel an yerel tarih-saat + IANA kimliği randevu, toplantı

Üçünü aynı sütun tipinde saklamak, hataların büyük kısmının kaynağı. Ayırmak, sonradan düzeltmekten çok ucuz.