I'm trying to write a program to calculate my exact age, to the day, to be outputted to a string, to be displayed on my website. My code so far is the following:
// establishing today's date
let currentTime = new Date();
let month = currentTime.getMonth() + 1;
let day = currentTime.getDate();
let year = currentTime.getFullYear();
// my birthdate
const birthMonth = 7;
const birthDay = 24;
const birthYear = 2004;
// comparing the two dates
let monthDifference = Math.abs(month - birthMonth);
let dayDifference = Math.abs(day - birthDay);
let yearDifference = Math.abs(year - birthYear);
// save and return the difference in a readable format
let comparison = `${yearDifference} year, \
${monthDifference} month, ${dayDifference} day`;
document.getElementById("birthday paragraph").innerText = `I \
am a ${comparison} old programmer from Concord, Ohio.`;
<div id="birthday paragraph"></div>
However, as you can see on crossflame22.github.io (if I haven't already fixed it), it displays the incorrect day. Today, it's showing 1 month, 5 days. I have no idea how to fix this.
Short answer: Use a library (like date-fns) instead of trying to use simple differences. There is almost never a good reason to try to do time difference calculations yourself across days, as you will undoubtedly do it wrong. If you adamantly want to do this, you need to handle a lot of edge cases.
Long answer: Your current logic doesn't account for leap years (which add days to your life), but it also assumes that being in and adjacent month credits you with a whole month. As an example, say you were born on July 31, 2021. Your code would imply you are immediately 1 month old on Aug 1, 2021 (even though clearly you are only 1 day old). You could probably do something like what you're doing if months were the same length (they aren't) and years were the same length (they aren't). Even days can have different lengths (see leap seconds), which can impact longer term calculations. Hence why you should look into a library designed to handled these edge cases for you.
The above answer by rfestag is good advice.
However, let's take a look at the problem and perhaps offer a simple approach.
As rfestag pointed out, date computations are very complex due to leap years, months being different lengths, and so on.
Forget years for a minute, and consider what it means to say "X months old"?
A baby born on Jan 1 is 3 months old on March 31 (90 days).
A baby born on July 1 is 3 months old on Sept 30 (92 days).
Those two "3 month old" babies are not the exact same age!
So try this approach:
Compute the difference between the two days, then convert that to approximate (years, months, days).
// get your inputs however you like, I'll just hard code them
const today = new Date();
const baseday = new Date("July 24, 2004");
let difference = today - baseday;
difference /= 24*3600*1000; // convert milliseconds to days
let yeardiff = Math.floor(difference/(365.25)); // whole number of average years
let monthdiff = (difference - yeardiff*365.25); // last partial year
let averagemonth = 365.25/12; // length of average month
let months = Math.floor(monthdiff/averagemonth);
let daysleft = Math.floor(monthdiff - months * averagemonth);
console.log(yeardiff + " years, " + months + " months, " + daysleft + " days");
For some days of the year (around the start of months mostly), it may be off in the days, but for general purposes it should be good enough.