6 dk

JavaScript Zaman Biçimlendirme ve Dönüşümü: Yaygın Tuzaklar

JavaScript'te zaman biçimlendirme ve dönüşümlerinin sürpriz yaratmaması için öğrenin: zaman damgaları, ISO stringler, zaman dilimleri, DST, ayrıştırma kuralları ve güvenilir desenler.

JavaScript Zaman Biçimlendirme ve Dönüşümü: Yaygın Tuzaklar

JavaScript zamanında genellikle neler ters gider

JavaScript zaman hataları nadiren "saat yanlış" gibi belirgin olur. Genellikle küçük, kafa karıştıran kaymalar şeklinde görünürler: laptopunuzda doğru görünen bir tarih meslektaşınızın makinesinde yanlış olabilir; bir API yanıtı farklı bir zaman diliminde render edilince bozulabilir; veya mevsimsel bir değişiklik etrafında "bir eksik" raporu oluşabilir.

En yaygın belirtiler

Genellikle şu durumlardan biri (veya birkaçı) göze çarpar:

  • Bir saat farkı: özellikle Yaz Saati Uygulaması (DST) sırasında veya bir değerin istemeden yerel zaman ile UTC arasında dönüştürülmesi durumunda.
  • Bir gün farkı: yalnızca tarih içeren bir değer (ör. “2025-12-23”) zaman dilimine bağlı olarak önceki/sonraki gün olarak görünebilir.
  • Yanlış zaman dilimi: saatler doğru görünür, ancak beklediğiniz ofset (ör. +02:00) farklıdır.
  • Tutarsız biçimlendirme: “Chrome'da çalışıyor” ama Safari'de farklı görünüyor; sunucu ve tarayıcı bir stringi farklı yorumluyor.

Bunun nedeni: “zaman” farklı şeyler anlamına gelebilir

Büyük sorunlardan biri, zaman kelimesinin farklı kavramlara işaret edebilmesidir:

  • Bir an (instant): dünya çapında belirli bir an (ör. “2025-12-23T10:00:00Z”). Genellikle logging, etkinlikler ve API depolama için istenen budur.
  • Takvim tarihi: bir zaman dilimi olmayan takvim günü (ör. bir doğum günü, fatura tarihi). Bunu bir an gibi ele almak gün sınırları arasında kaymaya yol açabilir.
  • Duvar saati zamanı (wall-clock time): “Berlin'de 09:00” gibi, zaman dilimi kurallarına ve DST değişikliklerine bağlıdır.

JavaScript'in yerleşik Date objesi bu kavramların hepsini kapsamaya çalışır, ancak öncelikle bir anı temsil eder ve sürekli olarak yerel gösterime doğru sizi yönlendirir; bu da istem dışı dönüşümleri kolaylaştırır.

Bu makalenin odak noktası

Bu rehber niyetli olarak pratiktir: tarayıcılar ve sunucular arasında öngörülebilir dönüşümler nasıl sağlanır, ISO 8601 gibi daha güvenli formatlar nasıl seçilir ve klasik tuzaklar (saniye vs milisaniye, UTC vs yerel, ayrıştırma farkları) nasıl tespit edilir. Amaç teori değil—daha az "neden kaydı?" sürprizidir.

Zaman Veri Türleri: Zaman damgası, Date ve String

JavaScript zaman hataları genelde birbirinin yerine kullanılabilir gibi görünen ama gerçekte olmayan temsil biçimlerinin karıştırılmasıyla başlar.

En çok göreceğiniz üç temsil

1) Epoch milisaniyeleri (sayı)

1735689600000 gibi bir sayı genellikle "1970-01-01T00:00:00Z'den bu yana milisaniyeler" demektir. Formatlama veya zaman dilimi içermeyen bir anı temsil eder.

2) Date nesnesi (bir anın sarmalayıcısı)

Bir Date, aynı türde bir anı zaman damgası olarak saklar. Kafa karıştıran nokta: bir Date'i yazdırdığınızda, JavaScript ortamdaki yerel kuralları kullanarak formatlar—istisna istemezseniz yerel gösterim olur.

3) Biçimlendirilmiş string (insan gösterimi)

