“Saat kaç?”

Anıl Tangül
Linktera
Published in
4 min readJun 19, 2018
Photo by Brooke Campbell on Unsplash

Aslında bu yazının başlığı “Yazılım & Bilişim Dünyası’nda Zaman ve Zaman Dilimi (Time Zone) Kavramlarıyla Çalışmak” şeklinde olacaktı, ancak öyle olursa hem çok uzun olduğu hem de daha ilk paragrafı okumadan geçilecek sıkıcı bir yazı hissi vereceği için bu haliyle güncelledim. Bu açıklamanın ardından, her ne kadar teknik bir yazı geleceği düşünülse de sadece yazılım geliştiricileri değil, analistler, bilgi yöneticileri, geniş bir coğrafi alanda faaliyet gösterecek yazılım sahipleri, kısaca zaman kavramının uygulamalarda kullanım halini merak eden herkes tarafından okunabileceğini belirtmek isterim. ☺

Sadece 1 tane “şu an” var!

Bildiğiniz gibi, aynı anda sorulan “Saat kaç?” gibi basit bir soruya insanlar farklı coğrafyalarda farklı cevaplar veriyorlar. Sadece 1 tane şu an olmasına rağmen bu sorunun doğru cevabı İstanbul’da 17:00 iken, Tokyo’da 23:00, New York’ta 10:00 olabiliyor. Bu farkın temel sebebi Dünya’nın şekli ve günlük hareketi sonucunda insanoğlunun Zaman Dilimi (Time Zone) kavramını uygulamaya koyması. Hatta mevsim geçişlerinde bu sabit gibi görünen zaman farkları yine değişebiliyor ve iki şehir/ülke/bölge arasındaki saat farkı da yıl içindeki zamanlara göre sabit kalmayabiliyor. Aslında temelinde basit kalması gereken zaman konusu bilgi teknolojileri dünyasında, kullanıcı tercihleri (user profiles), tarayıcı varsayılanları (browser defaults), istek başlıkları (request headers), oturum bilgileri (session data), ortam / sistem değişkenleri (environment / system variables) gibi parametreler hesaba katılmaya başlandığında karmaşık bir hal alıyor. Dürüstçe belirtmem gerekirse bu karmaşıklığın sağlıklı bir şekilde çözülemediği birçok uygulama ve servisle karşılaştım. Örnekleme “İstanbul’da yaşayan bir kullanıcının saat 17:00'de gerçekleştirdiği bir işlemin saatini, Tokyo’da yaşayan bir kullanıcı nasıl görmeli?” sorusuyla başlıyor. Aslında UX konusunun da devreye girdiği “İstanbul’da yaşayan bir kullanıcının saat 17:00'de gerçekleştirdiği bir işlemin saatini, Tokyo’da iş gezisinde bulunan New York’lu bir kullanıcı, işlemin gerçekleştirildiği yerel bilgiyle birlikte nasıl görmeli?” sorusuyla devam ediyor. Örnekte belirtilen işlem sadece 1 kez gerçekleşti ama bu olayın zamanını doğru olarak kaydetmek ve raporlamak neden bu kadar karmaşık? (Ya da gerçekten karmaşık mı?)

Aslında karmaşık değil, temel nitelikteki kavramlardan bahsediyoruz. Sadece günlük yaşamda çok anlaşılır ve pratik olan “Saat kaç?” sorusunun bilgi sistemlerindeki sağlıklı açılımını şu şekilde ele alırsak resim biraz daha netleşiyor:

  1. Saat UTC olarak kaç?
    UTC (Coordinated Universal Time | Eş Güdümlü Evrensel Zaman): Bilgi sistemlerinde kullanılan günlük tüm zaman problemlerini çözmek amacı taşıyan, zaman diliminin etkisinin olmadığı, yaz saati uygulamasından (daylight saving time) etkilenmeyen şahane bir bilimsel zamandır.
  2. Bu soru hangi zaman dilimi için soruldu?
  3. Soruyu soran kişinin zaman dilimi nedir?

Görüldüğü gibi aslında “Saat kaç?” sorusu atomik değil. :)
Dolayısı ile bu 3 soru ve cevabını, özellikle uluslararası kullanıma açık (uluslararası kullanım potansiyeli taşıyan, hedefleyen) sistemler için her zaman hesaba katmalıyız. Localization (L10n — yerelleştirme) ve Internationalization (I18n — uluslararasılaştırma) kavramları bir bütün olarak ele alınması gereken konular ancak şimdi bu ana başlıklar altındaki zamansal değerler yönetimi için bir kaç yöntem önerisi üzerine konuşabiliriz.

Bilişim dünyasındaki tüm uygulamalar/sistemler, kendilerine sorulan zaman sorularına her zaman, her coğrafi bölgede ve her bir kullanıcısı için tutarlı ve doğru cevap vermek zorunda. Aksi durumda sağladığı temel özellikler ve avantajlar açısından bile sıkıntıya düşebilirler.

Global kaydet, yerel görüntüle!

