8

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 ?

Community
  • 1
  • 1
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • Uh oh, reminds me of Jon Skeet's presentation. Why would you count date diff in such way? – Petteri H May 08 '13 at 08:33
  • Sorry, I don't have a question about your topic....how did you get the screenshot to have that tear effect on the right and bottom sides? :) – David May 08 '13 at 08:33
  • @PetteriHietavirta (i also saw the representation -- with Tony :-)) anyway - I know there are other alternatives. but I want to be corrected for my mistake. ( if any) , this way I'll understand better where are my mistakes :-) – Royi Namir May 08 '13 at 08:34
  • 1
    @david99world http://www.faststone.org/FSCaptureDetail.htm – Royi Namir May 08 '13 at 08:34
  • If a person is born on January 28 2012 and you ask for her age on February 29, 2012, what's the result you expect? What's the result on March 1, 2012? – likeitlikeit May 15 '13 at 15:11

4 Answers4

9

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.)

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • and how can i know for a given year [y] - how many exactly days ? – Royi Namir May 08 '13 at 08:57
  • @RoyiNamir: You can create a `Date` object for the 28 of february that year, then add a day to it. If the date is still in february, the year has 366 days. – Guffa May 08 '13 at 08:59
  • @alex23: The result as approximately correct, but the function returns an exact value that is never exactly correct. Calculating a year length average that is correct is a lot more complicated than simply calculating the exact number of years. – Guffa May 08 '13 at 09:07
  • @alex23: The OP asks "does my calculation is 100% correct ?". The simple answer to that is that it never is, except for the one special case where the age is exactly zero. – Guffa May 08 '13 at 21:26
  • @Guffa I opened a bounty . Im looking for a piece of code which will achieve the most accurate resolution.( day resolution). – Royi Namir May 14 '13 at 13:43
  • Thanks for your effort Guffa. Q: Doesn't the calculation needs to be made against UTC times ? – Royi Namir May 14 '13 at 17:42
  • @RoyiNamir: Interresting point. That depends on whether you want the days when daylight savings time changes to be counted as 1.042 and 0.958 days, or as regular days. – Guffa May 14 '13 at 19:53
  • @Guffa can you explain about the 1.042 and 0.958 ?( what are those ? ) – Royi Namir May 15 '13 at 06:48
  • @RoyiNamir: The day when daylight saving time starts contains 23 hours, and when it ends it contains 25 hours. 23 hours is about 0.958 normal days, and 25 hours is about 1.042 normal days. – Guffa May 15 '13 at 07:55
  • Since birth dates are given as days, not times, I don't think it makes sense to count fractional days. I also think it is wrong to consider whether the current year is a leap year or not in the same way for people born in January as for people born in March. See [my answer](http://stackoverflow.com/a/16550728/712765) for how I would handle this. – Old Pro May 15 '13 at 08:33
  • I don't think it's working for all ranges of dates :( for range : "11/12/1864" -"04/10/1866" it should return 2 years but 1 is returned – Pavel Durov Sep 29 '19 at 10:12
2

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.

Old Pro
  • 24,624
  • 7
  • 58
  • 106
  • Hi. let's say God has been with me since the day I was born and he counts the days - day by day. its calculation would be : `var now = new Date(); var utc = new Date(Date.UTC( now.getFullYear(), now.getMonth(), now.getDate()))-Date.UTC(1978,11,22); alert(utc/1000/60/60/24) //` the result is 12563(**days**). now how can i make years (and days) from this number ? – Royi Namir May 15 '13 at 11:13
  • 12563/365 = nominal years. 12563/356.25 approximate calendar years in the period 1901-2099. 12563/365.242 number of complete orbits of earth around the sun. Or use my calculation and get 34.394406392694066. Or use 12563/360 and get the number of banking years. Or use the Jewish or Islamic if God is Yaweh or Allah. – Old Pro May 15 '13 at 17:35
  • Thanks for reply. Q1: if the first calculation is approximate years , and the second is complete orbits around the sun , so what does _your_ calculation represents ? ( what meaning) .Q2 : if you were required to build a soft which allows a person to do some action only if his age is 20 and a quarter. what method would you choose ? youll have the days , but in what value would you divide those days ? – Royi Namir May 16 '13 at 05:47
  • My calculation represents how I (and I assume most people in the US) think of a person's age in years. I would use my calculation above in all situations dealing with the age of a person under US customs when no explicit definition applies. I would NOT use my calculation for astronomical calculations. If there is a legal requirement, I would look at the definition in the law. Usually the law is not written in fractions of a year but would say something like age 16 years and 6 months. That would be a whole different calculation for which you should ask a new question. – Old Pro May 16 '13 at 05:59
1

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.

cernunnos
  • 2,766
  • 1
  • 18
  • 18
  • Does every years contains .242 ? doesnt the .242 part is also leap year considirable ? – Royi Namir May 08 '13 at 08:50
  • the .242 allows you to convert in an exact manner, leap years exist to facilitate the average persons life, after all it would be annoying to have to wait about 6 hours after midnight to celebrate the new year :) – cernunnos May 08 '13 at 08:52
0

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)
T.O.M
  • 81
  • 1
  • 7