Uluslararası Zaman Yönetimi
Zaman Dilimleri ve Uygulamaları
Makalenin kapsamı
Bu makale, zaman bilgisini yalnızca bir saat değeri olarak değil; tarihsel kuralları, bölgesel kimliği ve sistemler arası aktarımı olan bir veri modeli olarak ele alır.
- UTC ve GMT arasındaki farkı ve doğru kullanım alanlarını açıklar.
- IANA zaman dilimi veritabanını, bölge kimliklerini ve DST kurallarını inceler.
- ISO 8601 tarih ve saat gösterimlerini karşılaştırır.
- Uygulama, veritabanı ve API katmanlarında güvenli zaman yönetimi ilkelerini sunar.
“Saat kaç?” gündelik hayatta basit bir sorudur. Ancak İstanbul'da gerçekleşen bir işlemi Tokyo'daki sunucuda saklayıp New York'taki kullanıcıya göstermek istediğinizde soru değişir: Kimin saati?
Toplantılar, canlı yayınlar, işlem kayıtları ve planlanmış görevler aynı probleme dayanır. Doğru cevap; tarihsel standartları, politik kararları ve yazılımın zamanı nasıl temsil ettiğini birlikte anlamayı gerektirir.
Güneşin Söylediği Saat
Binlerce yıl boyunca öğle, güneşin en yüksek noktaya ulaştığı an kabul edildi. Her şehir kendi yerel saatini kullandı; ulaşım ve iletişim yavaş olduğu için birkaç dakikalık fark günlük hayatı etkilemedi.
Hızlı ulaşım yaygınlaşınca yerel saatler ortak bir programa uymamaya başladı.
Her İstasyonun Saati Farklı
1830'larda demiryollarının yaygınlaşmasıyla “yerel öğle” sistemi işlemez hale geldi. İngiltere'de Bristol, Londra'dan 11 dakika gerideydi; makinist ve yolcu farklı saatlere göre hareket ettiğinde tarifeler güvenilirliğini yitiriyordu.
Çözüm 1847'de geldi: İngiliz demiryolları Railway Time adı altında tüm hatlarında Greenwich saatini (GMT) zorunlu kıldı. 1880'de tüm Britanya bunu resmi kabul etti.
Dünya genelinde ise ortak bir standart henüz yoktu. ABD'de 1883'te 300'den fazla yerel saat kullanılıyordu; demiryolu şirketlerinin belirlediği dört bölgenin yasal karşılığı bulunmuyordu.
Greenwich'ten Başlıyor Her Şey
1884'te 25 ülkenin delegesi, dünya için ortak bir referans noktası belirlemek üzere Washington'daki Uluslararası Meridyen Konferansı'nda buluştu.
Oylamayla Londra'nın güneydoğusundaki Greenwich Rasathanesi'nden geçen çizgi, 0° başlangıç meridyeni kabul edildi. Fransa çekimser kaldı (Paris meridyenini savunuyordu), ama sonunda herkes Greenwich'e razı oldu.
Kural basittir: her 15 derecelik meridyen dilimi bir saate eşittir. Doğuya gittikçe saat ileri (+), batıya gittikçe geri (−). Toplam 24 dilim, 24 saat.
Bu geometrik model tek başına yeterli değildir. İstanbul ile Berlin arasındaki fark, Almanya yaz saati uyguladığında bir; standart saate döndüğünde iki saattir.
Aynı iki şehir arasındaki saat farkı bile yılın farklı zamanlarında değişebilir.
Çünkü zaman dilimlerinin sınırları ve kuralları siyasi kararlarla belirlenir.
Çin, coğrafi olarak yaklaşık dört meridyen dilimine yayılmasına rağmen ülke genelinde UTC+8 kullanır. Bu nedenle aynı resmi saat, Pekin ve Urumçi'de güneş zamanıyla farklı anlamlara gelir.
Türkiye'nin yakın tarihi, bu kuralların ne kadar hızlı değişebildiğini gösterir.
Saat Kaçta Uyandığınızı Politikacılar Belirliyor
Zaman dilimleri kalıcı coğrafi kurallar değildir. Ülkeler enerji, ekonomi veya idari tercihler nedeniyle saat düzenlerini değiştirebilir.
Türkiye'nin Zaman Dilimi Kronolojisi
Türkiye, 2016 öncesinde standart saat ile yaz saati arasında geçiş yapıyordu. Sürecin başlıca kararları şöyledir:
- 1940 — Bakanlar Kurulu kararıyla yaz saati uygulaması resmen başladı
- 1952–1961 — Uygulama askıya alındı
- 1965–1972 — Tekrar askıya alındı, sonrasında aralıksız devam edildi
- 2008 — Enerji Bakanlığı GMT+2,5 zaman dilimi önerdi. İlerleme olmadı.
- 2013 — Enerji Bakanlığı uygulamanın kaldırılması yönünde karar aldı
- 2015 — Yaz saatinden çıkış, 1 Kasım seçimleri nedeniyle ertelendi; geçiş bir hafta sonra yapıldı.
- 8 Eylül 2016 — Bakanlar Kurulu kararıyla yaz saati kalıcı hâle getirildi (GMT+3)
- 14 Eylül 2017 — Danıştay kararı durdurdu
- 23 Ekim 2017 — Bakanlar Kurulu yeniden devam kararı aldı
- 2 Ekim 2018 — Son nokta: yaz saati uygulaması kalıcı hâle geldi
Sonuç, yaz saatinin kaldırılması değil; UTC+3 düzeninin yıl boyunca kalıcı hale gelmesi oldu.
Bu Sadece Türkiye'ye Özgü Değil
Son yıllarda benzer kararlar alan başka ülkeler de var:
- Grönland (Mart 2023) — Kalıcı yaz saatine geçti (UTC−02:00). Artık saat değiştirmiyor.
- Ukrayna (Temmuz 2024) — DST'yi kaldırdı, son geçiş 27 Ekim 2024'te yapıldı. Kalıcı UTC+2 (EET).
- Rusya (2014) — Önce kalıcı yaz (2011), sonra kalıcı kış (2014). Moskova: UTC+3.
Bu örnekler, zaman dilimi verisinin sabit kabul edilemeyeceğini gösterir. Ortak ve hassas bir zaman referansı ihtiyacı, atom saatleriyle karşılandı.
UTC: Herkesin Anlaştığı Tek Nokta
GMT'nin sorunu şuydu: Dünya'nın dönüşüne dayanıyordu ve bu dönüş mükemmel değildi. Atom saatleri devreye girince, çok daha kesin bir referans mümkün hâle geldi: UTC (Koordineli Evrensel Zaman).
UTC, iki şeyin birleşimidir:
- Uluslararası Atom Saati (TAI) — Dünya genelinde ~400 süper hassas atom saatinin ortalaması. Kesin hızı sağlar.
- Evrensel Zaman (UT1) — Dünya'nın gerçek dönüş hızı. Gelgitler ve jeofiziksel süreçler nedeniyle düzensizdir.
Bu ikisinin kombinasyonu, UTC'nin hem doğru hem de Dünya'nın dönüşüyle uyumlu kalmasını sağlar. 1960'ta kavram resmileşti, 1967'de adı benimsendi. O günden bu yana GMT artık bir standart değil, sadece bir zaman dilimi adıdır (UTC+0 ile eşdeğer).
| Kavram | Ne İfade Eder | Bugünkü Kullanımı |
|---|---|---|
| GMT | Dünya'nın dönüşüne dayalı eski standart | Sadece bir zaman dilimi adı (UTC+0) |
| UTC | Atom saati + Dünya dönüşü | Küresel standart |
| TAI | Saf atomik ölçüm | Bilimsel referans (UTC'den 37 saniye ileride) |
| Zulu (Z) | UTC'nin askeri kısaltması | Havacılık, NATO |
Dünya'nın dönüşü atom saatleri kadar düzenli değildir. Aradaki farkı sınırlamak için UTC'ye gerektiğinde artık saniye (leap second) eklenir. Negatif artık saniye teorik olarak mümkündür, ancak bugüne kadar uygulanmamıştır.
1972'den bu yana 27 artık saniye eklendi; son uygulama 31 Aralık 2016'da yapıldı.
18 Kasım 2022'de Genel Ağırlıklar ve Ölçüler Konferansı (CGPM), Resolution 4 ile leap second mekanizmasının 2035'te veya öncesinde sona ereceğini kararlaştırdı. WRC-23 (Dubai, Aralık 2023) bu kararı resmen tanıdı. 28. CGPM (2026) yeni limitleri onaylayacak.
Tek saniyelik değişiklik bile dağıtık sistemlerde kesinti ve zaman sıralaması hataları oluşturabilir. Kararın kısa süre önce duyurulması nedeniyle bazı platformlar değişikliği zamana yayan “leap smear” yöntemleri kullanır.
UTC ortak referansı sağlar; yerel yaz saati kuralları ise ülkelerin kararlarına bağlı kalır.
Yaz Saati: Avrupa'nın Bitmeyen Tartışması
Birçok Avrupa ülkesi yıl içinde CET (UTC+1) ile CEST (UTC+2) arasında geçiş yapar:
| Kısaltma | Tanım | UTC Offset | Dönem |
|---|---|---|---|
| CET | Central European Time | UTC+1 | Kış (Kasım–Mart) |
| CEST | Central European Summer Time | UTC+2 | Yaz (Mart–Ekim) |
CEST için CEDT, ECST veya MESZ gibi farklı kısaltmalarla da karşılaşılabilir. Bu çeşitlilik, uygulamalarda kısaltma yerine sayısal offset ve IANA kimliği kullanılmasının nedenlerinden biridir.
Avrupa Komisyonunun 2018 anketinde 4,6 milyon katılımcının %84'ü saat değişikliğinin kaldırılmasını istedi. Parlamento öneriyi 2019'da onayladı; ancak üye devletler kalıcı saat düzeninde uzlaşamadı.
Mayıs 2026 itibarıyla: Konsey onayı hâlâ yok. Ekim 2025'te EP plenerde tartışıldı, somut tarih verilmedi. Süreç "tamamen bloke." IANA'nın uyarısı geçerli: "1 yıldan az sürede bazı bilgisayar saatleri hatalı çalışabilir."
Bazı ülkeler beklemedi: Türkiye (2016, kalıcı yaz), Rusya (2014, kalıcı kış), Ukrayna (2024, kalıcı kış), Grönland (2023, kalıcı yaz).
Değişken yerel kurallar, yazılımın yalnızca mevcut offset değerine güvenemeyeceği anlamına gelir.
Sanıyorsunuz ki Zaman Dilimleri Basit...
Uygulama kararlarına geçmeden önce yaygın yanılgıları ayıralım:
"GMT = UTC = Zulu, hepsi aynı" — Çok yakın ama aynı değil. Üçü de 0° meridyeni referans alır, yaz saati uygulamaz. Fark: GMT eski standarttı (dönüşe dayalı); UTC atomik hassasiyetle modern versiyonu; Zulu ise UTC'nin havacılık/askeri kısaltması. Bugün UTC tercih edilen standarttır.
"Offsetler ±12 ile sınırlıdır" — Değildir. UTC+13 ve UTC+14 kullanan bölgeler vardır.
"Her offset tam saattir" — Bazı bölgeler yarım veya çeyrek saatlik offset kullanır:
| Ülke | Offset |
|---|---|
| İran | UTC+3:30 |
| Hindistan | UTC+5:30 |
| Nepal | UTC+5:45 |
| Chatham Adaları (Yeni Zelanda) | UTC+12:45 |
"DST her yerde aynı tarihte başlar" — Hayır. Güney Yarımküre'de yaz zıt aylarda. ABD'deki Navajo Ulusu gibi kısmi uyumlar da var.
"CST tek bir zaman dilimini gösterir" — Aynı kısaltma birden fazla anlam taşıyabilir:
| Kısaltma | Temsil Ettiği |
|---|---|
| CST | Central Standard Time (Kuzey Amerika) |
| CST | Central Standard Time (Avustralya) |
| CST | Central Summer Time (Avustralya) |
| CST | China Standard Time |
| CST | Cuba Standard Time |
"Büyük ülke = çok dilim" — Her zaman değil. Çin 4 meridyeni kaplar ama tek saat kullanır.
Uygulama ilkesi: Kısaltma yerine IANA tanımlayıcısı (Europe/Istanbul) ve gerektiğinde UTC offset (UTC+03:00) kullanın.
Bu değerlerin sistemler arasında taşınması için ortak biçim ISO 8601'dir.
Herkesin Konuştuğu Format: ISO 8601
Tarihleri ve saatleri kaydetmenin evrensel formatı: ISO 8601 (1988). Amacı: tarihlerin farklı ülkelerde yanlış yorumlanmasını önlemek.
Temel ilkesi: büyükten küçüğe sırala. Yıl → ay → gün → saat → dakika → saniye. Her değer sabit haneli, başında sıfır ile doldurulur.
İki biçim: temel (20090106) ve genişletilmiş (2009-01-06). Azaltılmış hassasiyet de mümkün: 2004-05 geçerli (Mayıs 2004).
Zaman dilimi bilgisi, UTC veya offset olarak eklenir. "Offset" = UTC'den kaç saat fark:
| Format | Anlam |
|---|---|
2024-07-04T17:00:00Z |
UTC (Z = Zulu = +00:00) |
2024-07-04T17:00:00+03:00 |
Türkiye (UTC+3) |
2024-07-04T17:00:00-05:00 |
ABD Doğu (UTC-5) |
2024-07-04T17:00:00+05:30 |
Hindistan (UTC+5:30) |
Z, değerin UTC olduğunu; +03:00 ise yerel saatin UTC'den üç saat ileride olduğunu belirtir.
Gelecek: Neler Değişiyor?
Zaman sistemlerini etkileyen iki önemli gelişme vardır:
1. Artık saniye uygulamasının sona ermesi. 2035 veya öncesinde mevcut yöntem bırakılacaktır:
| Tarih | Olay |
|---|---|
| 31 Aralık 2016 | Son eklenen leap second |
| 18 Kasım 2022 | CGPM Resolution 4 kararı |
| Aralık 2023 | WRC-23 (Dubai) resmen tanıdı |
| 2026 | 28. CGPM — yeni limit gözden geçirilecek |
| 2035 (veya önce) | Yeni UT1-UTC limiti yürürlüğe girecek |
2. AB'nin yaz saati kararı sonuçlanmadı. Üye devletler ortak bir düzen üzerinde uzlaşana kadar uygulamalar güncel IANA verisini izlemeye devam etmelidir.
Zamanı ölçmek kolay. Zor olan, tüm dünyanın aynı anı aynı dilde konuşmasını sağlamak.
Zaman dilimleri tamamlanıp değişmeden kalan bir veri kümesi değildir. Ülke kararları ve IANA güncellemeleri, uygulamaların düzenli bakım gerektirdiğini gösterir.
Yazılım Sistemlerinde Zaman
Aynı an, farklı zaman dilimlerinde farklı yerel saatlerle gösterilir.
An sabittir; yerel saat, o anın belirli bir zaman dilimindeki gösterimidir.
Gösterilecek zaman dilimi farklı kaynaklardan belirlenebilir:
- Kullanıcı Tercihleri (User Profiles)
- Tarayıcı Varsayılanları (Browser Default Settings)
- İstek Başlıkları (Request Headers)
- Oturum Bilgileri (Session Data)
- Ortam / Sistem Değişkenleri (Environment Variables)
Doğru bir zaman gösterimi için üç bilgi gerekir:
- Olayın UTC anı
- Olayın gerçekleştiği zaman dilimi
- Gösterimin yapılacağı kullanıcının zaman dilimi
Örnek: İstanbul'da saat 17:00'de bir işlem yapıldı. Bu işlemi Tokyo'daki kullanıcı 23:00, New York'taki 10:00 olarak görmeli — ama hepsi aynı anı ifade etmeli.
İşlemin gerçekleştiği yerel saat de önemliyse UTC anıyla birlikte kaynak zaman dilimini saklayın.
Uygulama için temel adımlar:
- Zaman bilgisini mutlaka UTC olarak kaydedin
- Kullanıcıların profillerinde zaman dilimi bilgilerini tutun
- Mümkünse tarih/zaman bilgisini sunucuda (UTC olarak) oluşturun
- Tüm sistem bileşenlerinin (OS, framework, runtime, DB) varsayılan TimeZone değeri UTC olsun
- İşlemin gerçekleştiği zaman dilimini IANA kimliğiyle kaydedin; offset tek başına geçmiş ve gelecek kurallarını taşımaz.
- İş gereksinimi yerel duvar saatine bağlıysa bu değeri ayrıca saklayın. Gelecek zamanlı planlarda yerel saat ve bölge kimliği birlikte gereklidir.
Aynı anı üç farklı yerde gösterme örneği:
// Tek bir anı (UTC) farklı zaman dilimlerinde görüntüleme
const event = new Date('2026-07-19T20:00:00Z'); // Örnek olayın UTC anı
const fmt = (tz) => event.toLocaleString('tr-TR', { timeZone: tz, hour: '2-digit', minute: '2-digit' });
console.log(fmt('America/New_York')); // 16:00 (yerel)
console.log(fmt('Europe/Istanbul')); // 23:00
console.log(fmt('Asia/Tokyo')); // 05:00 (+1 gün)
Bir sonraki adım, bu bilgiyi doğru veri tipiyle temsil etmektir.
Zaman Tipleri: Epoch, DateTime, DateTimeOffset
Unix Epoch ve Timestamp
Bilgisayarlar zamanı genellikle tek bir sayı olarak ifade eder: Unix timestamp — 1 Ocak 1970 00:00:00 UTC'den itibaren geçen saniye sayısı. Zaman dilimi bilgisi taşımaz, her yerde aynı anı temsil eder.
| Temsil | Değer | Anlam |
|---|---|---|
| Unix timestamp | 1721404800 |
19 Temmuz 2024 12:00 UTC |
| ISO 8601 | 2024-07-19T12:00:00Z |
Aynı an, okunabilir |
| .NET Ticks | 638565648000000000 |
Aynı an, 100ns hassasiyet |
Y2K38 uyarısı: 32-bit Unix timestamp 19 Ocak 2038'de taşacak. Bugün başlayan projelerde 64-bit zaman kullanın.
DateTime vs DateTimeOffset (.NET)
DateTime ile DateTimeOffset aynı bilgiyi taşımaz. Seçim, değerin tek bir anı mı yoksa yalnızca yerel duvar saatini mi temsil ettiğine göre yapılmalıdır.
// DateTime — offset bilgisi yok, anlam belirsiz
DateTime ambiguous = new DateTime(2026, 7, 19, 17, 0, 0);
// Bu 17:00 UTC mi? İstanbul mu? Tokyo mu? Belli değil.
// DateTimeOffset — offset bilgisi taşır, anlam net
DateTimeOffset precise = new DateTimeOffset(2026, 7, 19, 17, 0, 0, TimeSpan.FromHours(3));
// 17:00+03:00 → İstanbul saati, UTC karşılığı 14:00Z
// UTC olarak kaydetme
DateTimeOffset utcNow = DateTimeOffset.UtcNow; // Her zaman UTC
| Tip | Offset Taşır | DB'de Güvenli | Ne Zaman Kullan |
|---|---|---|---|
DateTime |
Hayır | Kısıtlı | Sadece yerel UI gösterimi |
DateTimeOffset |
Evet | Evet | API, DB, event kayıtları |
NodaTime.Instant |
Uygulanmaz | Evet | Hassas zaman hesaplamaları |
NodaTime: Daha Güvenli Bir Alternatif
NodaTime, an, yerel tarih-saat ve zaman dilimi kavramlarını ayrı tiplerle ifade ederek .NET'in yerleşik API'sindeki belirsizlikleri azaltır:
// NodaTime — açık ve güvenli
Instant now = SystemClock.Instance.GetCurrentInstant();
DateTimeZone zone = DateTimeZoneProviders.Tzdb["Europe/Istanbul"];
ZonedDateTime istanbul = now.InZone(zone); // 2026-07-19T20:00:00+03:00
// DST geçişi sırasında belirsizlik? NodaTime sizi uyarır:
LocalDateTime ambiguous = new LocalDateTime(2024, 10, 27, 2, 30);
// Almanya'da bu saat iki kez yaşanır — NodaTime exception fırlatır
NodaTime kendi IANA tzdata kopyasını NuGet paketiyle taşır. Böylece kullanılan veri sürümü işletim sisteminden bağımsız yönetilebilir ve gerektiğinde sabitlenebilir.
Offset ≠ Time Zone
Offset yalnızca belirli bir andaki UTC farkını gösterir; zaman dilimi ise geçmiş ve gelecek kurallarını da içerir.
| Kavram | Ne Taşır | Örnek |
|---|---|---|
| Offset | Sadece şu anki UTC farkı | +03:00 |
| Time Zone (IANA ID) | Tüm DST kuralları, geçmiş değişiklikler, gelecek planları | Europe/Istanbul |
UTC+03:00 Türkiye, Suudi Arabistan veya Moskova'yı birbirinden ayıramaz. Aynı offset değerini kullansalar da tarihsel kuralları farklıdır.
// Yalnızca offset kaydetmek gelecekte yetersiz kalabilir
var record = new { Time = DateTimeOffset.Parse("2024-03-01T10:00:00+05:00") };
// Kazakistan Mart 2024'te +6'dan +5'e geçti.
// Bu kayıt değişiklik öncesi mi sonrası mı? Belli değil.
// IANA zone ID ve instant değerini birlikte saklayın
var record2 = new {
Instant = Instant.FromUtc(2024, 3, 1, 5, 0),
ZoneId = "Asia/Almaty" // kuralları taşır
};
// Artık bu anın hangi yerel saate denk geldiğini her zaman doğru hesaplayabilirsiniz.
Gelecek Zaman: UTC Kuralının İstisnası
Gerçekleşmiş olaylar için UTC anı yeterlidir. Gelecek zamanlı planlar ise yerel saat kuralını da korumalıdır.
Örneğin “Her pazartesi İstanbul saatiyle 10:00” planını yalnızca UTC 07:00 olarak saklamak şu riskleri doğurur:
- Türkiye yarın offset'ini değiştirirse (tekrar +2'ye dönse), toplantı yanlış saatte tetiklenir
- Kullanıcının niyeti "duvar saati ile 10:00" idi — UTC değil
| Zaman Türü | Nasıl Saklanmalı | Neden |
|---|---|---|
| Geçmiş olay (log, işlem) | UTC instant (Instant veya DateTimeOffset) |
An sabit, asla değişmez |
| Gelecek randevu | Yerel saat + IANA zone ID (LocalDateTime + DateTimeZone) |
Kurallar değişebilir, anı son anda hesapla |
| Tekrarlayan olay | Yerel saat + IANA zone ID + tekrar kuralı (RRULE) | Her tetiklemede güncel kurala göre UTC'ye çevir |
// NodaTime — gelecek randevu doğru yönetimi
var zone = DateTimeZoneProviders.Tzdb["Europe/Istanbul"];
var localMeeting = new LocalDateTime(2027, 3, 15, 10, 0); // "duvar saati 10:00"
// Hatırlatma gönderirken: o anki kurala göre instant hesapla
var zoned = localMeeting.InZoneLeniently(zone);
var utcInstant = zoned.ToInstant(); // Şu anki kurala göre UTC
// Eğer Türkiye 2027'de offset değiştirirse,
// bu kod yeni kuralla doğru UTC'yi üretir — çünkü LocalDateTime sakladık.
Bu dönüşümlerin doğruluğu, kullanılan zaman dilimi verisinin kaynağına ve güncelliğine bağlıdır.
İki Veritabanı, İki Dünya
Zaman dilimi bilgileri iki büyük veritabanında tutulur:
| Veritabanı | Kim Yönetiyor | Format | Güncelleme |
|---|---|---|---|
| Microsoft Windows TZ | Microsoft | Registry | Windows Update |
| IANA/Olson (tzdata) | Topluluk + IANA | Text dosyaları | Yılda birkaç kez |
Çapraz platform uygulamalarda veri kaynağı açıkça belirlenmelidir. Microsoft, IANA tanımları için destek ve iki sistem arasında eşleme olanağı sunar; ancak çalışma zamanındaki gerçek veri kaynağı platforma bağlı kalabilir.
Microsoft'un Yaklaşımı
Windows, zaman dilimlerini Registry'de tutar:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
Artıları: Windows ile bütünleşir, sistem güncellemeleriyle dağıtılır ve .NET üzerinden kolayca kullanılır.
Eksileri: Tarihsel veri kapsamı ve adlandırma yaklaşımı IANA ile aynı değildir; güncellik işletim sistemi yamalarına bağlıdır.
Bazı Microsoft adları coğrafi kapsamı doğrudan ifade etmez:
- "Eastern Standard Time" — hem EST hem EDT'yi kapsıyor (yanıltıcı)
- "US Mountain Standard Time" — Arizona'nın sabit MST'si için
- "Romance Standard Time" — başka hiçbir veritabanında yok, Microsoft'a özgü
- "AUS Eastern Standard Time" vs "E. Australia Standard Time" — sadece DST farkı
- "Arab", "Arabian", "Arabic Standard Time" — üç farklı dilim, üç benzer isim
IANA: Endüstri Standardı
IANA veritabanı (ZoneInfo, TZDB, TZ Database), Linux, macOS, Java, PHP ve modern .NET'te kullanılır. Format: Bölge/Şehir — Europe/Istanbul.
Artıları: Geniş platform desteği, anlaşılır isimlendirme, tarihsel veri, RFC'lerde referans, topluluk sürdürür.
Eksileri: Birçok uygulama manuel güncelleme gerektirir, çok sayıda dilim UX'te liste sunmayı zorlaştırır.
Her iki kimlik sistemini tanımak yeterli değildir; kullanılan verinin sürümü ve çalışma ortamı da yönetilmelidir.
Platform ve Güncellik Riskleri
Kimlik eşleme desteği, zaman dilimi verisinin güncel olduğu anlamına gelmez. Uygulama, işletim sistemi, veritabanı ve container farklı veri sürümleri kullanabilir.
.NET 6+ ve ICU eşlemesi
.NET 6'dan itibaren FindSystemTimeZoneById("Europe/Istanbul") Windows'ta da çalışır. Bu işlem bir kimlik eşlemesidir; kullanılan kurallar yine işletim sistemindeki veriye bağlıdır. Güncellenmemiş Windows kurulumlarında veya eski sunucu imajlarında:
- Türkiye 2016'da DST'yi kaldırdı → güncellenmemiş sunucu hâlâ yaz/kış geçişi uygular
- Rusya 2014'te dilim değiştirdi → eski patch'siz makinelerde yanlış offset döner
- Mısır, Fas, Şili gibi sık kural değiştiren ülkeler için aynı risk geçerli
// .NET 6+ — her platformda çalışır (ICU mapping)
var tz = TimeZoneInfo.FindSystemTimeZoneById("Europe/Istanbul");
// AMA: Bu veri nereye dayanıyor?
// Windows → Registry (Windows Update'e bağlı)
// Linux → /usr/share/zoneinfo (tzdata paketine bağlı)
// Docker → Container image'ındaki tzdata versiyonuna bağlı
SQL Server ve Windows verisi
SQL Server'ın AT TIME ZONE komutu doğrudan Windows Registry'yi okur:
-- SQL Server: her zaman Windows TZ ID bekler
SELECT GETUTCDATE() AT TIME ZONE 'Turkey Standard Time';
-- Bu komutun doğru sonuç vermesi için:
-- 1. Host OS'un güncel Windows Update almış olması
-- 2. Registry'deki TZ verisinin doğru olması
-- 3. IANA ID desteklenmez (2026 itibarıyla hâlâ)
Örneğin güncellenmeyen bir Windows Server üzerindeki SQL Server, Kazakistan'ın 2024 zaman dilimi değişikliğini bilmeyebilir. Bu durumda ilgili kullanıcıların yerel saat dönüşümleri bir saat hatalı olur.
Docker ve cloud ortamları
# Alpine tabanlı .NET image — tzdata yüklü gelmez!
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
# TimeZoneInfo.FindSystemTimeZoneById → TimeZoneNotFoundException
# Çözüm: tzdata paketini kendiniz ekleyin
RUN apk add --no-cache tzdata
Cloud VM ve container imajlarında tzdata paketi eksik veya eski olabilir. Sürüm bilgisi dağıtım sürecinde açıkça kontrol edilmelidir.
Uygulama yaklaşımı
| Katman | Risk | Önlem |
|---|---|---|
| .NET API sunucusu | OS tzdata eski | Windows Update politikasını zorunlu kıl, Docker'da tzdata pinle |
| SQL Server | Registry eski, IANA desteksiz | Tarih/saati UTC olarak sakla, dönüşümü uygulama katmanında yap |
| Frontend (JS) | Kullanıcının cihazındaki IANA verisi eski | Intl API'si runtime'a bağlı — kritik hesaplamaları backend'de yap |
| Mobil | OS güncellenmemiş | Aynı strateji — UTC sakla, yerel göster |
Sistem sınırlarında şu üç gösterimi kullanın:
| # | Format | Örnek |
|---|---|---|
| 1 | IANA tanımlayıcısı | Europe/Istanbul |
| 2 | Microsoft tanımlayıcısı | Turkey Standard Time |
| 3 | UTC Offset | UTC+03:00 |
Kısaltmaları veri alışverişi veya kalıcı kayıt formatı olarak kullanmayın. Referans listesi: Wikipedia
Bu riskler, üretim öncesinde otomatik kontroller ve sınır koşulu testleriyle görünür hale getirilebilir.
Test ve CI/CD Stratejisi
Zaman dilimi hataları yalnızca belirli tarihlerde veya bölgelerde ortaya çıkabilir. Testler; veri sürümünü, DST geçişlerini ve çalışma ortamındaki tzdata kurulumunu kapsamalıdır.
tzdata Versiyonunu CI'da Kontrol Etme
# Linux/Docker — tzdata versiyonunu kontrol et
cat /usr/share/zoneinfo/tzdata.zi | head -1
# veya
dpkg -s tzdata | grep Version # Debian/Ubuntu
apk info tzdata # Alpine
# Beklenen minimum versiyon kontrolü (CI script)
EXPECTED="2026b"
ACTUAL=$(cat /usr/share/zoneinfo/tzdata.zi | head -1 | grep -oP '\d{4}[a-z]')
if [[ "$ACTUAL" < "$EXPECTED" ]]; then
echo "tzdata eski: $ACTUAL (beklenen: >= $EXPECTED)"
exit 1
fi
DST Geçiş Anlarını Test Etme
// xUnit — DST sınır koşulları
[Theory]
[InlineData("2024-03-31T01:59:00+01:00", "Europe/Berlin", "2024-03-31T02:59:00+02:00")]
[InlineData("2024-10-27T02:30:00+02:00", "Europe/Berlin", "2024-10-27T02:30:00+01:00")]
public void DstTransition_ShouldResolveCorrectly(string input, string tzId, string expected)
{
var dto = DateTimeOffset.Parse(input);
var tz = TimeZoneInfo.FindSystemTimeZoneById(tzId);
var converted = TimeZoneInfo.ConvertTime(dto, tz);
Assert.Equal(DateTimeOffset.Parse(expected), converted);
}
// Belirli ülke kurallarını doğrula
[Fact]
public void Turkey_HasNoDst_Since2016()
{
var tz = TimeZoneInfo.FindSystemTimeZoneById("Europe/Istanbul");
var summer = new DateTimeOffset(2026, 7, 15, 12, 0, 0, TimeSpan.FromHours(3));
var winter = new DateTimeOffset(2026, 12, 15, 12, 0, 0, TimeSpan.FromHours(3));
// Türkiye'de yaz-kış farkı olmamalı
Assert.Equal(summer.Offset, winter.Offset);
}
Docker Image'ında tzdata Pinleme
# Dockerfile — tzdata versiyonunu sabitle
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
# tzdata'yı belirli versiyonda yükle
RUN apk add --no-cache tzdata~=2026
# Health check'e tzdata versiyonu ekle
HEALTHCHECK CMD test -f /usr/share/zoneinfo/tzdata.zi
NodaTime ile Bağımsız Test
// NodaTime — OS'tan bağımsız, kendi TZDB ile test
var tzdb = DateTimeZoneProviders.Tzdb; // NuGet paketindeki versiyon
var zone = tzdb["Asia/Almaty"];
// Kazakistan 2024'te tek dilime geçti — bunu doğrula
var beforeChange = Instant.FromUtc(2024, 2, 29, 12, 0);
var afterChange = Instant.FromUtc(2024, 3, 1, 12, 0);
Assert.Equal(Offset.FromHours(6), zone.GetUtcOffset(beforeChange));
Assert.Equal(Offset.FromHours(5), zone.GetUtcOffset(afterChange));
Kaynaklar
- IANA Time Zone Database — Güncel: 2026b
- ISO 8601 (Wikipedia)
- timeanddate.com
- CGPM Resolution 4 (2022) — Leap second kararı
- Windows TZ Updates
- TZ Kısaltmaları (Wikipedia)