Unix Timestamp UTC Açıklandı: Saat Dilimleri, Ofsetler ve Dönüşümler

UTC saat dilimi çizgileri ve Unix zaman damgasıyla birden fazla yerel saate bağlanan dünya haritası

Bir veritabanında tarih sakladıysan, API geliştirdiysen ya da yalnızca belirli ülkelerde ortaya çıkan bir zamanlama hatasını debug ettiysen, büyük ihtimalle Unix timestamp UTC ile yerel saat arasındaki ilişkiyle karşılaşmışsındır. Bu kafa karışıklığı gerçek ve production ortamında ciddi hatalara yol açıyor. Bu yazıda UTC'nin tam olarak ne olduğunu, Unix timestamp'lerin neden varsayılan olarak UTC'ye göre tanımlandığını, timezone offset'lerinin nasıl çalıştığını ve JavaScript, Python ile PHP'de timestamp dönüşümlerini doğru şekilde nasıl yapacağını ele alacağız. Ayrıca geliştiricilerin en sık yaptığı hataları ve bunlardan nasıl kaçınacağını da bulacaksın.

Temel Çıkarımlar:

  • Bir Unix timestamp her zaman 1 Ocak 1970, 00:00:00 UTC'den itibaren geçen saniyeleri sayar - içinde herhangi bir timezone bilgisi taşımaz.
  • UTC evrensel referans noktasıdır; yerel saat ise UTC'ye offset eklenmesi ya da çıkarılmasıyla elde edilir.
  • Bir timestamp'i yerel saate doğru şekilde dönüştürmek için yalnızca offset sayısını değil, hedef timezone'u bilmen gerekir.
  • DST (Yaz Saati Uygulaması) bir timezone'un offset'ini değiştirir - bu yüzden offset'i kodun içine sabit yazman hatalara yol açar.

UTC Nedir ve Neden Önemlidir?

UTC, Koordineli Evrensel Zaman anlamına gelir (Coordinated Universal Time). Dünyanın saatlerini ve zamanını düzenlemek için kullanılan temel zaman standardıdır. Timezone'ların aksine UTC'nin herhangi bir offset'i yoktur - sıfır noktasının kendisidir. Yaz saati uygulamasına tabi değildir ve hiçbir ülke ya da bölge için kaymaz.

UTC'den önce GMT (Greenwich Mean Time) kullanılıyordu ve pek çok kişi hâlâ bu iki terimi birbirinin yerine kullanıyor. Teknik olarak UTC ile GMT arasında küçük bir fark bulunsa da yazılım geliştirme açısından ikisi genellikle eşdeğer kabul edilir. UTC, ITU-R TF.460 tavsiyesiyle resmi olarak tanımlanmış olup atom saatleri aracılığıyla korunmaktadır.

Geliştiriciler için UTC'nin önemi şuradan geliyor: tek ve kesin bir referans noktası sağlar. Frankfurt'taki sunucun ve Los Angeles'taki kullanıcın bir olayı UTC kullanarak kaydettiğinde, iki timestamp'i her zaman doğru şekilde karşılaştırabilirsin. Her ikisi de metadata olmadan yerel saatiyle kaydettiğinde ise ciddi bir sorun baş gösterir.

Unix Timestamp'ler Neden Her Zaman UTC'dir?

Bir Unix timestamp (epoch time ya da POSIX time olarak da bilinir), 1 Ocak 1970, 00:00:00 UTC'den bu yana geçen saniye sayısı olarak tanımlanır. Bu başlangıç noktası - UTC'de 1 Ocak 1970 geceyarısı - tanımın içine işlenmiştir. New York yerel saatinden ya da Tokyo yerel saatinden başlayan bir Unix time versiyonu yoktur.