"2025-01-01", "01/01/2025 10:00" veya "2025-01-01T00:00:00Z" gibi stringler tek bir şey değiller. Bazıları açık ve nettir (Z ile ISO 8601), bazıları locale'e bağlıdır, bazıları ise hiç zaman dilimi içermez.

“An” vs “insan gösterimi”

  • An (instant): "dünya çapında bu kesin an" (en iyi epoch ms veya UTC ISO string olarak saklanır).
  • İnsan gösterimi: "kullanıcının görmesi gereken" zaman (locale ve zaman dilimine bağlıdır).

Aynı an zaman dilimine göre farklı görünebilir:

const instant = new Date("2025-01-01T00:00:00Z");

instant.toLocaleString("en-US", { timeZone: "UTC" });
// "1/1/2025, 12:00:00 AM"

instant.toLocaleString("en-US", { timeZone: "America/Los_Angeles" });
// "12/31/2024, 4:00:00 PM" (bir önceki gün)

Bir “gerçek kaynak” seçin

Uygulamanız ve API'leriniz genelinde tek bir dahili temsil (genellikle epoch milisaniyeleri veya UTC ISO 8601) seçin ve ona sadık kalın. Date ve biçimlendirilmiş stringlere dönüşümü sadece sınırda yapın: giriş ayrıştırma ve UI gösterimi esnasında.

Zaman damgaları: Saniye vs Milisaniye (kolay karıştırılır)

“Timestamp” genellikle epoch zamanı (Unix zamanı) anlamına gelir: 1970-01-01 00:00:00 UTC'den bu yana geçen süre. Sorun şu: farklı sistemler farklı birimlerde sayar.

JavaScript Date çoğu kafa karışıklığının kaynağıdır çünkü milisaniye kullanır. Birçok API, veritabanı ve log ise saniye kullanır.

Pratik kural

  • Unix timestamp (saniye): 1704067200
  • JavaScript timestamp (milisaniye): 1704067200000

Aynı an; fakat milisaniye versiyonunda üç ekstra rakam vardır.

Güvenli dönüşümler (saniye ↔ milisaniye)

Birimlerin açıkça görülmesi için çarpma/bölme kullanın:

// seconds -> Date
const seconds = 1704067200;
const d1 = new Date(seconds * 1000);

// milliseconds -> Date
const ms = 1704067200000;
const d2 = new Date(ms);

// Date -> seconds
const secondsOut = Math.floor(d2.getTime() / 1000);

// Date -> milliseconds
const msOut = d2.getTime();

Klasik hata: saniyeleri Date()'e geçirmek

Makul gibi görünür ama yanlıştır:

const ts = 1704067200;      // seconds
const d = new Date(ts);     // WRONG: treated as milliseconds

Sonuç 1970 civarında bir tarih olacaktır, çünkü 1,704,067,200 milisaniye epoch'tan sadece yaklaşık 19 gün sonradır.

Hızlı doğrulama ve hata ayıklama kontrolleri

Hangi birimde olduğunu bilmediğinizde basit koruyucu önlemler ekleyin:

function asDateFromUnknownEpoch(x) {
  // crude heuristic: seconds are ~1e9-1e10, milliseconds are ~1e12-1e13
  if (x < 1e11) return new Date(x * 1000); // assume seconds
  return new Date(x);                      // assume milliseconds
}

const input = Number(valueFromApi);
console.log({ input, digits: String(Math.trunc(input)).length });
console.log('as ISO:', asDateFromUnknownEpoch(input).toISOString());

"digits" sayısı ~10 ise muhtemelen saniyedir. ~13 ise milisaniyedir. Hata ayıklarken toISOString() yazdırmak birim hatalarını hemen fark etmenize yardımcı olur.

Yerel zaman vs UTC: Neden çıktınız kayıyor

JavaScript Date kafa karıştırıcı olabilir çünkü bir anı saklar, ama o anı farklı zaman dilimlerinde sunabilir. İçeride bir Date, esasen "Unix epoch'tan (1970-01-01T00:00:00Z) bu yana milisaniyeler"dir. Kayma, JavaScript'e o anı yerel zaman (bilgisayar/sunucu ayarlarına göre) veya UTC olarak formatlamasını söylediğinizde ortaya çıkar.

Yerel getter'lar vs UTC getter'ları

