Возраст (+ високосный год) расчет в Javascript?
Я прочитал этот question, но было много комментариев, которые, по словам некоторых, были точными, а некоторые говорили, что это не точно.
В любом случае у меня есть этот код, который вычисляет возраст человека в Javascript:
function calculateDiffYearByString(date)
{
var cur = new Date();
var diff = (cur.getTime() - new Date(date)) / (60 * 60 * 24 * 1000);
return diff / 365.242;
}
Теперь,
эта часть var diff = (cur.getTime() - new Date(date)) / (60 * 60 * 24 * 1000);
делает все фактические дни (24 часа) с даты начала до конца даты , включая високосный год.
Он просто подсчитывает дни на 24-часовой группе.
мой вопрос о / 365.242;
когда я спросил Google, он сказал:
![enter image description here]()
Вот почему я делю его на 365.242.
но я думаю, что я ошибаюсь. becuase (IMHO) часть .242
относится к високовому году. поэтому я думаю, что боюсь, что високосный год рассматривается в общем расчете дважды..
Неужели я ошибаюсь? мой расчет на 100% правильный?
Ответы
Ответ 1
Расчет неправильный, из-за предположения, что год составляет 365.242 дня.
Год в среднем 365.242 дня, но нет фактического года, равного 365.242 дням. Год - ровно 365 или 366 дней (игнорируя небольшую деталь, что есть несколько лет, у которых есть прыжки секунд.)
Чтобы точно рассчитать возраст как дробные годы, вам нужно было бы рассчитать все количество лет до последнего дня рождения, а затем рассчитать долю за текущий год в зависимости от того, сколько дней в текущем году.
Вы можете использовать такой код, чтобы рассчитать точный возраст в годах:
function isLeapYear(year) {
var d = new Date(year, 1, 28);
d.setDate(d.getDate() + 1);
return d.getMonth() == 1;
}
function getAge(date) {
var d = new Date(date), now = new Date();
var years = now.getFullYear() - d.getFullYear();
d.setFullYear(d.getFullYear() + years);
if (d > now) {
years--;
d.setFullYear(d.getFullYear() - 1);
}
var days = (now.getTime() - d.getTime()) / (3600 * 24 * 1000);
return years + days / (isLeapYear(now.getFullYear()) ? 366 : 365);
}
var date = '1685-03-21';
alert(getAge(date) + ' years');
Демо: http://jsfiddle.net/Guffa/yMxck/
(Примечание: дни также являются дробным значением, поэтому он рассчитает возраст до точной миллисекунды. Если вы хотите целых дней, вы добавили бы Math.floor
вокруг вычисления для переменной days
.)
Ответ 2
Ваш расчет diff
даст вам количество дней между двумя датами. Он будет учитывать високосные годы, поэтому в течение ровно 4 лет он даст (365 * 4) + 1
дней.
Он также будет считать частичные дни, поэтому, если параметр date
будет днем, а сегодня он равен 6 утра, тогда diff
будет 0.75
.
Как вы конвертируете дни с годами, зависит от вас. Используя 365, 365.242 или 365,25 дней в году, все они являются обоснованными в реферате. Однако, поскольку вы вычисляете возраст людей в соответствии с их днями рождения, я бы сделал это следующим образом http://jsfiddle.net/OldPro/hKyBM/:
function noon(date) {
// normalize date to noon that day
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 12, 0, 0, 0);
}
// Takes a Date
function getAge(date) {
var now = noon(new Date()),
birthday = noon(date),
thisBirthday = new Date(birthday),
prevBirthday,
nextBirthday,
years,
partYear,
msInYear;
thisBirthday.setFullYear(now.getFullYear());
if (thisBirthday > now) { // not reached birthday this year
nextBirthday = thisBirthday;
prevBirthday = new Date(thisBirthday);
prevBirthday.setFullYear(now.getFullYear() - 1);
}
else {
nextBirthday = new Date(thisBirthday);
nextBirthday.setFullYear(now.getFullYear() + 1);
prevBirthday = thisBirthday;
}
years = prevBirthday.getFullYear() - birthday.getFullYear();
msInYear = nextBirthday - prevBirthday;
partYear = (now - prevBirthday) / msInYear;
return years + partYear
}
Другими словами, я вычисляю дробный год как количество дней с момента последнего дня рождения, деленное на количество дней между предыдущим днем рождения и следующим днем рождения. Я думаю, именно так большинство людей думают о днях рождения и годах.
Примечание. При преобразовании строк даты в даты вы можете столкнуться с проблемами с часовыми поясами. Короткие даты ISO 8601, такие как "2013-05-14", интерпретируются как полуночный UTC, который делает эту дату 13 мая, а не 14 мая в США и во всем мире с отрицательными смещениями UTC. Поэтому будьте осторожны.
Ответ 3
То, как вы вычисляете разницу между слишком датами, даст вам результат в дни, и он учитывает високосные годы.
Тем не менее, ваша функция предназначена для возврата значения в годах, поэтому вам нужно преобразовать свое устройство из нескольких дней в несколько лет, для этого преобразования требуется .242, чтобы быть точным, поэтому кажется, что ваша логика звучит.
Изменить: для получения возврата, аналогичного ожидаемому от калькулятора возраста, вы должны получить день, месяц и год обеих дат, используйте дни и месяцы, чтобы проверить, не происходит ли день после или перед другим дату, а затем вычесть годы и, возможно, добавить 1, например:
function getAge(dateStr) {
var cur = new Date();
var tar = new Date(dateStr);
// Get difference of year
var age = cur.getFullYear() - tar.getFullYear();
// If current month is > than birth month he already had a birthday
if (cur.getMonth() > tar.getMonth()) {
age ++;
}
// If months are the same but current day is >= than birth day same thing happened
else if (cur.getMonth() == tar.getMonth() && cur.getDate() >= tar.getDate()) {
age ++;
}
return age;
}
Вы можете поиграть s >= или сравнить часы, чтобы получить более подробную информацию, но этого должно быть достаточно для большинства требований расчета возраста.
По существу, использование .242 даст вам более точный результат с научной точки зрения, однако расчет возраста не является точным с точки зрения обществ.