Bu da "Unix timestamp her zaman UTC midir?" sorusunun cevabının tanım gereği evet olduğu anlamına gelir. 1700000000 sayısı, dünyanın her yerindeki her kullanıcı için tam olarak aynı anı temsil eder. Kullanıcılar arasında değişen tek şey, o anın kendi yerel timezone'larında nasıl gösterildiğidir.

Bu kavramın temelini daha ayrıntılı anlamak için Epoch Time: Unix Timestamp'lerin Temeli başlıklı yazımıza göz atabilirsin.

Unix time'ın UTC'ye dayalı bu tasarımı, en kullanışlı özelliklerinden biridir. Sayının kendisi timezone bilgisi taşımadığından, farklı ülkelerdeki iki sistem bir timestamp alışverişi yaptığında herhangi bir ek anlaşmaya gerek kalmadan hangi anı ifade ettiğini tam olarak bilirler.

UTC ile Yerel Saat ve Timezone Farkı

UTC referans noktasıdır. Yerel saat ise bu referansın üzerine bir timezone kuralı uygulandığında elde ettiğin sonuçtur. Bir timezone, yalnızca sabit bir offset değildir - zamanla değişebilen kurallar bütününe sahip, adlandırılmış bir bölgedir (bu değişiklikler çoğunlukla Yaz Saati Uygulaması nedeniyle gerçekleşir).

Örneğin, Amerika Birleşik Devletleri'ndeki "Eastern Time" kışın UTC-5, yazın ise UTC-4'tür. Timezone adı, çoğu programlama dili ve işletim sistemi tarafından kullanılan timezone kuralları için yetkili kaynak olan IANA timezone veritabanında "America/New_York" olarak geçer.

Pratik sonuç şudur: veritabanında bir Unix timestamp sakladığında UTC değeri saklıyorsun demektir. Bunu kullanıcıya gösterirken ise kendi yerel timezone'una dönüştürürsün. Yerel saati ham bir sayı olarak saklayıp bunun UTC olduğunu asla varsayma. Hatalar tam da buradan başlar.

UTC Offset'ler Nasıl Çalışır?

UTC offset, bir timezone'un UTC'den ne kadar uzakta olduğunu gösterir. +HH:MM ya da -HH:MM biçiminde yazılır. Bazı örnekler:

  • UTC+02:00 - Orta Avrupa Yaz Saati (CEST), Almanya ve Fransa'da yaz aylarında kullanılır.
  • UTC-05:00 - Doğu Standart Saati (EST), kışın ABD Doğu Kıyısı'nda kullanılır.
  • UTC+05:30 - Hindistan Standart Saati (IST), yarım saatlik bir offset içerir.
  • UTC+00:00 - UTC'nin kendisi; kışın Birleşik Krallık'ta da kullanılır (GMT).

Bir UTC epoch time'ı manuel olarak yerel saate dönüştürmek için offset'i saniye cinsinden ekler ya da çıkarırsın. UTC+02:00 için bu 2 * 3600 = 7200 saniyedir. Yani Unix timestamp'in 1700000000 ise, UTC+02:00'deki yerel saat, biçimlendirmeden önce 1700000000 + 7200'e karşılık gelir.

Ancak bunu manuel yapmak risklidir çünkü offset'ler DST ile birlikte değişir. Offset'i kodun içine sabit yazmak yerine her zaman uygun bir timezone kütüphanesi kullan. Dönüşüm yöntemlerine daha ayrıntılı bakmak için Unix Timestamp'i Tarihe Dönüştürme rehberimize göz atabilirsin.

Unix Timestamp'i Yerel Saate Dönüştürme

Somut bir örnek üzerinden gidelim. 1700000000 Unix timestamp'i 14 Kasım 2023, 22:13:20 UTC'ye karşılık gelir. Bunu üç farklı dilde "America/New_York" timezone'una (Kasım ayında UTC-5) dönüştüreceğiz.

JavaScript

const ts = 1700000000;

// JavaScript Date milisaniye alır
const date = new Date(ts * 1000);