Birçok Date API'sinin hem yerel hem UTC varyantları vardır. Aynı an için farklı sayılar döndürürler:

const d = new Date('2025-01-01T00:30:00Z');

d.getHours();      // saat, *yerel* zaman diliminde
d.getUTCHours();   // saat, UTC olarak

d.toString();      // yerel zaman string'i
d.toISOString();   // UTC (her zaman Z ile biter)

Makineniz New York'taysa (UTC-5), o UTC zamanı yerelde önceki günün "19:30"u olarak görünebilir. UTC'ye ayarlı bir sunucuda ise "00:30" olacaktır. Aynı an, farklı gösterim.

Loglar neden “yanlış” görünür

Loglar sıklıkla Date#toString() veya bir Date'i dolaylı olarak interpolasyonla kullanır; bu yerel zaman dilimini kullanır. Bu, aynı kodun laptopunuzda, CI'da ve üretimde farklı zaman damgaları yazdırabileceği anlamına gelir.

Pratik rehber

Zamanı UTC olarak saklayın ve iletin (ör. epoch milisaniyeleri veya toISOString()). Gösterimi yalnızca kullanıcı için locale'a göre yapın:

  • API'ler için: toISOString() veya epoch milisaniyeleri tercih edin
  • UI için: veriyi kullanıcı zaman diliminde Intl.DateTimeFormat ile formatlayın

Hızlı geliştirme yapıyorsanız (ör. Koder.ai ile hızlı uygulama üretimi), bunu API kontratlarınıza erken dahil etmek işinizi kolaylaştırır: alanlara net adlar verin (createdAtMs, createdAtIso) ve sunucu (Go + PostgreSQL) ile istemci (React) arasında her alanın neyi temsil ettiği konusunda tutarlı olun.

ISO 8601 Stringleri: API'ler için en güvenli format

Tarayıcı, sunucu ve veritabanı arasında tarih/zaman göndermeniz gerekiyorsa, ISO 8601 stringleri varsayılan olarak en güvenlisidir. Açık, yaygın destekli ve (en önemlisi) zaman dilimi bilgisi taşırlar.

Açık UTC veya açık ofset kullanın

İki iyi değiş tokuş formatı:

  • UTC zamanı (yerel bölgeyi önemsemediğinizde): 2025-03-04T12:30:00Z
  • Ofsetli yerel zaman ("duvar saati" önemliyse): 2025-03-04T12:30:00+02:00

"Z" ne anlama gelir?

Z Zulu zamanı, yani UTC anlamına gelir. Dolayısıyla 2025-03-04T12:30:00Z UTC'de 12:30 demektir.

+02:00 gibi ofsetler ne zaman önemlidir?

Ofsetler, bir etkinliğin yerel zaman bağlamına bağlı olduğu durumlarda (randevular, rezervasyonlar, mağaza açılış saatleri) çok önemlidir. 2025-03-04T12:30:00+02:00, UTC'den iki saat ileri olan bir anı tarif eder ve 2025-03-04T12:30:00Z ile aynı an değildir.

Belirsiz tarih stringlerinden kaçının

03/04/2025 gibi stringler tuzaktır: Mart 4 mü yoksa 3 Nisan mı? Farklı kullanıcılar ve ortamlar farklı şekilde yorumlayabilir. 2025-03-04 (ISO tarih) veya tam bir ISO datetime tercih edin.

Güvenli geri dönüşüm (string → Date → string)

const iso = "2025-03-04T12:30:00Z";
const d = new Date(iso);
const back = d.toISOString();

console.log(iso);  // 2025-03-04T12:30:00Z
console.log(back); // 2025-03-04T12:30:00.000Z

Bu "geri dönüşüm" davranışı API'ler için istediğiniz şeydir: tutarlı, öngörülebilir ve zaman dilimini göz önünde bulundurur.

Ayrıştırma tuzakları: Date.parse ve tarayıcı farkları

Add DST edge-case tests
Ask Koder.ai to scaffold unit tests around DST boundaries and multiple time zones.

Date.parse() kullanışlı gelebilir: bir string ver, bir zaman damgası alırsın. Sorun şu ki, ISO 8601 açıkça belirtilmemiş her şey için ayrıştırma tarayıcı sezgilerine dayanabilir. Bu sezgiler motorlar ve sürümler arasında farklılık gösterdi; aynı girdi farklı ortamlarda farklı yorumlanabilir (veya hiç ayrıştırılamayabilir).

