Royi Namir
Royi Namir

Reputation: 148524

Age (+leap year) calculation in Javascript?

I've read this question but there were many comments which some said it was accurate and some said it wasn't accurate.

Anyway I have this code which calc person's age in Javascript :

 function calculateDiffYearByString(date)
    {
        var cur = new Date();
        var diff = (cur.getTime() - new Date(date)) / (60 * 60 * 24 * 1000);
        return diff / 365.242;
    }

Now , this part var diff = (cur.getTime() - new Date(date)) / (60 * 60 * 24 * 1000); does consider all actual days (24 hr) from the start date till end date including leap year consideration.

It just count days by a 24 hr's groups. my question is about the / 365.242;

when I asked google , it said :

enter image description here

Which is why I devide it with 365.242.

but I think i'm wrong. becuase (IMHO) the .242 part is regarding the leap year. so I think I'm afraid the leap year is considered in the overall calculation twice ..

Am I wrong? does my calculation is 100% correct ?

Upvotes: 8

Views: 11011

Answers (4)

T.O.M
T.O.M

Reputation: 81

Simple passing age you will get a leap years array and the number of years in enter age

please run the code to get a result

// Simple passing age you will get  leap years array and number of years
let currentAge = 80;
let deathYear = 2010

function getLeapYears(currentAge,deathYear){
    const currentYear = new Date().getFullYear() 
    let getBirthYear = 0 
    if(deathYear){
        getBirthYear = deathYear-currentAge
    }
    else{
        getBirthYear = currentYear-currentAge
    }
    
    let numberOfYears = []
    for(let index = getBirthYear; index<currentYear+1;index++ ){
    numberOfYears.push(index)
    }
    
    let leapYears = []
    leapYears= numberOfYears.filter(item => item % 4 ==0)
    return {
        leapYears:leapYears,
        numberOfYears:leapYears.length +1
    }
    
}

const result1 = getLeapYears(currentAge)
const result2 = getLeapYears(currentAge,deathYear)
console.log("result1",  result1)
console.log("result2",  result2)

Upvotes: 0

Old Pro
Old Pro

Reputation: 25547

Your diff calculation will give you the number of days between the two dates. It will take into account leap years, so over exactly 4 years it will yield (365 * 4) + 1 days.

It will also count partial days so if the date parameter is noon yesterday and today it is 6am then diff will be 0.75.

How you convert from days to years is up to you. Using 365, 365.242, or 365.25 days per year all are reasonable in the abstract. However, since you are calculating people's ages according to their birthdays, I would do it like this 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
}

In other words, I compute the fractional year as number of days since the last birthday divided by the number of days between the previous birthday and the next birthday. I think that is how most people think of birthdays and years.

Note: You can get into trouble with timezones when converting date strings to Dates. Short ISO 8601 dates like '2013-05-14' are interpreted as midnight UTC which makes that date May 13, not May 14 in the US and everywhere else with negative UTC offsets. So be careful.

Upvotes: 2

Guffa
Guffa

Reputation: 700362

The calculation is not correct, because of the assumption that a year is 365.242 days.

A year is by average 365.242 days, but there is no actual year that is 365.242 days. A year is either exactly 365 or 366 days (ignoring the small detail that there are some years that have leap seconds.)

To calculate the age as fractional years exactly, you would have to calculate the whole number of years up to the last birthday, and then calculate the fraction for the current year based on how many days the current year has.


You can use code like this to calculate the exact age in years:

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');

Demo: http://jsfiddle.net/Guffa/yMxck/

(Note: the days is also a fractional value, so it will calculate the age down to the exact millisecond. If you want whole days, you would add a Math.floor around the calculation for the days variable.)

Upvotes: 9

cernunnos
cernunnos

Reputation: 2806

The way you calculate the difference between too dates will give you a result in days, and it does take into account leap years.

However, your function is meant to return a value in years, so you need to convert your unit from days to years, this conversion needs the .242 in order to be exact, so it appears your logic is sound.

Edit: In order to obtain a return similar to what is expected from an age calculator you have to get the day, month and year of both dates, use the days and months to check whether the day is after or before the other date, and then subtract the years and optionally add 1, for instance:

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;
}

You can fiddle with the >= or compare hours to get more detailed, but this should be enough for most age calculation requirements.

Essentially, using the .242 will give you a more exact result from a scientific point of view, however age calculation is not exact from a societies point of view.

Upvotes: 1

Related Questions