JavaScript'te Date nesnesi aslında tek bir sayı tutar: 1 Ocak 1970 00:00 UTC'den bu yana geçen milisaniye. Yıl, ay, gün gibi bileşenler bu sayıdan ya cihazın yerel saat dilimine ya da UTC'ye göre hesaplanır. En sık karşılaşılan tuzaklar ayların 0'dan başlaması, metin ayrıştırmanın biçime göre farklı saat dilimi varsayması ve setter metotlarının nesneyi yerinde değiştirmesidir. Kullanıcıya gösterim için Intl.DateTimeFormat, saklama ve aktarım için toISOString() kullanılır.
Yeni nesil tarih API'si Temporal bu sorunları çözmek için tasarlandı; ancak MDN onu şu an "Limited availability" (sınırlı kullanılabilirlik) olarak işaretliyor ve Node.js 24'te varsayılan olarak tanımlı değil. Bu yazıdaki Date örnekleri Node.js 24'te, saat dilimi Europe/Istanbul (UTC+3) olan bir ortamda çalıştırıldı; yerel saate bağlı çıktılar sizin makinenizde farklı olabilir.
Ay indeksi 0'dan başlar, gün 1'den

new Date(yil, ay, gun, ...) biçimindeki constructor bileşenleri yerel saate göre yorumlar. Ay 0 (Ocak) ile 11 (Aralık) arasındadır, ayın günü ise 1'den başlar. getDay() haftanın gününü verir ve 0 Pazar'dır. Aralık dışına taşan değerler bir üst bileşene aktarılır: 12. ay bir sonraki yılın Ocak ayı olur, 0. gün bir önceki ayın son günü olur.
const d = new Date(2026, 0, 15); // 15 Ocak 2026, yerel saat
console.log(d.getFullYear(), d.getMonth(), d.getDate()); // 2026 0 15
console.log(d.getDay()); // 4 (0 = Pazar, 4 = Perşembe)
const tasma = new Date(2026, 12, 1);
console.log(tasma.getFullYear(), tasma.getMonth()); // 2027 0
console.log(new Date(2026, 2, 0).getDate()); // 28 (Şubat 2026 son günü)Son satırdaki "0. gün" hilesi, bir ayın kaç gün çektiğini bulmanın yaygın bir yoludur. Ayrıca iki basamaklı yıllara dikkat edin: constructor new Date(99, 5, 24) ifadesini 1999 olarak yorumlar.
Setter'lar nesneyi değiştirir ve taşma yapar
setMonth(), setDate() gibi metotlar yeni nesne döndürmez, mevcut nesneyi değiştirir. Aynı nesneyi birden çok yerde paylaşıyorsanız beklenmedik yan etkiler ortaya çıkar. Ayrıca ay ekleme işlemi gün taşmasına yol açabilir:
const tarih = new Date(2021, 0, 31); // 31 Ocak 2021
const kopya = tarih; // aynı nesne
tarih.setMonth(1); // "Şubat 31" yok, taşar
console.log(tarih.getMonth(), tarih.getDate()); // 2 3 (3 Mart)
console.log(kopya.getMonth()); // 2 (kopya da değişti)
const guvenli = new Date(tarih.getTime()); // gerçek kopya
guvenli.setDate(1);
console.log(tarih.getDate(), guvenli.getDate()); // 3 1Metin ayrıştırma: aynı tarih, iki farklı an
Spesifikasyonun her ortamda desteklenmesini garanti ettiği tek biçim, ISO 8601'in sadeleştirilmiş hâli olan YYYY-MM-DDTHH:mm:ss.sssZ biçimidir. Burada kritik bir kural var: saat dilimi belirtilmediğinde yalnızca tarih içeren biçimler UTC, tarih ve saat içeren biçimler yerel saat olarak yorumlanır. MDN, bu tutarsızlığın web uyumluluğu nedeniyle düzeltilemeyen tarihsel bir hata olduğunu belirtir.
const a = new Date("2026-11-05"); // yalnızca tarih: UTC
const b = new Date("2026-11-05T00:00"); // tarih + saat: yerel
const c = new Date("2026-11-05T00:00+03:00"); // açık ofset
console.log(a.toISOString()); // 2026-11-05T00:00:00.000Z
console.log(b.toISOString()); // 2026-11-04T21:00:00.000Z
console.log(c.toISOString()); // 2026-11-04T21:00:00.000Z
console.log(a.getTime() === b.getTime()); // falseStandart dışı biçimler ("05.11.2026", "5 Kasım 2026" gibi) ise tamamen motora bırakılmıştır; bir tarayıcıda çalışan biçim diğerinde Invalid Date verebilir. Kullanıcıdan gelen tarihleri kendiniz parçalara ayırıp new Date(yil, ay - 1, gun) ile oluşturmak daha güvenlidir.
Geçersiz tarihi yakalamak
Ayrıştırılamayan bir metin hata fırlatmaz; zaman damgası NaN olan bir "Invalid Date" nesnesi üretir. Bu nesnede toISOString() çağırmak ise RangeError verir. Kontrolü getTime() üzerinden yapın:
const bozuk = new Date("bugün değil");
console.log(bozuk.getTime(), Number.isNaN(bozuk.getTime())); // NaN true
try {
bozuk.toISOString();
} catch (e) {
console.log(e.constructor.name, e.message); // RangeError Invalid time value
}Zaman damgaları ve süre hesabı
Date.now() şu anın zaman damgasını sayı olarak verir. getTime() bir tarihin damgasını döndürür; iki Date nesnesini çıkardığınızda da sayıya dönüştürülüp milisaniye farkı elde edilir. Gün farkı hesaplarken yaz saati geçişlerinden etkilenmemek için UTC tarihleri kullanmak daha güvenlidir.
const baslangic = new Date("2026-01-01T00:00:00Z");
const bitis = new Date("2026-11-05T00:00:00Z");
const gun = (bitis - baslangic) / (1000 * 60 * 60 * 24);
console.log(gun); // 308
console.log(new Date(0).toISOString()); // 1970-01-01T00:00:00.000Z
console.log(new Date("2026-07-01T12:00:00Z").getTimezoneOffset()); // -180getTimezoneOffset(), UTC ile yerel saat arasındaki farkı dakika cinsinden verir ve yerel saat UTC'nin ilerisindeyse negatiftir. MDN'e göre bu değer yalnızca saat dilimine değil, nesnenin temsil ettiği tarihe de bağlıdır; çünkü yaz saati ve geçmiş dönemlerdeki kural değişiklikleri ofseti etkileyebilir.
toISOString ile saklama, Intl.DateTimeFormat ile gösterme

