Gerçek zamanı yakalamak.

by pexels.com

Edebi bir yazı paylaşacakmış gibi bir başlık olsa da maalesef öyle olmayacak. Size NTP Client hakkında bahsedeceğim :)

NTP (Network Time Protocol) Türkçesi Ağ Zaman Protokolü olan protokol sayesinde kullanıcının cihazından bağımsız olarak gerçek zamanı yakalayabiliyoruz.

Buraya bir Wikipedia linki koymak isterdim ancak artık onu bırakın akademik kaynakçalardan bile çıkarmak zorunda kalıyor şu günlerde birçok insan, çünkü erişimi engellendi.

Size yine bir Wikipedia açıklamasıyla gelmem mümkün tabii ki:

Network Time Protocol. NTP Network Time Protocol’ün kısaltmasıdır. Türkçesi Ağ Zaman Protokolü’dür. NTP, değişken gecikmeye sahip paket anahtarlamalı ağlar üzerindeki bilgisayarların saatlerinin eş zamanlanmasının sağlanması için kullanılan bir protokoldür.

Neden böyle bir şeye ihtiyaç duyuyoruz? Olması gerekli mi?

Geliştirme kitlerinde mevcut Date() class ile ne yaparsanız yapın telefonun lokal saatini referans olarak elde edebilirsiniz. İster bir date formatter kullanın, isterseniz timezone UTC veya lokalizasyon bilgisi verin. Bu durumu yanlış referans lokal saatiniz olduğundan değiştiremeyeceksiniz.

Bu durumu değiştiremediğiniz için, bir kullanıcı gidip cihazın saatini ileri veya geri aldığında, sizin elde ettiğiniz yanlış zaman bilgisi sunucunuza o şekilde gidecek ve işler karışacak. Eğer zamanı ölçmeye ve ona göre yetkilendirme yapmaya dayalı bir uygulamaysa, UTC kullanmanın dışında bu durumu kaçırmak, sonucunda daha kötü şeyleri doğurabilir.

Neler yapabiliriz?

NTP Client ile bir veya birkaç sunucuyu referans alarak zaman senkronu yapılması gerekli. Bunun için GitHub da open source olarak bulabileceğiniz kütüphaneleri ürünlerinizde kullanabilirsiniz. Lyft’in yayınladığı Kronos Swift 3 ve iOS 10 ile tam uyumla çalışıyor. time.apple.com ve sunucu havuzu ile önce senkron yaptıktan sonra Clock.now() ile gerçek zamanı Date formatında UTC olarak yakalayabilirsiniz.

Clock.sync { date, offset in
print(date)
}
// then
print(Clock.now)

Öneri olarak optional Date? tipinde bir değişkene 1.0 timer ile sürekli .now() kullanarak atamanız önerilmiş. Optional chaning ile de bu değişkeni ihtiyacınız olduğunda string dönüşümüyle kullanabilirsiniz.

if let dateNow = Clock.now {
    print(dateNow) // 2017-05-01 4:19:43 PM +0000
    let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd"
formatter.timeZone = TimeZone(abbreviation: "UTC")
    // UTC TIME WORLD (NOW)
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
let DATE_TIME_UTC = formatter.string(from: dateNow)
dateTimeUTC = DATE_TIME_UTC
    // RETURNS LOCAL TIME (NOW)
formatter.timeZone = TimeZone.current
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
let localTimeString = formatter.string(from: dateNow)
    print(localTimeString) // 2017-05-01 19:19:44 +0300
}

Elde ettiğiniz Date? UTC formatında, yani +0000 olarak gelecektir. Bunu formatter kullanarak timeago halinde label oluşturabilmeniz mümkün olacaktır. Bunu daha önce açıkladığım şuradaki yazıdan ulaşabilirsiniz.

Daha detaylı örnekler için GitHub Gist dosyamı inceleyebilirsiniz.

Ek olarak belirtmeliyim ki telefon ayarlarından elle yanlış timezone seçimi durumunda GPS kullanmadan düzeltme yapabileceğiniz bir şey görünmüyor. NTP Client kullanarak server zamanıyla gerçek UTC bilgisini database üzerine kayıt edebilirsiniz. Ancak o tarihi bulunduğunuz dilime göre yorumlama meselesi yine seçili timezone bölgesine göre olacaktır.

Ayrıca Firebase servisini kullanıyorsanız server üzerinden timestamp değerine ulaşabilirsiniz. Bunu bir node üzerine sürekli kayıt edip ihtiyacınız olduğunda single observer kullanarak Date? tipinde alabilmenizin mümkün olabilir. Bu sizin tercihinize kalmış.

FirebaseServerValue.timestamp()

Firebase hakkında detaylı açıklamayı da şurada bulunan yanıtta bulabilirsiniz.

DateFormatter hakkında farklı parametreler için şuradaki yanıtı inceleyebilirsiniz.

Saat dilimleriyle uğraşmak bana keyifli gelmiştir. 
Bu yazının faydalı olması dileğiyle..