Neden Date.parse() değişkenlik gösterir

JavaScript yalnızca ISO 8601 tarzı stringler için ayrıştırmayı güvenilir şekilde standartlaştırır (hatta burada bile zaman dilimi detayları önem taşır). "Dost canlısı" formatlar—ör. "03/04/2025", "March 4, 2025" veya "2025-3-4"—için tarayıcılar:

  • Ay/gün vs gün/ay'ı locale varsayımlarına göre yorumlayabilir
  • Zaman dilimi eksikse bir motorda yerel zaman, başka bir motorda reddedilen ifade olabilir
  • Küçük hatalı formatları "yaklaşık yeterli" olarak kabul edebilir... taşma yaşanana kadar

Eğer kesin string şeklini tahmin edemiyorsanız, sonucu tahmin edemezsiniz.

Şaşırtıcı durum: YYYY-MM-DD

Yaygın bir tuzak, "YYYY-MM-DD" (örneğin "2025-01-15") formudur. Birçok geliştirici bunun yerel gece yarısı olarak yorumlanmasını bekler. Ancak bazı ortamlar bu formu UTC gece yarısı olarak ele alır.

Bu fark önemlidir: UTC gece yarısı yerel zamana çevrildiğinde negatif zaman dilimlerinde (örn. Amerika) bir önceki gün olabilir veya saat beklenmedik şekilde kayabilir. Bu, "tarihim neden bir gün kaydı?" hatalarının sık görülen bir sebebidir.

Ayrıştırma kontrol listesi: kullanıcı girişi vs sunucu girişi

Sunucu/API girişi için:

  • Zaman dilimi açık olan tam ISO 8601 tercih edin, örn. 2025-01-15T13:45:00Z veya 2025-01-15T13:45:00+02:00.
  • Tarih-only değerleri veri olarak ele alın, an olarak değil. Eğer doğum günü ya da son tarih ise, bunu düz bir string ("YYYY-MM-DD") olarak saklayın ve isterseniz ayrıca hangi zaman diliminin kastedildiğini tanımlayın.

Kullanıcı girişi için:

  • UI'niz anlamı zorlamıyorsa 03/04/2025 gibi belirsiz formatları kabul etmeyin.
  • Bilinen format üreten kontrollü girdiler (date picker) tercih edin.
  • Serbest metin ayrıştıracaksanız, kabul edilen formatları baştan belirleyin ve zorunlu kılın.

Sezgiler yerine açık kurallar kullanın

Date.parse()'in "anlamasını" beklemek yerine şu desenlerden birini seçin:

  • Sunucudan sadece ISO 8601 kabul edin; diğerlerini reddedin.
  • Bilinen formatları manuel ayrıştırın (string'i bölüp new Date(year, monthIndex, day) ile yerel tarihler oluşturun).
  • Kesin anlar için zaman damgalarını (epoch milisaniyeleri) saklayın ve gösterimi son anda yapın.

Zaman verisi kritikse, "makinemde ayrışıyor" yeterli değildir—ayrıştırma kurallarınızı açık ve tutarlı hale getirin.

İnsanlar için biçimlendirme: Intl.DateTimeFormat

Kullanıcıların beklediği şekilde bir tarih/zaman göstermek istiyorsanız, JavaScript'te en iyi araç Intl.DateTimeFormat'tır. Kullanıcının locale kurallarını (sıra, ayırıcılar, ay isimleri) kullanır ve month + '/' + day gibi kırılgan elle birleştirmelerden kaçınır.

Neden elle string birleştirmeden daha iyi

Elle biçimlendirme sıklıkla ABD stili çıktı sabitler, baştaki sıfırı unutur veya 24/12 saat karışıklığına sebep olur. Intl.DateTimeFormat ayrıca hangi zaman dilimini gösterdiğinizi açıkça belirtmenizi sağlar—veriniz UTC'de saklansa bile UI'nın kullanıcının yerel zamanını yansıtması gerektiğinde kritik önemdedir.

Gerçek hayatta sık kullandığınız seçenekler

"Güzelce göster" için dateStyle ve timeStyle en basit olanlardır:

const d = new Date('2025-01-05T16:30:00Z');

// Kullanıcının locale'i + kullanıcının yerel zaman dilimi
console.log(new Intl.DateTimeFormat(undefined, {
  dateStyle: 'medium',
  timeStyle: 'short'
}).format(d));

// Belirli bir zaman dilimini zorla (etkinlik zamanları için harika)
console.log(new Intl.DateTimeFormat('en-GB', {
  dateStyle: 'full',
  timeStyle: 'short',
  timeZone: 'UTC'
}).format(d));

Saat döngüsünü (12/24 saat) tutarlı yapmak isterseniz hour12 kullanın:

console.log(new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: '2-digit',
  hour12: true
}).format(d));