toISOString() her zaman UTC'ye göre, Z ekli ve 24 (genişletilmiş yıllarda 27) karakter uzunluğunda bir metin döndürür. JSON.stringify() de tarihleri toJSON() üzerinden bu biçime çevirir. Veritabanına yazarken veya API'ye gönderirken bu biçimi kullanmak, saat dilimi karışıklığını ortadan kaldırır.
const an = new Date("2026-11-05T10:30:00Z");
console.log(an.toISOString()); // 2026-11-05T10:30:00.000Z
console.log(JSON.stringify({ an })); // {"an":"2026-11-05T10:30:00.000Z"}Kullanıcıya gösterirken ise Intl.DateTimeFormat kullanın. timeZone seçeneği herhangi bir IANA saat dilimi adını kabul eder; verilmezse çalışma ortamının saat dilimi kullanılır. Sunucuda çalışan kodda bu seçeneği her zaman açıkça yazmak, sunucunun nerede barındırıldığından bağımsız olarak doğru saati göstermenizi sağlar.
const an = new Date("2026-11-05T10:30:00Z");
const tam = new Intl.DateTimeFormat("tr-TR", {
dateStyle: "full",
timeStyle: "short",
timeZone: "Europe/Istanbul",
});
console.log(tam.format(an)); // 5 Kasım 2026 Perşembe 13:30
const kisa = new Intl.DateTimeFormat("tr-TR", { timeZone: "Europe/Istanbul" });
console.log(kisa.format(an)); // 05.11.2026
const ny = new Intl.DateTimeFormat("tr-TR", {
hour: "2-digit",
minute: "2-digit",
timeZone: "America/New_York",
});
console.log(ny.format(an)); // 05:30Aynı an, New York saatiyle 05:30'dur; nesnenin içindeki zaman damgası değişmez, yalnızca gösterim değişir. dateStyle ve timeStyle kullanırken year, hour gibi tekil bileşen seçeneklerini aynı anda veremezsiniz; ikisini karıştırmak hata verir. Biçim çıktısı ICU verisine bağlı olduğu için ortamlar arasında küçük farklar olabilir.
| Metot | Saat dilimi | Kullanım |
|---|---|---|
| toISOString() | Her zaman UTC | Saklama, API, JSON |
| toString() | Yerel | Hata ayıklama |
| toUTCString() | UTC | RFC 7231 tabanlı metin biçimi |
| toLocaleDateString("tr-TR") | Yerel veya timeZone seçeneği | Kısa gösterim |
| Intl.DateTimeFormat | timeZone seçeneği | Kullanıcıya gösterim, yeniden kullanılabilir biçimlendirici |
Temporal: Date yerine gelen yeni API
MDN, Temporal nesnesini Date için tam bir yedek olarak tanımlar. Math gibi bir ad alanıdır, constructor değildir. Temel sınıfları şunlardır: süre için Temporal.Duration, kesin an için Temporal.Instant, saat dilimli tarih-saat için Temporal.ZonedDateTime, saat diliminden bağımsız değerler için PlainDateTime, PlainDate, PlainTime, PlainYearMonth, PlainMonthDay ve şu anki zamanı almak için Temporal.Now. Temporal nesneleri değiştirilemez (immutable); add() gibi metotlar her zaman yeni bir nesne döndürür ve aylar 1'den başlar.
console.log(typeof Temporal); // undefined (Node.js 24)// Node.js 24'te ÇALIŞMAZ: Temporal destekleyen bir ortam veya polyfill gerekir
const baslangic = Temporal.PlainDate.from("2021-01-31");
console.log(baslangic.add({ months: 1 }).toString()); // 2021-02-28
console.log(baslangic.toString()); // 2021-01-31 (değişmedi)
const gun = Temporal.PlainDate.from("2021-01-01");
console.log(gun.add({ years: 1, months: 2, weeks: 3, days: 4 }).toString()); // 2022-03-26
// ZonedDateTime metninde saat dilimi zorunludur; yoksa RangeError
const toplanti = Temporal.ZonedDateTime.from("2026-11-05T09:00[Europe/Istanbul]");31 Ocak'a bir ay eklemenin sonucunu karşılaştırın: Date.setMonth() 3 Mart'a taştı, Temporal.PlainDate.add() ise varsayılan overflow: "constrain" davranışıyla ayın son gününe, 28 Şubat'a sabitledi. Aynı işlemde taşmayı hata olarak görmek isterseniz { overflow: "reject" } seçeneği RangeError fırlatır.
Yaygın hatalar
- Ayı 1'den başlatmak:
new Date(2026, 11, 5)5 Kasım değil 5 Aralık'tır. - "YYYY-MM-DD" metnini yerel tarih sanmak: UTC gece yarısı olarak yorumlanır; UTC'nin gerisindeki saat dilimlerinde yerel gösterim bir önceki güne düşer.
- Standart dışı metinleri ayrıştırmak: Sonuç motora göre değişir. Biçimi kendiniz çözün veya ISO biçimine dönüştürün.
- Paylaşılan Date nesnesini setter ile değiştirmek: Önce
new Date(d.getTime())ile kopyalayın. - Sunucuda timeZone vermeden biçimlendirmek: Çıktı sunucunun saat dilimine bağlı kalır. Türkiye saati için
timeZone: "Europe/Istanbul"yazın.
Sık Sorulan Sorular
getMonth() neden bir eksik veriyor?
Aylar 0 ile 11 arasında numaralandırılır. Kullanıcıya gösterirken getMonth() + 1 yazın ya da doğrudan Intl.DateTimeFormat kullanın.
Tarihleri veritabanında nasıl saklamalıyım?
UTC zaman damgası veya toISOString() çıktısı olarak saklayıp gösterim anında kullanıcının saat dilimine çevirmek en tutarlı yöntemdir. JSON ile aktarım ayrıntıları JSON yazısında.
Temporal'ı bugün kullanabilir miyim?
MDN sınırlı kullanılabilirlik bildirdiği için hedeflediğiniz her ortamı uyumluluk tablosundan kontrol etmeniz gerekir. Node.js 24'te varsayılan olarak bulunmaz; desteklenmeyen ortamlarda MDN'in listelediği polyfill paketlerinden biri kullanılabilir.
İki tarih arasındaki gün farkını nasıl bulurum?
İki tarihi UTC olarak oluşturup farkı 1000 * 60 * 60 * 24 değerine bölün. Yerel saatle çalışırsanız yaz saati geçişi olan dönemlerde fark tam sayı çıkmayabilir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: JavaScript öğrenme rehberi · JSON.parse ve JSON.stringify · Sayılar: Number ve BigInt · JavaScript class kullanımı · Template literal · Node.js nedir?