Возраст (+ високосный год) расчет в 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 даст вам более точный результат с научной точки зрения, однако расчет возраста не является точным с точки зрения обществ.