Sorunun Arkasındaki Sayı
2147483647, 2^31 - 1’dir, işaretli 32 bit tamsayının maksimum değeridir. İkili olarak:
01111111 11111111 11111111 11111111
Baştaki 0 işaret bitidir. Unix zamanları 1960’ların sonlarında tasarlandığında, zamanı 32 bit tamsayı olarak saklamak hassasiyet, depolama maliyeti ve kullanılabilir aralık arasında denge kuran pragmatik bir seçimdi. İşaretli 32 bit tamsayı, 1 Ocak 1970’ten başlayarak yaklaşık 68 yıllık pozitif Unix zamanı verir.
Bu gelecek, 19 Ocak 2038 03:14:07 UTC’dir.
Taşma Anında Ne Olur
2147483647’den bir saniye sonra, işaretli 32 bit sayaç şu şekilde döner:
01111111 11111111 11111111 11111111 (2147483647)
+1
10000000 00000000 00000000 00000000 (-2147483648 ikinin tümleyeninde)
0x80000000 bit deseni, işaretli tamsayı olarak yorumlandığında -2147483648’dir. Unix zamanı olarak bu, 13 Aralık 1901 20:45:52 UTC’ye karşılık gelir.
Y2K ile Karşılaştırma
Y2K (2000 Yılı Sorunu), iki basamaklı yıl temsillerinden (99 → 00) kaynaklanıyordu. Y2K38 yapısal olarak benzer ancak daha sınırlıdır:
- Y2K, mimariden bağımsız olarak tüm yazılımları etkiledi. Y2K38 yalnızca 32 bit time_t kullanan sistemleri etkiler.
- Y2K, 1998-1999’da büyük bir küresel çabayla düzeltildi. Y2K38 azaltımı 1990’lardan beri devam etmektedir.
Hâlâ Risk Altındaki Sistemler
Gömülü ve IoT cihazları
ARM Cortex-M, MIPS, eski AVR türevleri gibi birçok mikrodenetleyici sabit bellenimle 32 bit mimarilerde çalışır.
Eski veritabanları
MySQL’in TIMESTAMP veri türü dahili olarak 32 bit Unix zamanı olarak saklanır ve maksimum değeri 2038-01-19 03:14:07’dir. DATETIME türü bu sınırlamaya sahip değildir.
-- MySQL TIMESTAMP max değeri
SELECT FROM_UNIXTIME(2147483647);
-- Döndürür: 2038-01-19 03:14:07
-- DATETIME'in böyle bir sınırı yoktur
ALTER TABLE events MODIFY created_at DATETIME(3);
32 bit Linux kurulumları
glibc 2.32’den önceki eski 32 bit Linux sistemleri 32 bit time_t kullanır.
Düzeltme: 64 bit time_t
64 bit işaretli tamsayı, epoch’tan itibaren yaklaşık ±9.2 × 10^18 saniyeyi, yani kabaca 292 milyar yılı temsil edebilir.
Çoğu modern dil ve çalışma zamanı zaten 64 bit Unix zamanları kullanır:
- Python:
time.time()float döndürür;datetimedahili olarak 64 bit kullanır. - JavaScript:
Date.now()float64 olarak milisaniye döndürür. - Java:
System.currentTimeMillis()birlong(64 bit) değeridir. - Go, Rust:
time.Time64 bit kullanır.
Geliştiriciler İçin Pratik Etkiler
Veritabanı şemanızı kontrol edin. MySQL’de TIMESTAMP sütunlarınız varsa, 2038 sonrası tarihleri temsil etmeleri gerekip gerekmediğini denetleyin. Gerekiyorsa DATETIME veya BIGINT’e geçin.
Tamsayı türlerinizi denetleyin. Unix zamanlarını kodda tamsayı olarak saklıyorsanız, int32/int değil int64/long/bigint olduklarından emin olun.
Gelecek Unix zamanlarıyla test edin. 20 Ocak 2038 için bir Unix zamanı oluşturan ve sisteminizin bunu doğru şekilde işlediğini doğrulayan bir test ekleyin.