Unix Zaman Damgaları Açıklaması
Unix zaman damgası, bir anı tek bir sayıyla ifade eder. Saklaması ve karşılaştırması kolaydır, ancak birimler, saat dilimleri ve metin biçimleri birçok dönüştürme hatasına yol açar.
Unix Zamanı Nedir?
Unix zamanı (epoch zamanı veya POSIX zamanı olarak da bilinir), Unix epoch'u olan 1970-01-01 00:00:00 UTC anından bu yana geçen saniyeleri sayar. 0 epoch'un kendisidir, 1700000000, 2023-11-14 22:13:20 UTC anına karşılık gelir ve negatif değerler 1970'ten önceki anları gösterir: -1, 1969-12-31 23:59:59 UTC anıdır.
Sayı saat dilimi içermez: her yerde aynı anı tanımlar; bu da onu olayları saklamak, sıralamak ve karşılaştırmak için pratik kılar.
Unix zamanı artık saniyeleri yok sayar: her gün tam olarak 86.400 saniyedir. UTC'ye bir artık saniye eklendiğinde sistemler bir saniyeyi tekrarlar ya da onu daha uzun bir süreye yayar ("smearing"); bu yüzden artık saniyeyi kapsayan bir zaman farkı, fiziksel olarak geçen süreden bir saniye kısadır.
Saniye, Milisaniye, Mikrosaniye mi, Nanosaniye mi?
Birçok sistem daha küçük birimlerle sayar ve sayının kendisi hangi birim olduğunu söylemez. Aynı an, birbirinden çok farklı dört sayı olarak görünebilir:
| Birim | 2023-11-14 22:13:20 UTC | Basamak (2001–2286) | Sık görüldüğü yerler |
|---|---|---|---|
| Saniye | 1700000000 |
10 | date +%s, birçok API, JWT exp talepleri |
| Milisaniye | 1700000000000 |
13 | JavaScript'te Date.now(), Java'da System.currentTimeMillis() |
| Mikrosaniye | 1700000000000000 |
16 | Bazı veritabanları ve günlük kayıt sistemleri |
| Nanosaniye | 1700000000000000000 |
19 | Go'da UnixNano(), Python'da time.time_ns() |
Basamakları saymak, güncel tarihler için en hızlı kontroldür. LeedyBox dönüştürücü de aynı fikri kullanır: 1011 değerine kadar olanlar saniye, 1014 değerine kadar olanlar milisaniye, 1017 değerine kadar olanlar mikrosaniye, daha büyük değerler ise nanosaniye olarak okunur. Bu pratik kural bugünden çok uzak tarihlerde işe yaramaz; bu yüzden bir sonuç tuhaf görünüyorsa birimi kontrol edin.
Hassasiyet de önemlidir. JavaScript sayıları tam sayıları yalnızca 253 değerine (yaklaşık 9 × 1015) kadar tam olarak gösterebilir; bu yüzden 1700000000123456789 gibi bir nanosaniye değeri normal bir sayı olarak ayrıştırıldığında son basamaklarını kaybeder. Bu tür değerleri dize olarak tutun veya BigInt kullanın; dönüştürücü bunu kendi içinde yapar. Bir belirtecin exp talebini okumak için belirteci Base64 / URL / JWT aracıyla çözün.
Saat Dilimleri ve Yaz Saati Uygulaması
Bir zaman damgasını tarih ve saat olarak göstermek için bir saat dilimi gerekir. Referans UTC'dir; yerel saat buna Seul'de +09:00 veya kışın New York'ta −05:00 gibi bir fark ekler.
Sabit farklar ve kısaltmalar yerine Asia/Seoul veya America/New_York gibi IANA saat dilimi adlarını tercih edin: bir ad, o dilimin geçmişini ve yaz saati kurallarını taşır; CST gibi bir kısaltma ise birkaç farklı dilimi ifade eder. Kurallar, yılda birkaç kez değişen saat dilimi veritabanından gelir. Tarayıcılar, işletim sistemleri ve programlama dilleri bu veritabanının kendi kopyalarını kullanır; bu yüzden geçmiş veya gelecek tarihler için sonuçlar farklı olabilir.
Yaz saati uygulaması, yerel bir saati zaman damgasına dönüştürürken iki zorlu durum yaratır:
- Boşluk: saatler ileri alındığında bazı yerel saatler hiç yaşanmaz.
America/New_Yorkdiliminde 2026-03-08 02:30 atlanır, çünkü saatler 02:00'den 03:00'e geçer. - Çakışma: saatler geri alındığında bazı yerel saatler iki kez yaşanır. 2026-11-01 01:30 bir kez EDT'de (UTC−04:00), bir saat sonra da yeniden EST'de (UTC−05:00) yaşanır.
Kütüphaneler bu durumları farklı şekillerde çözer. LeedyBox dönüştürücü bir boşlukta sonraki geçerli saati (burada 03:30), bir çakışmada ise ilk gerçekleşmeyi kullanır ve bunu bir notla açıklar. Zamanlanmış işler de aynı sorunla karşılaşır; bkz. Cron İfadeleri Nasıl Okunur?
ISO 8601, RFC 3339 ve HTTP Tarihleri
Bir anın okunabilir olması gerektiğinde onu ISO 8601 biçiminde ya da bu biçimin daha katı internet profili olan RFC 3339 biçiminde yazın:
2023-11-14T22:13:20Z
2023-11-15T07:13:20+09:00
2023-11-14T22:13:20.500Z
Z, UTC anlamına gelir. Z veya bir fark içeren dize belirsizlik taşımaz. 2023-11-14T22:13:20 gibi ikisini de içermeyen bir dize, bilinmeyen bir dilimdeki yerel saattir ve ayrıştırıcılar onu nasıl okuyacakları konusunda farklı davranır.
Last-Modified ve Expires gibi HTTP başlıkları, e-posta tarih biçiminden (RFC 2822, şimdi RFC 5322) türetilmiş, GMT ile yazılan daha eski bir biçim kullanır: Tue, 14 Nov 2023 22:13:20 GMT.
2038 Yılı Sorunu
Birçok eski sistem Unix zamanını işaretli 32 bitlik bir tam sayıda saklar. Bu tam sayının en büyük değeri olan 2147483647, 2038-01-19 03:14:07 UTC anına karşılık gelir. Bir saniye sonra sayaç taşarak -2147483648 değerine döner; bu değer de 1901-12-13 20:45:52 UTC olarak okunur. Güncel işletim sistemleri ve programlama dilleri çoğunlukla yüz milyarlarca yılı kapsayan 64 bitlik zaman değerleri kullanır, ancak 32 bitlik alanlar gömülü cihazlarda, dosya biçimlerinde, veritabanı sütunlarında ve ağ protokollerinde hâlâ karşımıza çıkar. Kodunuz veya verileriniz saniyeleri 32 bitte saklıyorsa değişikliği erkenden planlayın ve 2038 sonrasındaki tarihleri şimdiden test edin.
Kodda ve Veritabanlarında Zaman Damgaları
JavaScript milisaniyelerle çalışır:
Math.floor(Date.now() / 1000); // saniye cinsinden geçerli Unix zamanı
new Date(1700000000 * 1000).toISOString(); // "2023-11-14T22:13:20.000Z"
Date.parse("2026-10-03T09:00:00+09:00") / 1000; // 1790985600
Python'da time.time() saniyeleri ondalıklı sayı (float) olarak döndürür. tz=timezone.utc parametresini verin; aksi takdirde fromtimestamp() bilgisayarın yerel saatini saat dilimi bilgisi olmadan döndürür:
import time
from datetime import datetime, timezone
int(time.time()) # saniye
datetime.fromtimestamp(1700000000, tz=timezone.utc) # 2023-11-14 22:13:20+00:00
datetime.fromisoformat("2026-10-03T09:00:00+09:00").timestamp() # 1790985600.0
SQL'de işlevler veritabanına göre değişir:
-- PostgreSQL
SELECT extract(epoch FROM now()); -- saniye, kesirli
SELECT to_timestamp(1700000000); -- timestamp with time zone
-- MySQL
SELECT UNIX_TIMESTAMP();
SELECT FROM_UNIXTIME(1700000000); -- oturumun saat diliminde
Saklama konusunda birkaç alışkanlık çoğu sorunu önler:
- Gerçekleşmiş anları UTC olarak saklayın: ya saat dilimli bir zaman damgası (timestamp with time zone) sütununda ya da birimi sütun adında belirtilen 64 bitlik bir tam sayı olarak, örneğin
created_at_ms. - Seul'de saat 09:00'daki bir toplantı gibi gelecekteki yerel etkinlikleri yerel tarih ve saat ile IANA dilim adı olarak saklayın ve zaman damgasını gerektiğinde hesaplayın; böylece sonradan yapılan bir kural değişikliği toplantıyı kaydırmaz.
- Bir sütunda birimleri karıştırmayın; yanlış birim, değeri 1.000 kat veya daha fazla saptırır.
Sık Sorulan Sorular
Zaman damgam neden 1970'te bir tarihe dönüşüyor?
Değer büyük olasılıkla yanlış birimle okunmuştur: milisaniye olarak okunan saniyeler Ocak 1970'e düşer, saniye olarak okunan milisaniyeler ise on binlerce yıl sonrasına gider. Basamakları sayın veya dönüştürücüde birimi seçin.
Unix zaman damgası saat dilimime bağlı mı?
Hayır. UTC'deki sabit bir andan itibaren geçen saniyeleri sayar. Yalnızca bu değer için gösterilen tarih ve saat, saat dilimine bağlıdır.
Unix zamanı artık saniyeyi gösterebilir mi?
Hayır. Unix zamanı her günü 86.400 saniye olarak kabul eder; bu yüzden 23:59:60 gibi bir UTC zamanının kendine ait bir zaman damgası yoktur.