Pratik bir UI deseni

UI'nizdeki her "zaman türü" için tek bir biçimlendirme fonksiyonu seçin (mesaj zamanı, log girişi, etkinlik başlangıcı) ve timeZone kararını kasıtlı yapın:

  • "Benim için ne zaman oldu" için yerel zaman kullanın.
  • Denetim, sunucu olayları veya ekipler arası uyumda genellikle sabit bir bölge (çoğunlukla UTC) kullanın.

Bu, kırılgan özel format stringleri tutmak zorunda kalmadan tutarlı, locale-dostu çıktı sağlar.

Yaz Saati Uygulaması (DST): Gizli bir bir saatlik hata

Own the source code
Keep full control by exporting source code for review, audits, or custom tooling.

DST, bir zaman diliminin UTC ofsetini (genellikle bir saat) belirli tarihlerde değiştirdiği zamandır. Zorlayıcı kısmı: DST sadece ofseti değiştirmez—bazı yerel saatlerin varlığını değiştirir.

Eksik ve tekrar eden duvar saati zamanları

Saatler ileri alındığında, bazı yerel zaman aralıkları hiç olmaz. Örneğin, birçok bölgede saat 01:59'dan 03:00'a atlar, bu yüzden 02:30 yerel zamanı "olmayan" bir zamandır.

Saatler geri alındığında, bazı yerel zamanlar iki kez yaşanır. Örneğin 01:30 hem öne hem arkaya alınmadan önce hem de sonra gerçekleşebilir; aynı duvar saati iki farklı ana işaret edebilir.

24 saat eklemek vs “yarın aynı yerel zaman”

DST sınırlarında bunlar eşdeğer değildir:

  • 24 saat ekle: "tam olarak 24 * 60 * 60 saniye sonra"
  • Aynı yerel saatte yarın: "bu zaman diliminde yarın 9:00"

Eğer bugün DST başlıyorsa, "yarın 9:00" sadece 23 saat uzak olabilir. DST bitiyorsa 25 saat uzak olabilir.

// Senaryo: "yarın aynı yerel saatte" planlama
const d = new Date(2025, 2, 8, 9, 0); // 8 Mar, yerel 9:00

const plus24h = new Date(d.getTime() + 24 * 60 * 60 * 1000);
const nextDaySameLocal = new Date(d);
nextDaySameLocal.setDate(d.getDate() + 1);

// DST etrafında plus24h ile nextDaySameLocal 1 saat farklı olabilir.

setHours neden sizi şaşırtır

date.setHours(2, 30, 0, 0) gibi bir şey yaparsanız ve o gün "ileri alınmış"sa, JavaScript bunu geçerli bir zamana normalize edebilir (çoğunlukla 03:30), çünkü 02:30 yerel olarak yoktur.

Daha güvenli yaklaşımlar

  • Geçen süre (süreler) için UTC'de aritmetik yapın: epoch milisaniyelerini ve UTC method'larını kullanın.
  • Yerel planlama için niyeti açıkça belirtin: "yarın aynı yerel saatte" takvimsel operasyonlar (setDate) kullanılarak yapılmalıdır, milisaniye eklemek yerine.
  • API'ler aracılığıyla zaman alışverişinde ofsetli ISO 8601 veya Z tercih edin ki an net olsun.

Süreler vs Tarihler: Sayaç için Date kullanmayın

Sıkça yapılan bir hata, Date'i takvim anı olmayan bir şeyi temsil etmek için kullanmaktır.

