Methodology
Yaş hesaplama metodolojisi
Takvim farkındalıklı ödünç alma, naif bölme değil. Naif kodun biriktirdiği 4 günlük hata.
By Buğra SözeriPublished
Yaşı yıllar-aylar-günler cinsinden hesaplamak basit görünür. Değildir. Naif “bugün eksi doğum günü bölü 365,25” yaklaşımı, gerçek yıllar sabit sayıda gün içermediğinden dört ila yedi yılda yaklaşık bir gün sapma biriktirir. Doğru algoritma takvim ödünç almayı kullanır — ilkokul çıkarma mantığıyla aynı, ancak değişken uzunluklu “basamaklar” ile.
Aydan ödünç alma algoritması
Bir doğum tarihi (dY-dA-dG) ve bugün (bY-bA-bG) verildiğinde:
- Yıl farkı:
bY − dY. - Ay farkı:
bA − dA. Negatifse, yıl sayısından 1 ödünç alın: yıl farkından 1 çıkarın, ay farkına 12 ekleyin. - Gün farkı:
bG − dG. Negatifse, ay sayısından 1 ödünç alın: ay farkından 1 çıkarın, gün farkına önceki ayın uzunluğunu ekleyin.
3. adım çoğu uygulamanın hata yaptığı yerdir. “Önceki ayın uzunluğu” sabit 30 değildir — hangi ay ve (Şubat için) hangi yıl olduğuna bağlı olarak 28, 29, 30 veya 31’dir.
Çalışan örnek
Doğum: 1990-12-31. Bugün: 2026-03-15.
- Yıl farkı: 2026 − 1990 = 36.
- Ay farkı: 3 − 12 = −9. Ödünç: yıl farkı 35’e düşer, ay farkı 3 olur.
- Gün farkı: 15 − 31 = −16. Ödünç: ay farkı 2’ye düşer, gün farkına önceki ayın uzunluğu eklenir. Önceki ay Şubat 2026 (28 gün, artık yıl değil). Gün farkı = −16 + 28 = 12.
Sonuç: 35 yıl, 2 ay, 12 gün.
Önceki ay uzunluğu hilesi
JavaScript’te “önceki ay kaç günlük?” sorusunu sormanın en temiz yolu:
new Date(year, month, 0).getDate() // (ay - 1)'in son gününü döndürür. // N ayının 0. günü, N-1'in son günü olarak yorumlanır.
Bu, artık yıl Şubat doğruluğunu otomatik olarak işler çünkü Date bunu bilir. new Date(2024, 2, 0).getDate() 29 döndürür; new Date(2023, 2, 0).getDate() 28 döndürür.
Artık yıl doğum günleri (29 Şubat)
29 Şubat doğumlu kişiler tekrarlayan bir soru doğurur: artık olmayan yıllarda doğum günleri ne zaman? İki gelenek:
- 1 Mart’a yuvarlama — İngiltere, Hong Kong varsayılanı.
- 28 Şubat’a yuvarlama — ABD, Tayvan, Yeni Zelanda varsayılanı. Hesaplayıcı bunu kullanır.
Bu seçim, artık olmayan yıllarda “N yaşına girdiniz” anının ne zaman gerçekleştiğini etkiler. Çoğu amaç için önemli değildir — temel doğum tarihi hâlâ 29 Şubat’tır ve fark artık olmayan yıl başına bir gündür.
Neden “gün / 365,25” sapma yaratır
365,25, 400 yıllık Gregoryen döngüsü üzerindeki bir yılın ortalama uzunluğudur. Herhangi bir bireysel yıl 365 veya 366 gündür. Kısa zaman pencerelerinde ortalama iyi bir yaklaşım değildir:
- 4 yıl tam 1 artık yıl içerir → 1461 gün → tam 365,25. İyi.
- Sapma yüzyıl kuralından kaynaklanır: 1900 bir artık yıl değildi (100’e bölünebilir, 400’e değil). 2000 artık yıldı. 1900 veya 2100’ü kapsayan yaşları 365,25 yaklaşımıyla hesaplamak görünür gün düzeyinde hatalar üretir.
Yaş hesaplaması için takvim ödünç alma her zaman kesindir. Naif yaklaşım kabataslak tahminler için sorunsuz, ancak pasaport veya doğum belgesiyle eşleşmesi gereken durumlar için yanlıştır.
Algoritma ayrıntıları: eksiksiz aydan ödünç alma
Tam referans uygulaması satır içinde yeniden üretilecek kadar kısadır; sürpriz olan, gün-0 hilesinin değişken-ay-uzunluğu sorununu çözdükten sonra kaç az dallanmaya ihtiyaç duyulduğudur.
function age(birth: Date, today: Date) {
let y = today.getFullYear() - birth.getFullYear();
let m = today.getMonth() - birth.getMonth();
let d = today.getDate() - birth.getDate();
if (d < 0) {
// Önceki aydan gün ödünç al — 0. gün önceki ayın son gününü döndürür.
const prevMonthLen = new Date(today.getFullYear(), today.getMonth(), 0).getDate();
d += prevMonthLen;
m -= 1;
}
if (m < 0) {
m += 12;
y -= 1;
}
return { years: y, months: m, days: d };
}Algoritma O(1) sürede çalışır, bölme ve kayan nokta aritmetiği içermez ve takvim kütüphanesi gerektirmez. Tek spesifikasyon odaklı dal artık yıl işlemedir — o da Date’e devredilir; bu ECMA-262’den gelen Gregoryen kuralını uygular.
100 yıllık bir süre için naif gün sayma yaklaşımıyla karşılaştırma:
| Yöntem | 1925-01-01 → 2025-01-01 sonucu | Hata |
|---|---|---|
| Ödünç alma algoritması | 100 yıl, 0 ay, 0 gün | 0 gün (kesin) |
| (gün) / 365,25 | 99,9999 yıl → 99’a yuvarlanır | ~1 gün (sessiz yanlış sayım) |
| (gün) / 365 | 100,07 yıl | ~25 gün |
Kaynaklar ve referanslar
Artık yıl kuralı 1582 Gregoryen reformuna (Inter Gravissimas) dayanır; kabul ettiğimiz tarih biçimi ISO 8601’dir; önceki ay uzunluğu hilesi ECMA-262’de iyi tanımlanmış ECMAScript davranışıdır. 29 Şubat doğum günü yuvarlama gelenekleri yargı yetkisine özgüdür ve ulusal mevzuata dayanır — yargı bölgesi tablosu için yaş hesaplama yöntemleri rehberimize bakın.
Varsayımlar ve sınırlamalar
- Yalnızca Gregoryen takvimi. Hicri, İbrani, Çin ay ve Jülyen takvimleri farklı algoritmalar gerektirir; dönüştürücü takvim sistemi seçimini açığa çıkarmaz.
- Yalnızca tarih, tarih-saat değil. Girdiler kullanıcının yerel saat diliminde gece yarısına kesilir. Yaz saati geçişleri sonucu etkilemez.
- 29 Şubat → 28 Şubat yuvarlama.Varsayılan olarak ABD geleneğini kullanırız. İngiltere / HK yargı bölgelerindeki kullanıcılar artık olmayan yıllarda “N yaşına girdiniz” işaretine bir gün eklemelidir.
- Gregoryen öncesi destek yok. 1582-10-15 öncesindeki doğum tarihleri proleptik Gregoryen uzantısını kullanır — tarihsel olarak bunlar Jülyen tarihi olarak kaydedilmiş ve modern karşılaştırma için 10-13 gün ileriye alınmış olurdu.
- Artık saniye işleme yok. Artık saniyeler takvim günü aritmetiğini etkilemez; UTC ve TAI hassasiyetine ihtiyacınız varsa farklı bir araç kullanın.
- Gelecek tarihler sıfır döndürür, negatif değil. Negatif yaş neredeyse her zaman gerçek bir sonuç değil, bir UX hatasıdır.
Hesaplayıcının ele aldığı uç durumlar
- Gelecekteki doğum tarihleri — negatif yaş yerine sıfır döndürürüz. Negatif yaş bir hata yüzeyidir.
- Bugün doğum tarihine eşit — 0 yıl, 0 ay, 0 gün.
- Yaz saati geçişleri boyunca — hesaplayıcı yalnızca tarih matematiği kullanır (saat yok), bu nedenle yaz saati değişiklikleri sonucu etkilemez.
Frequently asked questions
- Convertitive yaşı yıllar, aylar ve günler cinsinden nasıl hesaplar?
- Takvim ödünç alma algoritmasını kullanırız: yıl, ay ve gün ham farkını hesaplar, bir bileşen negatife döndüğünde bir üst birimden ödünç alırız. Gün ödünç alımında artık yıl Şubat doğruluğunun otomatik işlenmesi için JavaScript'in Date(year, month, 0).getDate() yöntemiyle önceki ayın tam uzunluğu (28, 29, 30 veya 31 gün) kullanılır.
- Convertitive neden yaş hesaplamak için gün / 365,25 kullanmıyor?
- 365,25, tam 400 yıllık Gregoryen döngüsündeki ortalama yıl uzunluğudur; ancak herhangi bir tek yıl tam olarak 365 veya 366 gündür. Ortalama kullanmak birkaç yılda bir yaklaşık 1 günlük sapma ve tarih aralığı 1900 (artık yıl değil) veya 2100 gibi bir yüzyıl yılını kapsadığında görünür hata üretir. Ödünç alma algoritması O(1) karmaşıklığa sahiptir, kayan nokta aritmetiği içermez ve her zaman kesindir.
- 29 Şubat doğum günleriyle artık olmayan yıllarda ne olur?
- Convertitive varsayılan olarak 29 Şubat'ı 28 Şubat'a yuvarlar — ABD, Tayvan ve Yeni Zelanda geleneği. İngiltere ve Hong Kong geleneği 1953 tarihli Doğum ve Ölüm Kayıt Yasası uyarınca 1 Mart'a yuvarlama yapar. İki gelenek artık olmayan yıllarda bir gün farklılık gösterir; evrensel olarak doğru tek bir gelenek yoktur.
- Hesaplayıcı hangi takvim sistemini kullanıyor?
- Yalnızca proleptik Gregoryen — 1582 Inter Gravissimas reformundan gelen artık yıl kuralı (4'e bölünebilir, yüzyıllar hariç, 400'lük yüzyıllar hariç). Hicri, İbrani, Çin ay takvimi ve Jülyen takvimi girdileri desteklenmez. 1582-10-15 öncesindeki tarihler, kayıtlı Jülyen tarihlerinden 10–13 gün farklılık gösteren proleptik Gregoryen uzantısını kullanır.
- Yaz saati geçişi yaş sonucunu etkiler mi?
- Hayır. Hesaplayıcı zaman damgaları değil takvim tarihleri üzerinde çalışır. Girdiler yerel saat diliminde gece yarısı olarak ele alınır ve zaman bileşeni yoktur; bu nedenle yaz saati uygulaması geçişi gün sayısını etkilemez.
Related
Published May 15, 2026