Çünkü "aylardaki yaş" tanımıdır... esnek, en kolay yol, kafanızda hesaplayacağınız gibi küçük bir aritmetik kullanmaktır ve Date
sınıf.
"Aylardaki yaş" ın [a] insan yorumu için kural şu şekildedir
İki tarih arasındaki farkı ay cinsinden hesaplayın,
sanki ayın günü her iki tarih için de ayın 1'i gibi
Son ayı hariç tutmak için 1'i çıkarın
Ardından, dönemin son gününün ayın günü açıksa
veya dönemin ilk gününün ayın gününden sonra [potansiyel olarak kısmi] son ayı tamamlanır: sayımı geri yüklemek için 1 ekleyin
Merhemdeki tek sinek, aylar farklı sayıda gün içerdiğinden, 2 ayın gün sayılarında farklılık gösterdiği durumlarla ilgilidir.
Bununla birlikte, bitiş ayı başlangıç ayından kısaysa, sınır koşulunun hiçbir zaman karşılanamayacağı bir duruma girebilirsiniz (örneğin, başlangıç tarihi 28 Şubat ve bitiş tarihi 31 Mart'tır. Bunu düzeltmek için," ayın sonu " na, başlangıç ayının son gününden bitiş ayının son gününe kadar değişen bir pencere olarak bakmanız gerekir.
Bu, bu koda yol açar. Bir tarihi temsil etmek için aşağıdaki gibi bir yapı kullanıyorum:
{
year: 2021 , // 4-digit year
month: 11 , // month of year (1-12 mapping to January-December)
day: 23 // day of month (1-[28-31] depending on year/month
}
Bu yapıdaki verilerin geçerli bir tarihi temsil ettiğinden emin olmak, okuyucu için bir alıştırma olarak bırakılır.
Kod o kadar karmaşık değil:
/**
*
* @param {object} bgn - start date of period
* @param {number} bgn.year - 4-digit year
* @param {number} bgn.month - month of year [1-12]
* @param {number} bgn.day - day of month [1-31]
*
* @param {object} end - end date of period
* @param {number} end.year - 4-digit year
* @param {number} end.month - month of year [1-12]
* @param {number} end.day - day of month [1-31]
*
*/
function diffInMonths( bgn , end ) {
const between = ( x , min , max ) => x >= min && x <= max;
// We'll need to add back the final month based on the following:
// - end.day >= bgn.day -- we've passed the month boundary, or
// - end.day is within the end-of-month window
// (when the end month is shorter than the start month)
const needAdjustment = end.day >= bgn.day
|| between( end.day, daysInMonth(bgn), daysInMonth(end) );
const finalMonthAdjustment = needsAdjustment ? 1 : 0;
const deltaM = 12 * ( end.year - bgn.year )
+ ( end.month - bgn.month )
- 1 // remove the final month from the equation
+ finalMonthAdjustment // add in the precomputed final month adjustment
;
return deltaM;
}
/**
*
* @param {object} dt - date
* @param {number} dt.year - 4-digit year
* @param {number} dt.month - month of year [1-12]
* @param {number} dt.day - day of month [1-31]
*
*/
function daysInMonth(dt) {
const leapYear = ( dt.year % 4 === 0 && dt.year % 100 !== 0 ) || dt.year % 400 === 0;
const monthDays = leapYear ? daysPerMonthLeap : daysPerMonth;
const days = monthDays[dt.month];
return days;
}
// jan feb mar apr may jun jul aug sep oct nov dec
// ---------- --- --- --- --- --- --- --- --- --- --- --- ---
const daysPerMonth = [ undefined, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ];
const daysPerMonthLeap = [ undefined, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, ];
new Date(userDate.split('/').reverse())
neredeyse kesinlikle geçersiz bir Tarih döndürür.