Last active
September 18, 2021 00:57
-
-
Save sacah/2df59fd483311a2b41d1cb3b679acd91 to your computer and use it in GitHub Desktop.
Calculate days, months, years between two dates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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