// New York yerel saatinde göster
const options = {
  timeZone: 'America/New_York',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  timeZoneName: 'short'
};

console.log(date.toLocaleString('en-US', options));
// Çıktı: November 14, 2023 at 05:13:20 PM EST

JavaScript'teki Date nesnesi zamanı dahili olarak UTC milisaniye cinsinden saklar. timeZone seçeneğiyle kullanılan toLocaleString metodu, offset ve DST kurallarını senin adına yönetir.

Python

from datetime import datetime, timezone
import zoneinfo  # Python 3.9+

ts = 1700000000

# Timestamp'ten UTC'ye duyarlı bir datetime oluştur
utc_dt = datetime.fromtimestamp(ts, tz=timezone.utc)

# New York yerel saatine dönüştür
ny_tz = zoneinfo.ZoneInfo('America/New_York')
local_dt = utc_dt.astimezone(ny_tz)

print(local_dt.strftime('%Y-%m-%d %H:%M:%S %Z'))
# Çıktı: 2023-11-14 17:13:20 EST

Buradaki kritik nokta datetime.fromtimestamp(ts, tz=timezone.utc) kullanımıdır. tz argümanını atlarsanız Python, timestamp'i yorumlamak için sunucunun yerel timezone'unu kullanır - bu da yaygın bir hata kaynağıdır.

PHP

$ts = 1700000000;

// Unix timestamp'ten (her zaman UTC) bir DateTime nesnesi oluştur
$dt = new DateTime('@' . $ts);

// Hedef timezone'u ayarla
$dt->setTimezone(new DateTimeZone('America/New_York'));

echo $dt->format('Y-m-d H:i:s T');
// Çıktı: 2023-11-14 17:13:20 EST

PHP'de DateTime nesnesi oluştururken kullanılan @ öneki, PHP'ye bu değeri Unix timestamp (UTC) olarak işlemesini söyler. Bu önek olmadan PHP, string'i sunucunun varsayılan timezone ayarına göre yorumlayabilir.

Geliştiricilerin Sık Yaptığı Hatalar

Deneyimli geliştiriciler bile timezone yönetiminde tökezleyebilir. İşte en sık karşılaşılan sorunlar:

1. Sunucunun yerel saatinin UTC olduğunu varsaymak

Sunucun "Europe/Berlin" olarak ayarlıysa ve timezone argümanı olmadan PHP'de time() ya da Python'da datetime.now() çağırırsan, UTC değil yerel saat alırsın. Timestamp kaydederken her zaman UTC'yi açıkça belirt.

2. Timezone adı yerine UTC offset'ini sabit kodlamak

Almanya için +02:00'yi sabit offset olarak kullanmak, Almanya'nın +01:00'e geçtiği kış aylarında hatalara yol açar. Kütüphanenin DST kurallarını otomatik uygulayabilmesi için her zaman Europe/Berlin gibi adlandırılmış timezone'lar kullan.

3. Timestamp'leri timezone metadata'sı olmadan yerel saat string'i olarak saklamak

Veritabanındaki 2023-11-14 17:13:20 gibi bir string belirsizdir. UTC mi? EST mi? IST mi? Timestamp'leri Unix integer olarak ya da UTC offset içeren ISO 8601 string'i olarak (örn. 2023-11-14T22:13:20Z) saklarsan anlam kesin olur. Hangisini seçmen gerektiğine dair Unix Timestamp Formatı ile ISO 8601 Karşılaştırması yazımıza bakabilirsin.

4. Zamanlama işlemlerinde DST'yi göz ardı etmek

Son çalışma zamanına 86400 saniye ekleyerek "her gün 09:00'da" bir iş çalıştırmayı zamanlarsanız, DST değişikliği olan günlerde bir saat kayması yaşanır. Timezone kurallarını anlayan bir cron kütüphanesi ya da zamanlayıcı kullan.