Zaman damgası "bu ne zaman oldu?" sorusunu cevaplar (ör. 2025-12-23T10:00:00Z). Süre "ne kadar sürdü?" sorusunu cevaplar (ör. "3 dakika 12 saniye"). Bunlar farklı kavramlardır; karıştırılması kafa karıştıran aritmetiğe ve beklenmeyen zaman dilimi/DST etkilerine yol açar.

Neden Date süreler için yanlış araçtır

Date her zaman epoch'a göre bir anı temsil eder. "90 saniye"yi bir Date ile saklarsanız, aslında "1970-01-01 artı 90 saniye" saklıyorsunuzdur; formatlandığında 01:01:30 olarak gösterilebilir, bir saat kayabilir veya istemediğiniz bir tarih görünebilir.

Süreler için şu tercihleri kullanın:

  • Süreleri saniye veya milisaniye olarak saklayın (bir birim seçin ve ona bağlı kalın).
  • Aritmetiği sayılarla yapın.
  • Gösterimi en son aşamada string'e çevirin.

Saniyeleri HH:mm:ss'ye çevirme

Geri sayım ve medya uzunlukları için basit bir formatlayıcı:

function formatHMS(totalSeconds) {
  const s = Math.max(0, Math.floor(totalSeconds));
  const hh = String(Math.floor(s / 3600)).padStart(2, "0");
  const mm = String(Math.floor((s % 3600) / 60)).padStart(2, "0");
  const ss = String(s % 60).padStart(2, "0");
  return `${hh}:${mm}:${ss}`;
}

formatHMS(75);    // "00:01:15" (geri sayım)
formatHMS(5423);  // "01:30:23" (medya süresi)

Dakikadan dönüştürüyorsanız önce çarpın (minutes * 60) ve render edene kadar sayısal değeri koruyun.

Karşılaştırma, Sıralama ve Aralıklar: Sürprizlere karşı

JavaScript'te zamanları karşılaştırırken en güvenli yaklaşım formatlanmış metinler yerine sayıları karşılaştırmaktır. Bir Date nesnesi temelde bir epoch milisaniyesi sayısının sarmalayıcısıdır; karşılaştırmaların "sayı vs sayı" olarak bitmesini istersiniz.

Güvenli karşılaştırmalar (zaman damgaları kazanır)

Güvenilir karşılaştırma için getTime() (veya aynı sayıyı döndüren Date.valueOf()) kullanın:

const a = new Date('2025-01-10T12:00:00Z');
const b = new Date('2025-01-10T12:00:01Z');

if (a.getTime() < b.getTime()) {
  // a daha önce
}

// Ayrıca çalışır:
if (+a < +b) {
  // unary + valueOf()'u çağırır
}

"1/10/2025, 12:00 PM" gibi formatlanmış stringleri karşılaştırmaktan kaçının—bunlar locale'e bağımlıdır ve doğru sıralamaz. Aynı formatta ve aynı zaman diliminde olan ISO 8601 stringleri (...Z) leksikografik olarak sıralanabilir; bu bir istisnadır.

Sıralama ve aralık ile filtreleme

Zamana göre sıralama, epoch milisaniyelerine göre sıralanırsa basittir:

items.sort((x, y) => new Date(x.createdAt).getTime() - new Date(y.createdAt).getTime());

Aralıkla filtreleme de aynı fikir:

const start = new Date('2025-01-01T00:00:00Z').getTime();
const end   = new Date('2025-02-01T00:00:00Z').getTime();

const inRange = items.filter(i => {
  const t = new Date(i.createdAt).getTime();
  return t >= start && t < end;
});

"Günün başı/sonu" (yerel vs UTC)

"Günün başı" yerel mi yoksa UTC mi kastettiğinize bağlıdır:

// Yerel gün başı/sonu
const d = new Date(2025, 0, 10); // Yerelde 10 Ocak
const localStart = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0, 0, 0);
const localEnd   = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23, 59, 59, 999);

// UTC gün başı/sonu
const utcStart = new Date(Date.UTC(2025, 0, 10, 0, 0, 0, 0));
const utcEnd   = new Date(Date.UTC(2025, 0, 10, 23, 59, 59, 999));

Erken bir tanımı seçin ve karşılaştırma ile aralık mantığınızda ona sadık kalın.