İşte en anlaşılır ve sağlam çözümlerden biri bu. Zaman değerlerini global olarak kaydet ve görüntülerken/sunarken/raporlarken kullanıcının görmek istediği zaman dilimini kullan. Hatta bunları yaparken asıl işlemin yapıldığı zaman dilimi bilgisini de kaybetme. Bu yöntemde:

  • Zaman bilgisini mutlaka UTC olarak kaydedin —Tablo1
    (Bazı önemli sistemlerde 1 Ocak 1970'ten beri geçen milisaniye olarak sayı değeri tutulduğunu, son derece problemsiz yönetilebildiğini bile gördüm)
  • Tüm kullanıcılarınızın profillerinde zaman dilimi bilgilerini kaydedin — Tablo 2
  • Uygulamanızı çalıştırdığınız tüm sistem bileşenlerinin (işletim sistemi, ortam, framework, runtime, veritabanı gibi) varsayılan TimeZone değeri UTC olsun
  • Opsiyonel — İşlemin gerçekleştiği zaman dilimini kaydedin
    (Özellikle işlemin gerçekleştiği coğrafi yer önemliyse ve diğer kullanıcılar için geçerliliği olan bir veriyse saklayabilirsiniz)
  • Opsiyonel — İşlemin gerçekleştiği zaman dilimindeki yerel zamanı kaydedin
    (Yine bir önceki maddedeki gibi opsiyonel bir veri olmakla birlikte bazı istatistiki çalışmalar için gerekli olabilecek bir bilgi olabilir, örneğin “Bu işlem günün hangi saatlerinde yapılıyor?” sorusunun cevabı yerel zaman veri üzerinden verildiğinde daha fazla anlam taşıyabilir)
Tablo 1: Örnek bir İşlem domain objesi veya veritabanı tablosu
Tablo 2: Örnek bir Kullanıcı domain objesi veya veritabanı tablosu

Yazılımla ilgili olan tüm ortam bileşenlerinin mutlaka kendine ait zaman dilimi varsayılanları var! Veritabanı, framework, platform, işletim sistemi, geliştirme ortamı gibi… Bunların birbirini etkileyebileceklerinin farkında olmakta ve doğru olarak ayarlandığından emin olmakta fayda var.

… ve kod konuşur!

Alt örnekteki (Kod1) bir parça Java koduyla zamansal değerlerin uygulamalar seviyesindeki durumunu biraz daha net olarak açıklamaya çalışacağım.

Bu örneklerde UTC, 1 Ocak 1970, milisaniye, TimeZone, System saati, Local time, hatta Date Formatting gibi kavramları bir arada kullanıp tam olarak ne olduklarını göstermeyi hedefliyorum. En ufak bir kafa karışıklığınız varsa kod örnekleri ve çıktılarını detaylı incelemekten çekinmeyin.

Kod 1: Java’da Zaman ve Zaman dilimi kavramları

Bu Java kodunu derleyip, hiç bir değişiklik yapmadan JRE’nizde çalıştırdığınızda timezone değeri UTC olarak verildiği için (bu saat diliminde yaşamadığınızı varsayarak) kol saatinize baktığınızda gördüğünüz değerlerden farklı değerler göreceksiniz. Yaratılan Date nesnesi, her zaman 1 Ocak 1970 00:00'dan itibaren geçen milisaniye değerlerini (Long tipinde) tutar. Sistem saati de bu değerle aynı sonucu verir. Sistem saatinin de okunabilir (readable) hali de Java Date nesnesinin çıktısına eşittir.

java.util.Date           : Mon Apr 30 17:09:17 UTC 2018
java.util.Date - fmtd : 2018-04-30T17:09:17.308Z UTC
java.util.Date.getTime() : 1525108157308
System.currentTimeMillis : 1525108157308
Sys CTM readable format : 17651. day, 17:09:17.308
User TimeZone : UTC

Aynı kodun, sadece zaman diliminin UTC olarak ayarlandığı 10. satırı silindiğinde ya da yorum satırı içine alındığındaki çıktısına bakıldığında ise artık timezone değeri varsayılan (lokal, Asia/Istanbul) şekilde belirlenmiş olur. Zaman nesnesi içindeki yine aynı long tipinde milisaniye değerini tutmasına rağmen çıktısı farklıdır. Formatlanmış zaman çıktısındaki +03:00 değeri bu farkın nedenini belirtir. Bu örnekte ise dikkat edilecek detay sistem saatinin yine UTC olarak yer almasıdır, ancak tüm uygulama çıktıları timezone değerini dikkate alır.

java.util.Date           : Mon Apr 30 20:09:09 EET 2018
java.util.Date - fmtd : 2018-04-30T20:09:09.057+03:00 EET
java.util.Date.getTime() : 1525108149057
System.currentTimeMillis : 1525108149057
Sys CTM readable format : 17651. day, 17:09:09.057
User TimeZone : Asia/Istanbul

Hazır Java kodu ile örneklemeler yapmışken, Java 8 özelinde bazı faydalı kullanımlar için aşağıdaki bağlantıyı paylaşabilirim:
https://www.javacodegeeks.com/2018/03/java-8-date-and-time.html

Unutmayın ki, yazılım/sistem tasarımında bazı temel noktaların gözden kaçması büyük geçiş maliyetleri yaratabilir. Bu temel noktalardan birinin de “zaman kavramıyla çalışmak” olduğunu söyleyebiliriz.

Her türlü soru, öneri ve katkılarınız için şimdiden teşekkürler.

Sonuna kadar okuyanlara sorunsuz günler dilerim. ☺

--

--

Anıl Tangül
Linktera

İngiltere kralı, rahmetli başkan Kenedi, taçsız kral Pele, Bakenbauer, kaleci Mıyer, Nadya Komanaçi, Biricik Bardo ve Fenerbahçeli Cemil'in de okuduğu adam.