Ders 21 / 21
Tarih ve Zaman
Zaman damgası modeli, yerel saat ile eşgüdümlü evrensel zaman ayrımı, ayrıştırma tuzakları, tarih aritmetiği ve yerel ayarlı biçimlendirme.
İçindekiler
Ölçüm kayıtları bu derse kadar zamansızdı: hangi okumanın ne zaman alındığı bilinmiyordu. Bu ders zaman gösterimini ekliyor ve kursu kapatıyor.
Tarih–zaman, dilin en çok yanlış kullanılan alanıdır. Nedeni tek bir karışıklıktır: bir an ile o anın bir gösterimi aynı şey değildir. Bu ders ayrımı kurar ve tuzakları o ayrımdan türetir.
Aşağıdaki örneklerin çıktısı çalıştırıldığı makinenin saat dilimine bağlıdır. Yeniden üretilebilir olması için hepsi saat dilimi açıkça verilerek çalıştırılmıştır:
TZ=Europe/Istanbul node olcum.mjs
Zaman Damgası
Bir tarih nesnesinin taşıdığı tek veri, sabit bir başlangıç anından itibaren geçen milisaniye sayısıdır. Bu sayı zaman damgasıdır ve saat diliminden bağımsızdır.
const damga = 1709287200000; const t = new Date(damga); console.log(t.getTime()); console.log(t.toISOString()); console.log(Number(t) === damga);
1709287200000 2024-03-01T10:00:00.000Z true
Aynı betik başka bir saat diliminde çalıştırıldığında bu üç satır değişmez. Damga bir andır; ISO gösterimi de eşgüdümlü evrensel zamana göre yazıldığı için sabittir.
Nesne sayı bağlamında damgasına çevrilir; bu, tarih aritmetiğinin temelidir.
Yerel Saat ve Evrensel Zaman
Okuma yöntemleri iki ailededir. Adında UTC geçenler evrensel zamana, geçmeyenler
makinenin yerel saat dilimine göre değer verir:
const t = new Date(1709287200000); console.log("ISO :", t.toISOString()); console.log("yerel yil:", t.getFullYear(), "ay:", t.getMonth(), "gun:", t.getDate()); console.log("yerel saat:", t.getHours()); console.log("UTC saat :", t.getUTCHours()); console.log("fark(dk) :", t.getTimezoneOffset());
TZ=Europe/Istanbul ile:
ISO : 2024-03-01T10:00:00.000Z yerel yil: 2024 ay: 2 gun: 1 yerel saat: 13 UTC saat : 10 fark(dk) : -180
TZ=UTC ile aynı betik, yerel saat satırında 10 ve fark satırında 0 verir; diğer
satırlar değişmez.
İki tuzak burada birleşir. Birincisi, ay numarası sıfırdan başlar: mart ayı 2
değerini verdi. Gün ve yıl ise birden başlar. Bu tutarsızlık dilin ilk halinden gelir ve
geriye dönük uyumluluk nedeniyle korunmuştur.
İkincisi, saat dilimi farkının işareti terstir: evrensel zamandan üç saat ileride
olan bir dilim -180 verir. Değer, yerel saatten evrensel zamana gitmek için eklenmesi
gereken dakika sayısıdır.
Ayrıştırma Tuzağı
Metinden tarih üretmek, biçime göre farklı saat dilimi varsayar:
const bicimler = [ "2024-03-01T10:00:00Z", "2024-03-01T10:00:00", "2024-03-01", "2024-03-01T10:00:00+03:00", ]; for (const m of bicimler) { console.log(m.padEnd(26), new Date(m).toISOString()); }
TZ=Europe/Istanbul ile:
2024-03-01T10:00:00Z 2024-03-01T10:00:00.000Z 2024-03-01T10:00:00 2024-03-01T07:00:00.000Z 2024-03-01 2024-03-01T00:00:00.000Z 2024-03-01T10:00:00+03:00 2024-03-01T07:00:00.000Z
Dört satır dört farklı kural gösteriyor.
Birinci ve dördüncü satırlarda saat dilimi metnin içinde yazılıdır; sonuç makineden bağımsızdır. İkinci satırda saat dilimi yazılmamış ve yerel saat varsayılmıştır; aynı metin başka bir makinede başka bir ana karşılık gelir. Üçüncü satırda yalnızca tarih verilmiş ve evrensel zaman varsayılmıştır — ikinci satırın tam tersi.
Kural buradan çıkar: ayrıştırılacak her zaman metni saat dilimi bilgisi taşımalıdır. Taşımıyorsa, hangi kuralın uygulanacağı biçime bağlıdır ve iki biçim birbirine zıt davranır.
Ayrıştırılamayan metin hata vermez; geçersiz bir tarih üretir:
const t = new Date("bozuk"); console.log(String(t)); console.log(Number.isNaN(t.getTime())); try { t.toISOString(); } catch (hata) { console.log(hata.name + ": " + hata.message); }
Invalid Date true RangeError: Invalid time value
Geçersizlik, damganın NaN olmasıyla saptanır. Denetim yapılmadan kullanıldığında hata,
ancak biçimlendirme aşamasında ortaya çıkar — kaynağından uzakta.
Tarih Aritmetiği
Aritmetik zaman damgası üzerinden yapılır; nesnelerin çıkarılması damga farkını verir:
const bas = new Date("2024-03-01T10:00:00Z"); const son = new Date("2024-03-01T10:00:00.800Z"); console.log(son.getTime() - bas.getTime(), "ms"); const birGunSonra = new Date(bas.getTime() + 24 * 60 * 60 * 1000); console.log(birGunSonra.toISOString());
800 ms 2024-03-02T10:00:00.000Z
Sabit milisaniye eklemek süre ekler, takvim günü eklemez. İkisi çoğu zaman aynıdır; yaz saati geçişlerinin olduğu dilimlerde bir günlük süre bir takvim gününe eşit olmayabilir. Takvim işlemleri için ayarlayıcı yöntemler kullanılır:
const bas = new Date("2024-03-01T10:00:00Z"); const kopya = new Date(bas.getTime()); kopya.setUTCDate(kopya.getUTCDate() + 1); console.log(kopya.toISOString(), bas.toISOString());
2024-03-02T10:00:00.000Z 2024-03-01T10:00:00.000Z
Tarih nesneleri değiştirilebilirdir: ayarlayıcı yöntemler nesneyi yerinde günceller.
Bu yüzden önce kopya alındı; alınmasaydı bas da değişirdi. Nesneler dersindeki kural
burada da geçerlidir — dönüşüm girdisini değiştirmez.
Biçimlendirme
Kullanıcıya gösterilecek metin, yerel ayar ve saat dilimi açıkça verilerek üretilir:
const t = new Date("2024-03-01T10:00:00Z"); const bicim = new Intl.DateTimeFormat("tr-TR", { dateStyle: "short", timeStyle: "medium", timeZone: "Europe/Istanbul", }); console.log(bicim.format(t)); const utcBicim = new Intl.DateTimeFormat("tr-TR", { dateStyle: "short", timeStyle: "medium", timeZone: "UTC", }); console.log(utcBicim.format(t)); console.log(t.toISOString().slice(0, 19).replace("T", " "));
1.03.2024 13:00:00 1.03.2024 10:00:00 2024-03-01 10:00:00
Aynı an iki farklı saatle gösterildi; ikisi de doğrudur. Fark, hangi saat diliminde bakıldığıdır.
Biçimlendiricinin ürettiği metnin ayrıntıları — ayırıcılar, basamak sayısı, harf kullanımı — yerel ayar verilerine bağlıdır ve çalışma zamanları arasında değişebilir. Bu yüzden biçimlendirilmiş metin gösterim içindir; ayrıştırılmak veya karşılaştırılmak üzere saklanmaz. Saklanacak biçim ISO gösterimidir.
JSON ile Birlikte
Tarih nesneleri dizileştirmede ISO metnine çevrilir, ama geri okunduğunda nesne olmaz:
const kayit = { istasyon: "A1", zaman: new Date("2024-03-01T10:00:00Z") }; const metin = JSON.stringify(kayit); console.log(metin); const geri = JSON.parse(metin); console.log(typeof geri.zaman, geri.zaman); const geriCanli = JSON.parse(metin, (anahtar, deger) => anahtar === "zaman" ? new Date(deger) : deger, ); console.log(geriCanli.zaman instanceof Date);
{"istasyon":"A1","zaman":"2024-03-01T10:00:00.000Z"}
string 2024-03-01T10:00:00.000Z
true
Çevrim tek yönlü asimetriktir: yazma kendiliğinden olur, okuma geri çağrı ister. JSON dersindeki simetri kuralı burada da uygulanır.
Ölçüm Betiğinin Son Hali
Kursun ekseni tamamlanıyor: metinden okunan, zamanla sıralanan ve biçimlendirilmiş bir ölçüm listesi.
const gelen = [ { istasyon: "A1", zaman: "2024-03-01T10:00:00Z", sicaklik: 21.5 }, { istasyon: "A1", zaman: "2024-03-01T10:15:00Z", sicaklik: 22.75 }, { istasyon: "B1", zaman: "2024-03-01T10:05:00Z", sicaklik: 23 }, ]; const bicim = new Intl.DateTimeFormat("tr-TR", { timeStyle: "short", timeZone: "Europe/Istanbul", }); const kayitlar = gelen .map((k) => ({ ...k, zaman: new Date(k.zaman) })) .filter((k) => !Number.isNaN(k.zaman.getTime())) .sort((a, b) => a.zaman - b.zaman); for (const k of kayitlar) { console.log( `${k.istasyon.padEnd(4)} ${bicim.format(k.zaman).padStart(6)} ${k.sicaklik.toFixed(2).padStart(7)}`, ); } const kapsam = kayitlar[kayitlar.length - 1].zaman - kayitlar[0].zaman; console.log("kapsanan sure (dk):", kapsam / 60000);
A1 13:00 21.50 B1 13:05 23.00 A1 13:15 22.75 kapsanan sure (dk): 15
Zincirin her adımı kursun bir dersinden geliyor. Yayma ile yeni nesneler üretildi (Nesneler), geçersiz tarihler süzüldü (Doğruluk Değerleri ve bu ders), sıralama karşılaştırma fonksiyonuyla yazıldı (Diziler), metin şablon dizgisiyle hizalandı (Dizgiler) ve süre farkı damga aritmetiğiyle hesaplandı.
Sıralama karşılaştırması a.zaman - b.zaman yazımıyla yapıldı; çıkarma işleci tarih
nesnelerini damgalarına çevirdiği için sonuç sayıdır. Bu, Tip Dönüşümü ve Zorlama
dersindeki kuralın yararlı kullanıldığı ender yerlerden biridir.
Özet
- Tarih nesnesi tek bir veri taşır: saat diliminden bağımsız zaman damgası. Gösterim ise saat dilimine bağlıdır.
- Ay numarası sıfırdan, gün ve yıl birden başlar; saat dilimi farkının işareti terstir.
- Saat dilimi yazılmamış zaman metni yerel saat, yalnızca tarih içeren metin evrensel zaman varsayılır; ayrıştırılacak metin saat dilimi taşımalıdır.
- Geçersiz tarih hata vermez; damgası
NaNolur ve ancak biçimlendirmede hata üretir. - Aritmetik damga üzerinden yapılır; ayarlayıcı yöntemler nesneyi yerinde değiştirdiği için önce kopya alınır.
- Biçimlendirilmiş metin gösterim içindir; saklama ve karşılaştırma ISO gösterimiyle yapılır.
Kurs Kapanışı
Bu kurs JavaScript’in değer modelini ve temel yapılarını kurdu. Dört konu birbirini tamamladı: dilin nasıl yürütüldüğü ve adların nasıl bağlandığı; hangi değerlerin bulunduğu ve nasıl dönüştürülüp karşılaştırıldıkları; akışın ve fonksiyonların nasıl yazıldığı; yerleşik veri yapılarının nasıl kullanıldığı.
Kurs boyunca tek bir örnek üzerinde çalışıldı. Ölçüm listesi, dört sayıdan oluşan bir diziyken başladı; metinden okunan, doğrulanan, gruplanan, biçimlendirilen ve JSON olarak geri yazılan bir veri kümesine dönüştü. Her ders o listeye bir yetenek ekledi ve eklediği yeteneğin sınırını da gösterdi.
Bilinçli olarak dışarıda bırakılan üç alan var. Birincisi, nesnelerin arkasındaki
prototip modeli: özelliklerin nasıl arandığı, sınıf sözdiziminin bu modele karşılığı ve
this bağlamasının kuralları. İkincisi, kapanışların durum taşımak için kullanılması.
Üçüncüsü, eşzamansız yürütme.
İlk ikisi JavaScript’te Nesneler ve Fonksiyonlar kursunun konusudur. O kurs, bu
kursta birkaç kez ertelenen soruları yanıtlar: bir dizinin map yöntemi nereden gelir,
ok fonksiyonunun prototype özelliğinin bulunmaması neyi engeller, nesne yöntemlerinde
this neye bağlanır ve bir fonksiyonun döndürdüğü fonksiyon dış değişkeni nasıl
hatırlar. Bu kursun kurduğu değer modeli, oradaki tartışmanın zeminidir.
Üçüncüsü daha sonra gelir. Bu kursta veri hep elimizin altındaydı; bir ağ isteğinden ya da dosya okumasından gelseydi sonucun hazır olmasını beklemek gerekirdi ve program bu sırada durmazdı. Olay döngüsü, sözler ve eşzamansız bekleme müfredatın ilerleyen kursunun konusudur. Sıradaki kurs olan JavaScript’te Nesneler ve Fonksiyonlar ise önce değerlerin arkasındaki yapıyı açar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.