Hata ayıklama kontrol listesi: Bir zaman dönüşüm hatasını nasıl teşhis edersiniz

Get rewarded for sharing builds
Share what you build and earn credits through content and referrals.

Zaman hataları rastgele hissedilir ta ki elinizde ne olduğunu (zaman damgası? string? Date?) ve kaymanın nerede meydana geldiğini (ayrıştırma, zaman dilimi dönüşümü, formatlama) tespit edene kadar.

1) Aynı anın “üç görünümünü” yakalayın

İşinize genellikle aynı değeri üç farklı şekilde loglamak başlar. Bu, birimin saniye/milisaniye, yerel/UTC veya string ayrıştırma hatası olup olmadığını hızlıca gösterir.

console.log('raw input:', input);

const d = new Date(input);
console.log('toISOString (UTC):', d.toISOString());
console.log('toString (local):', d.toString());
console.log('timezone offset (min):', d.getTimezoneOffset());

Ne aramalı:

  • Eğer toISOString() çok farklı (ör. 1970 veya çok uzak bir gelecek), saniye vs milisaniye şüphesi vardır.
  • toISOString() doğru ama toString() "kaymış" ise yerel zaman dilimi gösterimi sorunu görüyorsunuz.
  • getTimezoneOffset() tarih değiştikçe değişiyorsa yaz saati uygulaması ile karşılaşıyorsunuz demektir.

2) Ortamı doğrulayın: zaman dilimi ve locale

Birçok "bende çalışıyor" raporu farklı ortam varsayımlarından kaynaklanır.

  • Tarayıcı: OS zaman dilimi ayarlarını ve tarayıcı dilini kontrol edin. Sonra loglayın:
console.log(Intl.DateTimeFormat().resolvedOptions());
  • Node.js / sunucu: prosesin zaman dilimini doğrulayın:
console.log('TZ:', process.env.TZ);
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone);

Sunucunuz UTC'de çalışırken laptopunuz yerel bir bölgedeyse, formatlanmış çıktı timeZone açık belirtilmediği sürece farklı olur.

3) Zamanın en çok kırıldığı yerlerde testler ekleyin

DST sınırları ve "uç" zamanlar etrafında ünite testleri oluşturun:

  • İlgili bölgedeki DST geçişinden bir saat önce ve bir saat sonra
  • Ay/ yıl sonu ve 23:3000:30 geçişleri
  • Ürününüz birden fazla zaman dilimi destekliyorsa birden fazla bölge

Hızlı iterasyon yapıyorsanız, bu testleri iskeletinize ekleyin. Örneğin React + Go uygulaması üretirken Koder.ai ile küçük bir "zaman kontratı" test paketi eklemek regreksiyonların dağıtımdan önce yakalanmasını sağlar.

Hızlı yayına alma kontrol listesi

  • Girdiler açık sözleşmeye sahip: epoch milisaniyeleri veya ofsetli ISO 8601.
  • "2025-03-02 10:00" gibi belirsiz stringler yok.
  • Formatlama her zaman locale ve (gerekirse) timeZone belirtir.
  • Testler hedef bölgeleriniz için DST sınırlarını kapsar.

Güvenilir zaman işleme için önerilen desenler

JavaScript'te güvenilir zaman işleme büyük ölçüde bir "gerçek kaynak" seçip saklamadan gösterime kadar tutarlı olmaktır.

Basit bazı en iyi uygulamalar

UTC'de saklayın ve hesaplayın. Kullanıcıya yönelik yerel zamanı yalnızca sunum detayı olarak ele alın.

Sistemler arası iletimde ISO 8601 stringleri ofsetle birlikte gönderin (tercihen Z). Numerik epoch göndermeniz gerekiyorsa, alan adıyla birimi belgeleyin ve tutarlı olun (createdAtMs gibi). UI için Intl.DateTimeFormat (veya toLocaleString) ile biçimlendirin; deterministik çıktı gerekliyse açık timeZone verin.

