Skip to content

Instantly share code, notes, and snippets.

@sacah
Last active September 18, 2021 00:57
Show Gist options
  • Save sacah/2df59fd483311a2b41d1cb3b679acd91 to your computer and use it in GitHub Desktop.
Save sacah/2df59fd483311a2b41d1cb3b679acd91 to your computer and use it in GitHub Desktop.
Calculate days, months, years between two dates
function dateDiff_COMMENTED(date1, date2) {
let days = 0;
let months = 0;
let years = 0;
// The calculations need date1 to be earlier than date2.
// If date2 is earlier, swap date1 and date2
if (date1 > date2) [date2, date1] = [date1, date2];
let year1 = date1.getFullYear();
let year2 = date2.getFullYear();
let month1 = date1.getMonth();
let month2 = date2.getMonth();
let day1 = date1.getDate();
let day2 = date2.getDate();
/* Minus date1 and date2s year, month and day.
Best case, date2s year, month and day are all >= date1s year, month and day, respectively,
and our answer is the result of these 3 sums.
date1 = 2021, 4, 4
date2 = 2021, 8, 5
years = 2021 - 2021
months = 8 - 4
days = 5 - 4
Answer: { days: 1, months: 4, years: 0 }
*/
years = year2 - year1;
months = month2 - month1;
days = day2 - day1;
if (days < 0) {
/*
date1 = 2021, 4, 4
date2 = 2021, 8, 1
We would count months like
1 month ahead = 2021, 5, 4
2 months ahead = 2021, 6, 4
3 months ahead = 2021, 7, 4
4 months ahead = 2021, 8, 4
But 4 months ahead is past date2, so we say 3 months ahead and then calculate the days from
the 4th day to the end of the 7th month, plus the days in date2.
*/
months -= 1;
/*
new Date(date2.getFullYear(), date2.getMonth() - 1, 0).getDate() will return the number of days
in the month previous to date2s month.
In our example, there are 31 days in the 7th month, date1.days is 4 and date2.days is 1
days = 31 - 4 + 1
Answer = { days: 28, months: 3, years: 0 }
*/
days = new Date(date2.getFullYear(), date2.getMonth() - 1, 0).getDate() - day1 + day2;
}
if (months < 0) {
/* If months are negative we roll back a year
date1 = 2021, 4, 4
date2 = 2022, 3, 5
months = 3 - 4
So we know it's not a full year, lets minus 1 year and add on 12 months
months += 12
So -1 + 12 = 11
{ months: 11 }
*/
months += 12;
years -= 1;
}
return { days, months, years };
}
function dateDiff(date1, date2) {
let days = 0;
let months = 0;
let years = 0;
if (date1 > date2) [date2, date1] = [date1, date2];
let year1 = date1.getFullYear();
let year2 = date2.getFullYear();
let month1 = date1.getMonth();
let month2 = date2.getMonth();
let day1 = date1.getDate();
let day2 = date2.getDate();
years = year2 - year1;
months = month2 - month1;
days = day2 - day1;
if (days < 0) {
months -= 1;
days = new Date(date2.getFullYear(), date2.getMonth() - 1, 0).getDate() - day1 + day2;
}
if (months < 0) {
months += 12;
years -= 1;
}
return { days, months, years };
}
/*
Everything below is just for testing the above code
*/
function c(a, v) {
if (a.days === v.days && a.months === v.months && a.years === v.years) return true;
return `${JSON.stringify(a)} !== ${JSON.stringify(v)}`;
}
[ [new Date(2022, 3, 3), { days: 27, months: 10, years: 0}],
[new Date(2022, 3, 5), { days: 1, months: 11, years: 0}],
[new Date(2021, 5, 1), { days: 27, months: 0, years: 0}],
[new Date(2021, 5, 5), { days: 1, months: 1, years: 0}],
[new Date(2021, 6, 1), { days: 28, months: 1, years: 0}],
[new Date(2021, 6, 5), { days: 1, months: 2, years: 0}],
[new Date(2021, 7, 1), { days: 27, months: 2, years: 0}],
[new Date(2021, 7, 5), { days: 1, months: 3, years: 0}],
[new Date(2021, 8, 1), { days: 28, months: 3, years: 0}],
[new Date(2021, 8, 5), { days: 1, months: 4, years: 0}],
[new Date(2021, 9, 1), { days: 28, months: 4, years: 0}],
[new Date(2021, 9, 5), { days: 1, months: 5, years: 0}],
[new Date(2021, 10, 1), { days: 27, months: 5, years: 0}],
[new Date(2021, 10, 5), { days: 1, months: 6, years: 0}],
[new Date(2021, 11, 1), { days: 28, months: 6, years: 0}],
[new Date(2021, 11, 5), { days: 1, months: 7, years: 0}],
[new Date(2021, 12, 1), { days: 27, months: 7, years: 0}],
[new Date(2021, 12, 5), { days: 1, months: 8, years: 0}],
[new Date(2022, 1, 1), { days: 28, months: 8, years: 0}],
[new Date(2022, 1, 5), { days: 1, months: 9, years: 0}],
[new Date(2022, 2, 1), { days: 28, months: 9, years: 0}],
[new Date(2022, 2, 5), { days: 1, months: 10, years: 0}],
[new Date(2022, 3, 1), { days: 25, months: 10, years: 0}],
[new Date(2022, 3, 5), { days: 1, months: 11, years: 0}],
[new Date(2022, 4, 1), { days: 28, months: 11, years: 0}],
[new Date(2022, 4, 5), { days: 1, months: 0, years: 1}],
[new Date(2022, 5, 1), { days: 27, months: 0, years: 1}],
[new Date(2022, 5, 5), { days: 1, months: 1, years: 1}],
[new Date(2021, 4, 4, 10), { days: 0, months: 0, years: 0}],
[new Date(2020, 8, 1), { days: 3, months: 8, years: 0}]
].forEach(test => {
console.log(c(dateDiff(new Date(2021, 4, 4), test[0]), test[1]));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment