Konuyu Açan
#0
Bir yazılımcı olarak kariyerimde beni en çok terleten, saç baş yolduran konulardan biri herhalde tarih ve zaman işlemleri olmuştur. Basit gibi durur değil mi? Alt tarafı bir tarih, bir saat... Ama gelin görün ki işin içine zaman dilimleri, yaz saati uygulamaları, artık yıllar, hatta bazen saniye atlamaları (leap seconds) girince işler bir anda çorbaya dönüyor. "Şu saatte oldu", "Şu tarihte yapıldı" demekle bitmiyor bu işler, hele ki global bir uygulama geliştiriyorsanız. Herkesin kendi yerel saatiyle çalışmasını beklemek, aslında felakete davetiye çıkarmak demek.
Neden Bu Kadar Karışık?
Şimdi şöyle bir düşünün: İstanbul'da saat öğlen 12:00 iken, Londra'da 09:00, New York'ta ise sabah 04:00 olabilir. Aynı anda gerçekleşen bir olayı veritabanına kaydederken herkes kendi saatini mi yazacak? E o zaman hangi olayın önce, hangi olayın sonra olduğunu nasıl anlayacağız? Ya da yaz saati uygulamasına geçişler... Bir gün bir saat ileri alınıyor, bir gün geri. O aradaki "kayıp" bir saat veya "kazanılan" bir saat, hesaplamaları nasıl etkileyecek? Raporlar, loglar, takvimler... Hepsi allak bullak olabilir. Bizim sektörde bu konuyu "kolay" gören çok kişi var, ta ki ilk büyük hatayı yapana kadar. Ondan sonra anlıyorlar işin ciddiyetini.
Temel Kavramlar: İşi Doğru Anlamak
Bu karmaşadan kurtulmanın yolu, temel kavramları sağlam oturtmaktan geçiyor. Her şeyden önce, bir standarda ihtiyacımız var.
Veritabanında ve Uygulamada Saklama Stratejileri
Şimdi gelelim bu değerleri nerede, nasıl tutacağımıza. Burada da birkaç farklı yaklaşım var, ama doğru olan tek bir yol var aslında:
Yaygın Sorunlar ve Çözümleri
Bu konuda başımıza gelen, gelmeyen kalmadı. İşte sıkça karşılaşılan dertler ve nasıl başa çıkabileceğimiz:
[list]
[b
Neden Bu Kadar Karışık?
Şimdi şöyle bir düşünün: İstanbul'da saat öğlen 12:00 iken, Londra'da 09:00, New York'ta ise sabah 04:00 olabilir. Aynı anda gerçekleşen bir olayı veritabanına kaydederken herkes kendi saatini mi yazacak? E o zaman hangi olayın önce, hangi olayın sonra olduğunu nasıl anlayacağız? Ya da yaz saati uygulamasına geçişler... Bir gün bir saat ileri alınıyor, bir gün geri. O aradaki "kayıp" bir saat veya "kazanılan" bir saat, hesaplamaları nasıl etkileyecek? Raporlar, loglar, takvimler... Hepsi allak bullak olabilir. Bizim sektörde bu konuyu "kolay" gören çok kişi var, ta ki ilk büyük hatayı yapana kadar. Ondan sonra anlıyorlar işin ciddiyetini.
Temel Kavramlar: İşi Doğru Anlamak
Bu karmaşadan kurtulmanın yolu, temel kavramları sağlam oturtmaktan geçiyor. Her şeyden önce, bir standarda ihtiyacımız var.
- UTC (Coordinated Universal Time): İşte bu, bizim kralımız. Dünya üzerindeki tüm zaman dilimlerinin referans noktası. Greenwich Ortalama Zamanı (GMT) ile aynıdır diyebiliriz, ufak tefek bilimsel farklılıkları olsa da günlük yazılım işlerimizde pratik olarak aynı kabul edilir. Veritabanlarınızda, backend sistemlerinizde, loglarınızda her zaman UTC kullanmalısınız. Neden mi? Çünkü UTC'nin zaman dilimi yok, yaz saati uygulaması yok. Sabit, değişmez bir referans noktası. Bu sayede farklı coğrafyalardan gelen verileri tutarlı bir şekilde karşılaştırabilir, sıralayabiliriz.
- Epoch Time / Unix Timestamp: Bu da UTC'nin bir nevi sayısal temsilidir. 1 Ocak 1970, saat 00:00:00 UTC'den bu yana geçen saniye sayısıdır. Bazen milisaniye veya mikrosaniye olarak da tutulur. Avantajı ne? Tek bir tam sayı. Karşılaştırması, saklaması, iletmesi çok kolay. Veritabanında bir integer veya bigint olarak saklayabilirsiniz. Performans açısından da çok iyidir. "Şu olay ne zaman oldu?" sorusuna tek bir sayıyla cevap vermek gibisi yok.
- Yerel Saat (Local Time): Kullanıcının bilgisayarının veya cihazının ayarlı olduğu zaman dilimine göre gösterilen saat. Bu, son kullanıcının gördüğü ve anladığı saat formatıdır. Bizim backend'de asla kullanmamamız gereken, sadece kullanıcı arayüzünde dönüştürüp göstermemiz gereken değerdir.
- Zaman Dilimleri (Timezones): Dünya üzerindeki coğrafi bölgelere göre belirlenen saat farkları. Her zaman diliminin bir adı vardır (örneğin "Europe/Istanbul", "America/New_York"). Bu zaman dilimleri, UTC'den belirli bir ofsete (örneğin +3 saat) sahiptir ve genellikle yaz saati uygulamalarına tabidir. İşin en zor kısmı da bu zaman dilimi dönüşümleri ve yaz saati geçişlerini doğru yönetmek.
Veritabanında ve Uygulamada Saklama Stratejileri
Şimdi gelelim bu değerleri nerede, nasıl tutacağımıza. Burada da birkaç farklı yaklaşım var, ama doğru olan tek bir yol var aslında:
- Veritabanında:
- TIMESTAMP (veya DATETIME WITH TIMEZONE): PostgreSQL gibi bazı veritabanları TIMESTAMP WITH TIME ZONE gibi tipler sunar. Bu, aslında değeri UTC olarak saklar ama sorgularken sizin oturumunuzun zaman dilimine göre dönüştürülmüş halini gösterir. Bu çok kullanışlıdır, çünkü saklama UTC, gösterim ise kullanıcı dostu olur. Ama dikkat, her veritabanı bunu aynı şekilde implemente etmez. MySQL'deki TIMESTAMP ise genellikle sunucunun zaman dilimine göre davranır, ki bu da kafa karıştırıcı olabilir.
- DATETIME (veya TIMESTAMP WITHOUT TIMEZONE): Bu, zaman dilimi bilgisi olmadan sadece yıl-ay-gün saat-dakika-saniye bilgisini saklar. Eğer bunu kullanıyorsanız, mutlaka ama mutlaka tüm değerleri UTC olarak saklayın. Uygulamanızda bir olay olduğunda, o anki yerel saati alıp direkt veritabanına yazmak yerine, önce onu UTC'ye çevirip öyle yazmalısınız. Okurken de tam tersi. Bu, bizim sektörde en sık yapılan hatalardan biridir.
- BIGINT (Epoch Time için): Eğer sadece bir olayın ne zaman gerçekleştiği, hangi sırada olduğu önemliyse, Unix timestamp olarak BIGINT kullanmak harika bir çözüm. Hem yer kaplamaz, hem indekslemesi kolaydır, hem de karşılaştırması basittir. Özellikle yüksek performans gerektiren sistemlerde veya log kayıtlarında çok işe yarar.
- TIMESTAMP (veya DATETIME WITH TIMEZONE): PostgreSQL gibi bazı veritabanları TIMESTAMP WITH TIME ZONE gibi tipler sunar. Bu, aslında değeri UTC olarak saklar ama sorgularken sizin oturumunuzun zaman dilimine göre dönüştürülmüş halini gösterir. Bu çok kullanışlıdır, çünkü saklama UTC, gösterim ise kullanıcı dostu olur. Ama dikkat, her veritabanı bunu aynı şekilde implemente etmez. MySQL'deki TIMESTAMP ise genellikle sunucunun zaman dilimine göre davranır, ki bu da kafa karıştırıcı olabilir.
- Programlama Dillerinde (Örnekler): Çoğu modern dil, tarih ve zaman işlemleri için sağlam kütüphanelere sahiptir.
- Python: modülü. ÖzellikleCODE
1
datetimeveyaCODE1
pytz(Python 3.9+) gibi kütüphanelerle zaman dilimi dönüşümlerini kolayca yapabilirsiniz.CODE1
zoneinfo
CODE12345678910111213141516
from datetime import datetime, timezone import pytz # veya zoneinfo [b]Şu anki UTC zamanı[/b] now_utc = datetime.now(timezone.utc) print(f"Şu anki UTC: {now_utc}") [b]İstanbul yerel saati[/b] istanbul_tz = pytz.timezone('Europe/Istanbul') now_istanbul = datetime.now(istanbul_tz) print(f"Şu anki İstanbul: {now_istanbul}") [b]UTC'yi İstanbul'a çevirme[/b] utc_to_istanbul = now_utc.astimezone(istanbul_tz) print(f"UTC'den İstanbul'a çevrilmiş: {utc_to_istanbul}")
- Java: paketi (Java 8 ve sonrası).CODE
1
java.time(UTC anı),CODE1
Instant(zaman dilimi olmayan tarih/saat),CODE1
LocalDateTime(zaman dilimi bilgisi içeren tarih/saat) gibi sınıflar sunar.CODE1
ZonedDateTime
- JavaScript: objesi. Tarayıcının yerel zaman dilimini kullanma eğilimindedir, bu yüzden backend'den gelen UTC değerlerini doğru parse edip, kullanıcıya göstermeden önceCODE
1
Dategibi metodlarla dönüştürmek gerekir.CODE1
toLocaleString()
- Python:
Yaygın Sorunlar ve Çözümleri
Bu konuda başımıza gelen, gelmeyen kalmadı. İşte sıkça karşılaşılan dertler ve nasıl başa çıkabileceğimiz:
[list]