Karar rehberi: DB vs API vs UI

  • Veritabanı: bir anı UTC olarak saklayın (epoch ms veya UTC datetime tipi). Eğer domain gerçekten duvar saati zamanlarını saklıyorsa (örn. "mağaza 09:00'da açılır"), yerel zamanlara izin verin.
  • API sınırları: Z içeren ISO 8601 tercih edin (2025-12-23T10:15:00Z). Epoch kullanıyorsanız alan adı createdAtMs gibi bir isimle birimi belli edin.
  • UI: saklı UTC anı alın ve kullanıcı locale'ine göre formatlayın. Planlama UI'larında zaman dilimini açıkça gösterin ve dönüşümleri kasıtlı yapın.

Bir kütüphane kullanmak ne zaman değerli olur

Tekrarlayan etkinlikler, karmaşık zaman dilimi kuralları, DST-güvenli aritmetik ("yarın aynı yerel zaman") veya tutarsız girdilerden çokça ayrıştırma gerekiyorsa özel bir tarih-saat kütüphanesi düşünün. Değer, daha temiz API'ler ve daha az uç durum hatasında yatar.

Eğer daha derine inmek isterseniz, zamanla ilgili daha fazla rehbere /blog sayfasında göz atabilirsiniz. Araç veya destek seçeneklerini değerlendiriyorsanız, /pricing bölümüne bakın.

SSS

JavaScript'te zaman damgaları için hangi biçimi kullanmalıyım?

Dahili biçim olarak epoch milisaniyelerini veya UTC ISO 8601 dizgesini kullanın. Değeri yalnızca bir kişiye gösterirken yerel biçime dönüştürün.

Unix zaman damgam neden 1970'te bir tarihe dönüşüyor?

JavaScript Date milisaniye bekler. Saniye cinsinden bir Unix zaman damgasını new Date() işlevine vermeden önce 1000 ile çarpın.

Aynı tarih neden farklı bilgisayarlarda farklı saatler gösteriyor?

Bir Date tek bir anı saklar, ancak JavaScript bunu genellikle bilgisayarın yerel saat diliminde gösterir. Verinin mi değiştiğini yoksa yalnızca görünümün mü değiştiğini görmek için toISOString() ile toString() sonuçlarını karşılaştırın.

Bir tarihin bir gün kaymasını nasıl önlerim?

Doğum günü veya fatura tarihi gibi yalnızca tarih içeren bir değeri YYYY-MM-DD olarak saklayın. Amaçlanan saat dilimini de tanımlamadıkça onu Date nesnesine dönüştürmeyin.

Bir API için en güvenli tarih biçimi nedir?

UTC için Z içeren 2025-03-04T12:30:00Z gibi tam bir ISO 8601 değeri gönderin ya da açık bir ofset ekleyin. 03/04/2025 gibi dizgelerden kaçının, çünkü insanlar ve tarayıcılar bunları farklı yorumlayabilir.

Kullanıcılar için tarihleri nasıl biçimlendirmeliyim?

Intl.DateTimeFormat kullanın ve ekranın sabit bir saat dilimine ihtiyacı olduğunda timeZone belirtin. Tarihleri elle dizge oluşturmadan kullanıcının yerel ayarlarına göre biçimlendirir.

Kullanıcının girdiği tarihler için Date.parse kullanmalı mıyım?

Belirsiz veya gündelik dizgeler için buna güvenmeyin. API'lerden bilinen bir ISO biçimini kabul edin ya da denetimli kullanıcı girdilerini kendi tanımladığınız kurallarla ayrıştırın.

Geri sayım veya süre için Date kullanmaktan neden kaçınmalıyım?

Bir Date takvimdeki bir anı belirtirken süre yalnızca bir zaman miktarıdır. Süreleri saniye veya milisaniye olarak saklayın, ardından görüntülerken sayıyı biçimlendirin.

Yaz saati uygulaması JavaScript tarihlerini nasıl etkiler?

Geçen süre hesaplamaları için epoch milisaniyelerini kullanın. Adlandırılmış bir saat diliminde «yarın sabah 9:00» gibi programlar için takvim tabanlı işlemler kullanın ve DST geçiş tarihlerini test edin.

JavaScript'teki bir zaman hatasını ayıklamanın en hızlı yolu nedir?

Ham girdiyi, toISOString(), toString() ve getTimezoneOffset() değerlerini günlüğe kaydedin. Hatalı bir ISO değeri çoğu zaman ayrıştırma veya birim sorununu gösterirken farklı bir yerel dizge genellikle saat dilimi gösterim farkını belirtir.

Related posts