5. Milisaniye ile saniyeyi karıştırmak

JavaScript'in Date nesnesi milisaniye kullanır, ancak çoğu Unix timestamp saniye cinsindendir. Saniye tabanlı bir timestamp'i 1000 ile çarpmadan new Date()'e geçirirsen Ocak 1970'te bir tarih elde edersin. Bu konu, Saniye, Milisaniye ve Mikrosaniye yazımızda ayrıntılı olarak ele alınmaktadır.

Sonuç

Unix timestamp'ler ve UTC, tasarım gereği birbirinden ayrılamaz. Timestamp her zaman bir UTC değeridir - sabit bir UTC başlangıç noktasından itibaren sayılan saniyelerdir. Yerel saat ise farklı bir timestamp türü değil, yalnızca bir görüntüleme biçimidir. En güvenli yaklaşım her şeyi UTC olarak saklamak, yerel saate yalnızca gösterim noktasında dönüştürmek ve sabit offset'ler yerine her zaman adlandırılmış timezone'lar kullanmaktır. Bu kurallara uyduğunda timezone kaynaklı hataların büyük çoğunluğu kendiliğinden ortadan kalkar. Bu değerleri saklama konusundaki en iyi uygulamalar için Veritabanlarında Unix Timestamp rehberimize göz atabilirsin.

unixtimestamp.app ile Unix timestamp'i UTC veya yerel saate dönüştür

Herhangi Bir Unix Timestamp'i UTC veya Yerel Saate Anında Dönüştür

Herhangi bir Unix timestamp'i yapıştır, tek tıkla UTC ve yerel timezone'una dönüştürülmüş halini gör. Ücretsiz, kayıt gerektirmez; saniye ve milisaniye ile çalışır.

Ücretsiz Aracı Dene →

Evet. Tanım gereği, bir Unix epoch timestamp 1 Ocak 1970, 00:00:00 UTC'den itibaren geçen saniyeleri sayar. Sayının kendisi herhangi bir timezone taşımaz - bir UTC değeridir. Timezone yalnızca timestamp'i görüntüleme amacıyla okunabilir bir tarih ve saate dönüştürdüğünde devreye girer.

Kullandığın dilin yerleşik timezone kütüphanesini kullan. JavaScript'te timeZone seçeneğiyle toLocaleString kullan. Python'da adlandırılmış bir timezone ile datetime.fromtimestamp(ts, tz=timezone.utc).astimezone() kullan. PHP'de timestamp'ten bir DateTime oluştur ve setTimezone() çağır. Her zaman ham offset yerine adlandırılmış timezone kullan.

Bu durum genellikle bir fonksiyonun timestamp'i yorumlarken UTC yerine sunucunun varsayılan timezone'unu kullanmasından kaynaklanır. Python'da datetime.fromtimestamp()'e tz argümanı vermemek sistem yerel saatini kullanır. PHP'de @ önekini kullanmamak da aynı sonucu doğurur. Oluşturma noktasında her zaman UTC'yi açıkça belirt.

UTC offset, bir timezone'un UTC'nin kaç saat (bazen dakika) önünde ya da gerisinde olduğunu gösterir. Örneğin UTC-05:00, UTC'nin beş saat gerisindedir. Bir Unix timestamp'i yerel saate dönüştürürken offset, UTC değerine uygulanır. Offset'ler DST ile değiştiğinden, sabit bir offset kodlamak yerine adlandırılmış timezone kullanman gerekir.

Evet, ve bu Unix timestamp'lerin en büyük avantajlarından biridir. Her timestamp bir UTC değeri olduğundan, herhangi iki timestamp'i doğrudan integer olarak karşılaştırabilirsin. Daha büyük bir sayı her zaman daha sonraki bir anı ifade eder; timestamp'lerin nerede üretildiğine bakılmaksızın. Karşılaştırma için herhangi bir timezone dönüşümüne gerek yoktur.