This question already has answers here:
How to calculate number of days between two dates?
(42 answers)
Closed 3 months ago.
I want to calculate date difference in days, hours, minutes, seconds, milliseconds, nanoseconds. How can I do it?
Assuming you have two Date objects, you can just subtract them to get the difference in milliseconds:
var difference = date2 - date1;
From there, you can use simple arithmetic to derive the other values.
var DateDiff = {
inDays: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return Math.floor((t2-t1)/(24*3600*1000));
},
inWeeks: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/(24*3600*1000*7));
},
inMonths: function(d1, d2) {
var d1Y = d1.getFullYear();
var d2Y = d2.getFullYear();
var d1M = d1.getMonth();
var d2M = d2.getMonth();
return (d2M+12*d2Y)-(d1M+12*d1Y);
},
inYears: function(d1, d2) {
return d2.getFullYear()-d1.getFullYear();
}
}
var dString = "May, 20, 1984";
var d1 = new Date(dString);
var d2 = new Date();
document.write("<br />Number of <b>days</b> since "+dString+": "+DateDiff.inDays(d1, d2));
document.write("<br />Number of <b>weeks</b> since "+dString+": "+DateDiff.inWeeks(d1, d2));
document.write("<br />Number of <b>months</b> since "+dString+": "+DateDiff.inMonths(d1, d2));
document.write("<br />Number of <b>years</b> since "+dString+": "+DateDiff.inYears(d1, d2));
Code sample taken from here.
Another solution is convert difference to a new Date object and get that date's year(diff from 1970), month, day etc.
var date1 = new Date(2010, 6, 17);
var date2 = new Date(2013, 12, 18);
var diff = new Date(date2.getTime() - date1.getTime());
// diff is: Thu Jul 05 1973 04:00:00 GMT+0300 (EEST)
console.log(diff.getUTCFullYear() - 1970); // Gives difference as year
// 3
console.log(diff.getUTCMonth()); // Gives month count of difference
// 6
console.log(diff.getUTCDate() - 1); // Gives day count of difference
// 4
So difference is like "3 years and 6 months and 4 days". If you want to take difference in a human readable style, that can help you.
Expressions like "difference in days" are never as simple as they seem. If you have the following dates:
d1: 2011-10-15 23:59:00
d1: 2011-10-16 00:01:00
the difference in time is 2 minutes, should the "difference in days" be 1 or 0? Similar issues arise for any expression of the difference in months, years or whatever since years, months and days are of different lengths and different times (e.g. the day that daylight saving starts is 1 hour shorter than usual and two hours shorter than the day that it ends).
Here is a function for a difference in days that ignores the time, i.e. for the above dates it returns 1.
/*
Get the number of days between two dates - not inclusive.
"between" does not include the start date, so days
between Thursday and Friday is one, Thursday to Saturday
is two, and so on. Between Friday and the following Friday is 7.
e.g. getDaysBetweenDates( 22-Jul-2011, 29-jul-2011) => 7.
If want inclusive dates (e.g. leave from 1/1/2011 to 30/1/2011),
use date prior to start date (i.e. 31/12/2010 to 30/1/2011).
Only calculates whole days.
Assumes d0 <= d1
*/
function getDaysBetweenDates(d0, d1) {
var msPerDay = 8.64e7;
// Copy dates so don't mess them up
var x0 = new Date(d0);
var x1 = new Date(d1);
// Set to noon - avoid DST errors
x0.setHours(12,0,0);
x1.setHours(12,0,0);
// Round to remove daylight saving errors
return Math.round( (x1 - x0) / msPerDay );
}
This can be more concise:
/* Return number of days between d0 and d1.
** Returns positive if d0 < d1, otherwise negative.
**
** e.g. between 2000-02-28 and 2001-02-28 there are 366 days
** between 2015-12-28 and 2015-12-29 there is 1 day
** between 2015-12-28 23:59:59 and 2015-12-29 00:00:01 there is 1 day
** between 2015-12-28 00:00:01 and 2015-12-28 23:59:59 there are 0 days
**
** #param {Date} d0 - start date
** #param {Date} d1 - end date
** #returns {number} - whole number of days between d0 and d1
**
*/
function daysDifference(d0, d1) {
var diff = new Date(+d1).setHours(12) - new Date(+d0).setHours(12);
return Math.round(diff/8.64e7);
}
// Simple formatter
function formatDate(date){
return [date.getFullYear(),('0'+(date.getMonth()+1)).slice(-2),('0'+date.getDate()).slice(-2)].join('-');
}
// Examples
[[new Date(2000,1,28), new Date(2001,1,28)], // Leap year
[new Date(2001,1,28), new Date(2002,1,28)], // Not leap year
[new Date(2017,0,1), new Date(2017,1,1)]
].forEach(function(dates) {
document.write('From ' + formatDate(dates[0]) + ' to ' + formatDate(dates[1]) +
' is ' + daysDifference(dates[0],dates[1]) + ' days<br>');
});
<html lang="en">
<head>
<script>
function getDateDiff(time1, time2) {
var str1= time1.split('/');
var str2= time2.split('/');
// yyyy , mm , dd
var t1 = new Date(str1[2], str1[0]-1, str1[1]);
var t2 = new Date(str2[2], str2[0]-1, str2[1]);
var diffMS = t1 - t2;
console.log(diffMS + ' ms');
var diffS = diffMS / 1000;
console.log(diffS + ' ');
var diffM = diffS / 60;
console.log(diffM + ' minutes');
var diffH = diffM / 60;
console.log(diffH + ' hours');
var diffD = diffH / 24;
console.log(diffD + ' days');
alert(diffD);
}
//alert(getDateDiff('10/18/2013','10/14/2013'));
</script>
</head>
<body>
<input type="button"
onclick="getDateDiff('10/18/2013','10/14/2013')"
value="clickHere()" />
</body>
</html>
use Moment.js for all your JavaScript related date-time calculation
Answer to your question is:
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b) // 86400000
Complete details can be found here
adding to #paresh mayani 's answer, to work like Facebook - showing how much time has passed in sec/min/hours/weeks/months/years
var DateDiff = {
inSeconds: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/1000);
},
inMinutes: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/60000);
},
inHours: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/3600000);
},
inDays: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/(24*3600*1000));
},
inWeeks: function(d1, d2) {
var t2 = d2.getTime();
var t1 = d1.getTime();
return parseInt((t2-t1)/(24*3600*1000*7));
},
inMonths: function(d1, d2) {
var d1Y = d1.getFullYear();
var d2Y = d2.getFullYear();
var d1M = d1.getMonth();
var d2M = d2.getMonth();
return (d2M+12*d2Y)-(d1M+12*d1Y);
},
inYears: function(d1, d2) {
return d2.getFullYear()-d1.getFullYear();
}
}
var dString = "May, 20, 1984"; //will also get (Y-m-d H:i:s)
var d1 = new Date(dString);
var d2 = new Date();
var timeLaps = DateDiff.inSeconds(d1, d2);
var dateOutput = "";
if (timeLaps<60)
{
dateOutput = timeLaps+" seconds";
}
else
{
timeLaps = DateDiff.inMinutes(d1, d2);
if (timeLaps<60)
{
dateOutput = timeLaps+" minutes";
}
else
{
timeLaps = DateDiff.inHours(d1, d2);
if (timeLaps<24)
{
dateOutput = timeLaps+" hours";
}
else
{
timeLaps = DateDiff.inDays(d1, d2);
if (timeLaps<7)
{
dateOutput = timeLaps+" days";
}
else
{
timeLaps = DateDiff.inWeeks(d1, d2);
if (timeLaps<4)
{
dateOutput = timeLaps+" weeks";
}
else
{
timeLaps = DateDiff.inMonths(d1, d2);
if (timeLaps<12)
{
dateOutput = timeLaps+" months";
}
else
{
timeLaps = DateDiff.inYears(d1, d2);
dateOutput = timeLaps+" years";
}
}
}
}
}
}
alert (dateOutput);
With momentjs it's simple:
moment("2016-04-08").fromNow();
function DateDiff(date1, date2) {
date1.setHours(0);
date1.setMinutes(0, 0, 0);
date2.setHours(0);
date2.setMinutes(0, 0, 0);
var datediff = Math.abs(date1.getTime() - date2.getTime()); // difference
return parseInt(datediff / (24 * 60 * 60 * 1000), 10); //Convert values days and return value
}
var d1=new Date(2011,0,1); // jan,1 2011
var d2=new Date(); // now
var diff=d2-d1,sign=diff<0?-1:1,milliseconds,seconds,minutes,hours,days;
diff/=sign; // or diff=Math.abs(diff);
diff=(diff-(milliseconds=diff%1000))/1000;
diff=(diff-(seconds=diff%60))/60;
diff=(diff-(minutes=diff%60))/60;
days=(diff-(hours=diff%24))/24;
console.info(sign===1?"Elapsed: ":"Remains: ",
days+" days, ",
hours+" hours, ",
minutes+" minutes, ",
seconds+" seconds, ",
milliseconds+" milliseconds.");
I think this should do it.
let today = new Date();
let form_date=new Date('2019-10-23')
let difference=form_date>today ? form_date-today : today-form_date
let diff_days=Math.floor(difference/(1000*3600*24))
based on javascript runtime prototype implementation you can use simple arithmetic to subtract dates as in bellow
var sep = new Date(2020, 07, 31, 23, 59, 59);
var today = new Date();
var diffD = Math.floor((sep - today) / (1000 * 60 * 60 * 24));
console.log('Day Diff: '+diffD);
the difference return answer as milliseconds, then you have to convert it by division:
by 1000 to convert to second
by 1000×60 convert to minute
by 1000×60×60 convert to hour
by 1000×60×60×24 convert to day
function DateDiff(b, e)
{
let
endYear = e.getFullYear(),
endMonth = e.getMonth(),
years = endYear - b.getFullYear(),
months = endMonth - b.getMonth(),
days = e.getDate() - b.getDate();
if (months < 0)
{
years--;
months += 12;
}
if (days < 0)
{
months--;
days += new Date(endYear, endMonth, 0).getDate();
}
return [years, months, days];
}
[years, months, days] = DateDiff(
new Date("October 21, 1980"),
new Date("July 11, 2017")); // 36 8 20
Sorry but flat millisecond calculation is not reliable
Thanks for all the responses, but few of the functions I tried are failing either on
1. A date near today's date
2. A date in 1970 or
3. A date in a leap year.
Approach that best worked for me and covers all scenario e.g. leap year, near date in 1970, feb 29 etc.
var someday = new Date("8/1/1985");
var today = new Date();
var years = today.getFullYear() - someday.getFullYear();
// Reset someday to the current year.
someday.setFullYear(today.getFullYear());
// Depending on when that day falls for this year, subtract 1.
if (today < someday)
{
years--;
}
document.write("Its been " + years + " full years.");
This code will return the difference between two dates in days:
const previous_date = new Date("2019-12-23");
const current_date = new Date();
const current_year = current_date.getFullYear();
const previous_date_year =
previous_date.getFullYear();
const difference_in_years = current_year -
previous_date_year;
let months = current_date.getMonth();
months = months + 1; // for making the indexing
// of months from 1
for(let i = 0; i < difference_in_years; i++){
months = months + 12;
}
let days = current_date.getDate();
days = days + (months * 30.417);
console.log(`The days between ${current_date} and
${previous_date} are : ${days} (approximately)`);
If you are using moment.js then it is pretty simple to find date difference.
var now = "04/09/2013 15:00:00";
var then = "04/09/2013 14:20:30";
moment.utc(moment(now,"DD/MM/YYYY HH:mm:ss").diff(moment(then,"DD/MM/YYYY HH:mm:ss"))).format("HH:mm:ss")
This is how you can implement difference between dates without a framework.
function getDateDiff(dateOne, dateTwo) {
if(dateOne.charAt(2)=='-' & dateTwo.charAt(2)=='-'){
dateOne = new Date(formatDate(dateOne));
dateTwo = new Date(formatDate(dateTwo));
}
else{
dateOne = new Date(dateOne);
dateTwo = new Date(dateTwo);
}
let timeDiff = Math.abs(dateOne.getTime() - dateTwo.getTime());
let diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
let diffMonths = Math.ceil(diffDays/31);
let diffYears = Math.ceil(diffMonths/12);
let message = "Difference in Days: " + diffDays + " " +
"Difference in Months: " + diffMonths+ " " +
"Difference in Years: " + diffYears;
return message;
}
function formatDate(date) {
return date.split('-').reverse().join('-');
}
console.log(getDateDiff("23-04-2017", "23-04-2018"));
function daysInMonth (month, year) {
return new Date(year, month, 0).getDate();
}
function getduration(){
let A= document.getElementById("date1_id").value
let B= document.getElementById("date2_id").value
let C=Number(A.substring(3,5))
let D=Number(B.substring(3,5))
let dif=D-C
let arr=[];
let sum=0;
for (let i=0;i<dif+1;i++){
sum+=Number(daysInMonth(i+C,2019))
}
let sum_alter=0;
for (let i=0;i<dif;i++){
sum_alter+=Number(daysInMonth(i+C,2019))
}
let no_of_month=(Number(B.substring(3,5)) - Number(A.substring(3,5)))
let days=[];
if ((Number(B.substring(3,5)) - Number(A.substring(3,5)))>0||Number(B.substring(0,2)) - Number(A.substring(0,2))<0){
days=Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter
}
if ((Number(B.substring(3,5)) == Number(A.substring(3,5)))){
console.log(Number(B.substring(0,2)) - Number(A.substring(0,2)) + sum_alter)
}
time_1=[]; time_2=[]; let hour=[];
time_1=document.getElementById("time1_id").value
time_2=document.getElementById("time2_id").value
if (time_1.substring(0,2)=="12"){
time_1="00:00:00 PM"
}
if (time_1.substring(9,11)==time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))
}
if (time_1.substring(9,11)!=time_2.substring(9,11)){
hour=Math.abs(Number(time_2.substring(0,2)) - Number(time_1.substring(0,2)))+12
}
let min=Math.abs(Number(time_1.substring(3,5))-Number(time_2.substring(3,5)))
document.getElementById("duration_id").value=days +" days "+ hour+" hour " + min+" min "
}
<input type="text" id="date1_id" placeholder="28/05/2019">
<input type="text" id="date2_id" placeholder="29/06/2019">
<br><br>
<input type="text" id="time1_id" placeholder="08:01:00 AM">
<input type="text" id="time2_id" placeholder="00:00:00 PM">
<br><br>
<button class="text" onClick="getduration()">Submit </button>
<br><br>
<input type="text" id="duration_id" placeholder="days hour min">
var date1 = new Date("06/30/2019");
var date2 = new Date("07/30/2019");
// To calculate the time difference of two dates
var Difference_In_Time = date2.getTime() - date1.getTime();
// To calculate the no. of days between two dates
var Difference_In_Days = Difference_In_Time / (1000 * 3600 * 24);
//To display the final no. of days (result)
document.write("Total number of days between dates <br>"
+ date1 + "<br> and <br>"
+ date2 + " is: <br> "
+ Difference_In_Days);
this should work just fine if you just need to show what time left, since JavaScript uses frames for its time you'll have get your End Time - The Time RN after that we can divide it by 1000 since apparently 1000 frames = 1 seconds, after that you can use the basic math of time, but there's still a problem to this code, since the calculation is static, it can't compensate for the different day total in a year (360/365/366), the bunch of IF after the calculation is to make it null if the time is lower than 0, hope this helps even though it's not exactly what you're asking :)
var now = new Date();
var end = new Date("End Time");
var total = (end - now) ;
var totalD = Math.abs(Math.floor(total/1000));
var years = Math.floor(totalD / (365*60*60*24));
var months = Math.floor((totalD - years*365*60*60*24) / (30*60*60*24));
var days = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24)/ (60*60*24));
var hours = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24)/ (60*60));
var minutes = Math.floor((totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60)/ (60));
var seconds = Math.floor(totalD - years*365*60*60*24 - months*30*60*60*24 - days*60*60*24 - hours*60*60 - minutes*60);
var Y = years < 1 ? "" : years + " Years ";
var M = months < 1 ? "" : months + " Months ";
var D = days < 1 ? "" : days + " Days ";
var H = hours < 1 ? "" : hours + " Hours ";
var I = minutes < 1 ? "" : minutes + " Minutes ";
var S = seconds < 1 ? "" : seconds + " Seconds ";
var A = years == 0 && months == 0 && days == 0 && hours == 0 && minutes == 0 && seconds == 0 ? "Sending" : " Remaining";
document.getElementById('txt').innerHTML = Y + M + D + H + I + S + A;
Ok, there are a bunch of ways you can do that.
Yes, you can use plain old JS. Just try:
let dt1 = new Date()
let dt2 = new Date()
Let's emulate passage using Date.prototype.setMinutes and make sure we are in range.
dt1.setMinutes(7)
dt2.setMinutes(42)
console.log('Elapsed seconds:',(dt2-dt1)/1000)
Alternatively you could use some library like js-joda, where you can easily do things like this (directly from docs):
var dt1 = LocalDateTime.parse("2016-02-26T23:55:42.123");
var dt2 = dt1
.plusYears(6)
.plusMonths(12)
.plusHours(2)
.plusMinutes(42)
.plusSeconds(12);
// obtain the duration between the two dates
dt1.until(dt2, ChronoUnit.YEARS); // 7
dt1.until(dt2, ChronoUnit.MONTHS); // 84
dt1.until(dt2, ChronoUnit.WEEKS); // 356
dt1.until(dt2, ChronoUnit.DAYS); // 2557
dt1.until(dt2, ChronoUnit.HOURS); // 61370
dt1.until(dt2, ChronoUnit.MINUTES); // 3682242
dt1.until(dt2, ChronoUnit.SECONDS); // 220934532
There are plenty more libraries ofc, but js-joda has an added bonus of being available also in Java, where it has been extensively tested. All those tests have been migrated to js-joda, it's also immutable.
I made a below function to get the difference between now and "2021-02-26T21:50:42.123".
The difference return answer as milliseconds, so I convert it by using this formula:
(1000 * 3600 * 24).
function getDiff(dateAcquired) {
let calDiff = Math.floor(
(new Date() - new Date(dateAcquired)) / (1000 * 3600 * 24)
);
return calDiff;
}
console.log(getDiff("2021-02-26T21:50:42.123"));
Can be useful :
const date_diff = (date1, date2) => Math.ceil(Math.abs(date1 - date2)/24 * 60 * 60 * 1000)
or
const date_diff = (date1, date2) => Math.ceil(Math.abs(date1 - date2)/86400000)
where 24 * 60 * 60 * 1000 is (day * minutes * seconds * milliseconds) = 86400000 milliseconds in one day
Thank you
// the idea is to get time left for new year.
// Not considering milliseconds as of now, but that
// can be done
var newYear = '1 Jan 2023';
const secondsInAMin = 60;
const secondsInAnHour = 60 * secondsInAMin;
const secondsInADay = 24 * secondsInAnHour;
function DateDiffJs() {
var newYearDate = new Date(newYear);
var currDate = new Date();
var remainingSecondsInDateDiff = (newYearDate - currDate) / 1000;
var days = Math.floor(remainingSecondsInDateDiff / secondsInADay);
var remainingSecondsAfterDays = remainingSecondsInDateDiff - (days * secondsInADay);
var hours = Math.floor(remainingSecondsAfterDays / secondsInAnHour);
var remainingSecondsAfterhours = remainingSecondsAfterDays - (hours * secondsInAnHour);
var mins = Math.floor(remainingSecondsAfterhours / secondsInAMin);
var seconds = Math.floor(remainingSecondsAfterhours - (mins * secondsInAMin));
console.log(`days :: ${days}`)
console.log(`hours :: ${hours}`)
console.log(`mins :: ${mins}`)
console.log(`seconds :: ${seconds}`)
}
DateDiffJs();
How to get the difference between two dates in years, months, and days in JavaScript, like: 10th of April 2010 was 3 years, x month and y days ago?
There are lots of solutions, but they only offer the difference in the format of either days OR months OR years, or they are not correct (meaning not taking care of actual number of days in a month or leap years, etc). Is it really that difficult to do that?
I've had a look at:
http://momentjs.com/ -> can only output the difference in either years, months, OR days
http://www.javascriptkit.com/javatutors/datedifference.shtml
http://www.javascriptkit.com/jsref/date.shtml
http://timeago.yarp.com/
www.stackoverflow.com -> Search function
In php it is easy, but unfortunately I can only use client-side script on that project. Any library or framework that can do it would be fine, too.
Here are a list of expected outputs for date differences:
//Expected output should be: "1 year, 5 months".
diffDate(new Date('2014-05-10'), new Date('2015-10-10'));
//Expected output should be: "1 year, 4 months, 29 days".
diffDate(new Date('2014-05-10'), new Date('2015-10-09'));
//Expected output should be: "1 year, 3 months, 30 days".
diffDate(new Date('2014-05-10'), new Date('2015-09-09'));
//Expected output should be: "9 months, 27 days".
diffDate(new Date('2014-05-10'), new Date('2015-03-09'));
//Expected output should be: "1 year, 9 months, 28 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-09'));
//Expected output should be: "1 year, 10 months, 1 days".
diffDate(new Date('2014-05-10'), new Date('2016-03-11'));
How precise do you need to be? If you do need to take into account common years and leap years, and the exact difference in days between months then you'll have to write something more advanced but for a basic and rough calculation this should do the trick:
today = new Date()
past = new Date(2010,05,01) // remember this is equivalent to 06 01 2010
//dates in js are counted from 0, so 05 is june
function calcDate(date1,date2) {
var diff = Math.floor(date1.getTime() - date2.getTime());
var day = 1000 * 60 * 60 * 24;
var days = Math.floor(diff/day);
var months = Math.floor(days/31);
var years = Math.floor(months/12);
var message = date2.toDateString();
message += " was "
message += days + " days "
message += months + " months "
message += years + " years ago \n"
return message
}
a = calcDate(today,past)
console.log(a) // returns Tue Jun 01 2010 was 1143 days 36 months 3 years ago
Keep in mind that this is imprecise, in order to calculate the date with full precision one would have to have a calendar and know if a year is a leap year or not, also the way I'm calculating the number of months is only approximate.
But you can improve it easily.
Actually, there's a solution with a moment.js plugin and it's very easy.
You might use moment.js
Don't reinvent the wheel again.
Just plug Moment.js Date Range Plugin.
Example:
var starts = moment('2014-02-03 12:53:12');
var ends = moment();
var duration = moment.duration(ends.diff(starts));
// with ###moment precise date range plugin###
// it will tell you the difference in human terms
var diff = moment.preciseDiff(starts, ends, true);
// example: { "years": 2, "months": 7, "days": 0, "hours": 6, "minutes": 29, "seconds": 17, "firstDateWasLater": false }
// or as string:
var diffHuman = moment.preciseDiff(starts, ends);
// example: 2 years 7 months 6 hours 29 minutes 17 seconds
document.getElementById('output1').innerHTML = JSON.stringify(diff)
document.getElementById('output2').innerHTML = diffHuman
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
<script src="https://raw.githubusercontent.com/codebox/moment-precise-range/master/moment-precise-range.js"></script>
</head>
<body>
<h2>Difference between "NOW and 2014-02-03 12:53:12"</h2>
<span id="output1"></span>
<br />
<span id="output2"></span>
</body>
</html>
Modified this to be a lot more accurate. It will convert dates to a 'YYYY-MM-DD' format, ignoring HH:MM:SS, and takes an optional endDate or uses the current date, and doesn't care about the order of the values.
function dateDiff(startingDate, endingDate) {
let startDate = new Date(new Date(startingDate).toISOString().substr(0, 10));
if (!endingDate) {
endingDate = new Date().toISOString().substr(0, 10); // need date in YYYY-MM-DD format
}
let endDate = new Date(endingDate);
if (startDate > endDate) {
const swap = startDate;
startDate = endDate;
endDate = swap;
}
const startYear = startDate.getFullYear();
const february = (startYear % 4 === 0 && startYear % 100 !== 0) || startYear % 400 === 0 ? 29 : 28;
const daysInMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let yearDiff = endDate.getFullYear() - startYear;
let monthDiff = endDate.getMonth() - startDate.getMonth();
if (monthDiff < 0) {
yearDiff--;
monthDiff += 12;
}
let dayDiff = endDate.getDate() - startDate.getDate();
if (dayDiff < 0) {
if (monthDiff > 0) {
monthDiff--;
} else {
yearDiff--;
monthDiff = 11;
}
dayDiff += daysInMonth[startDate.getMonth()];
}
return yearDiff + 'Y ' + monthDiff + 'M ' + dayDiff + 'D';
}
// Examples
let dates = [
['2019-05-10','2019-05-10'], // 0Y 0M 0D
['2019-05-09','2019-05-10'], // 0Y 0M 1D
['2018-05-09','2019-05-10'], // 1Y 0M 1D
['2018-05-18','2019-05-10'], // 0Y 11M 23D
['2019-01-09','2019-05-10'], // 0Y 4M 1D
['2019-02-10','2019-05-10'], // 0Y 3M 0D
['2019-02-11','2019-05-10'], // 0Y 2M 27D
['2016-02-11','2019-05-10'], // 3Y 2M 28D - leap year
['1972-11-30','2019-05-10'], // 46Y 5M 10D
['2016-02-11','2017-02-11'], // 1Y 0M 0D
['2016-02-11','2016-03-10'], // 0Y 0M 28D - leap year
['2100-02-11','2100-03-10'], // 0Y 0M 27D - not a leap year
['2017-02-11','2016-02-11'], // 1Y 0M 0D - swapped dates to return correct result
[new Date() - 1000 * 60 * 60 * 24] // 0Y 0M 1D - uses current date
].forEach(([s, e]) => console.log(dateDiff(s, e)));
Older less accurate but much simpler version
#RajeevPNadig's answer was what I was looking for, but his code returns incorrect values as written. This code is not very accurate because it assumes that the sequence of dates from 1 January 1970 is the same as any other sequence of the same number of days. E.g. it calculates the difference from 1 July to 1 September (62 days) as 0Y 2M 3D and not 0Y 2M 0D because 1 Jan 1970 plus 62 days is 3 March.
// startDate must be a date string
function dateAgo(date) {
var startDate = new Date(date);
var diffDate = new Date(new Date() - startDate);
return ((diffDate.toISOString().slice(0, 4) - 1970) + "Y " +
diffDate.getMonth() + "M " + (diffDate.getDate()-1) + "D");
}
Then you can use it like this:
// based on a current date of 2018-03-09
dateAgo('1972-11-30'); // "45Y 3M 9D"
dateAgo('2017-03-09'); // "1Y 0M 0D"
dateAgo('2018-01-09'); // "0Y 2M 0D"
dateAgo('2018-02-09'); // "0Y 0M 28D" -- a little odd, but not wrong
dateAgo('2018-02-01'); // "0Y 1M 5D" -- definitely "feels" wrong
dateAgo('2018-03-09'); // "0Y 0M 0D"
If your use case is just date strings, then this works okay if you just want a quick and dirty 4 liner.
I used this simple code to get difference in Years, Months, days with current date.
var sdt = new Date('1972-11-30');
var difdt = new Date(new Date() - sdt);
alert((difdt.toISOString().slice(0, 4) - 1970) + "Y " + (difdt.getMonth()+1) + "M " + difdt.getDate() + "D");
I think you are looking for the same thing that I wanted. I tried to do this using the difference in milliseconds that javascript provides, but those results do not work in the real world of dates. If you want the difference between Feb 1, 2016 and January 31, 2017 the result I would want is 1 year, 0 months, and 0 days. Exactly one year (assuming you count the last day as a full day, like in a lease for an apartment). However, the millisecond approach would give you 1 year 0 months and 1 day, since the date range includes a leap year. So here is the code I used in javascript for my adobe form (you can name the fields): (edited, there was an error that I corrected)
var f1 = this.getField("LeaseExpiration");
var g1 = this.getField("LeaseStart");
var end = f1.value
var begin = g1.value
var e = new Date(end);
var b = new Date(begin);
var bMonth = b.getMonth();
var bYear = b.getFullYear();
var eYear = e.getFullYear();
var eMonth = e.getMonth();
var bDay = b.getDate();
var eDay = e.getDate() + 1;
if ((eMonth == 0)||(eMonth == 2)||(eMonth == 4)|| (eMonth == 6) || (eMonth == 7) ||(eMonth == 9)||(eMonth == 11))
{
var eDays = 31;
}
if ((eMonth == 3)||(eMonth == 5)||(eMonth == 8)|| (eMonth == 10))
{
var eDays = 30;
}
if (eMonth == 1&&((eYear % 4 == 0) && (eYear % 100 != 0)) || (eYear % 400 == 0))
{
var eDays = 29;
}
if (eMonth == 1&&((eYear % 4 != 0) || (eYear % 100 == 0)))
{
var eDays = 28;
}
if ((bMonth == 0)||(bMonth == 2)||(bMonth == 4)|| (bMonth == 6) || (bMonth == 7) ||(bMonth == 9)||(bMonth == 11))
{
var bDays = 31;
}
if ((bMonth == 3)||(bMonth == 5)||(bMonth == 8)|| (bMonth == 10))
{
var bDays = 30;
}
if (bMonth == 1&&((bYear % 4 == 0) && (bYear % 100 != 0)) || (bYear % 400 == 0))
{
var bDays = 29;
}
if (bMonth == 1&&((bYear % 4 != 0) || (bYear % 100 == 0)))
{
var bDays = 28;
}
var FirstMonthDiff = bDays - bDay + 1;
if (eDay - bDay < 0)
{
eMonth = eMonth - 1;
eDay = eDay + eDays;
}
var daysDiff = eDay - bDay;
if(eMonth - bMonth < 0)
{
eYear = eYear - 1;
eMonth = eMonth + 12;
}
var monthDiff = eMonth - bMonth;
var yearDiff = eYear - bYear;
if (daysDiff == eDays)
{
daysDiff = 0;
monthDiff = monthDiff + 1;
if (monthDiff == 12)
{
monthDiff = 0;
yearDiff = yearDiff + 1;
}
}
if ((FirstMonthDiff != bDays)&&(eDay - 1 == eDays))
{
daysDiff = FirstMonthDiff;
}
event.value = yearDiff + " Year(s)" + " " + monthDiff + " month(s) " + daysDiff + " days(s)"
I have created, yet another one, function for this purpose:
function dateDiff(date) {
date = date.split('-');
var today = new Date();
var year = today.getFullYear();
var month = today.getMonth() + 1;
var day = today.getDate();
var yy = parseInt(date[0]);
var mm = parseInt(date[1]);
var dd = parseInt(date[2]);
var years, months, days;
// months
months = month - mm;
if (day < dd) {
months = months - 1;
}
// years
years = year - yy;
if (month * 100 + day < mm * 100 + dd) {
years = years - 1;
months = months + 12;
}
// days
days = Math.floor((today.getTime() - (new Date(yy + years, mm + months - 1, dd)).getTime()) / (24 * 60 * 60 * 1000));
//
return {years: years, months: months, days: days};
}
Doesn't require any 3rd party libraries. Takes one argument -- date in YYYY-MM-DD format.
https://gist.github.com/lemmon/d27c2d4a783b1cf72d1d1cc243458d56
With dayjs we did it in that way:
export const getAgeDetails = (oldDate: dayjs.Dayjs, newDate: dayjs.Dayjs) => {
const years = newDate.diff(oldDate, 'year');
const months = newDate.diff(oldDate, 'month') - years * 12;
const days = newDate.diff(oldDate.add(years, 'year').add(months, 'month'), 'day');
return {
years,
months,
days,
allDays: newDate.diff(oldDate, 'day'),
};
};
It calculates it perfectly including leap years and different month amount of days.
For quick and easy use I wrote this function some time ago. It returns the diff between two dates in a nice format. Feel free to use it (tested on webkit).
/**
* Function to print date diffs.
*
* #param {Date} fromDate: The valid start date
* #param {Date} toDate: The end date. Can be null (if so the function uses "now").
* #param {Number} levels: The number of details you want to get out (1="in 2 Months",2="in 2 Months, 20 Days",...)
* #param {Boolean} prefix: adds "in" or "ago" to the return string
* #return {String} Diffrence between the two dates.
*/
function getNiceTime(fromDate, toDate, levels, prefix){
var lang = {
"date.past": "{0} ago",
"date.future": "in {0}",
"date.now": "now",
"date.year": "{0} year",
"date.years": "{0} years",
"date.years.prefixed": "{0} years",
"date.month": "{0} month",
"date.months": "{0} months",
"date.months.prefixed": "{0} months",
"date.day": "{0} day",
"date.days": "{0} days",
"date.days.prefixed": "{0} days",
"date.hour": "{0} hour",
"date.hours": "{0} hours",
"date.hours.prefixed": "{0} hours",
"date.minute": "{0} minute",
"date.minutes": "{0} minutes",
"date.minutes.prefixed": "{0} minutes",
"date.second": "{0} second",
"date.seconds": "{0} seconds",
"date.seconds.prefixed": "{0} seconds",
},
langFn = function(id,params){
var returnValue = lang[id] || "";
if(params){
for(var i=0;i<params.length;i++){
returnValue = returnValue.replace("{"+i+"}",params[i]);
}
}
return returnValue;
},
toDate = toDate ? toDate : new Date(),
diff = fromDate - toDate,
past = diff < 0 ? true : false,
diff = diff < 0 ? diff * -1 : diff,
date = new Date(new Date(1970,0,1,0).getTime()+diff),
returnString = '',
count = 0,
years = (date.getFullYear() - 1970);
if(years > 0){
var langSingle = "date.year" + (prefix ? "" : ""),
langMultiple = "date.years" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (years > 1 ? langFn(langMultiple,[years]) : langFn(langSingle,[years]));
count ++;
}
var months = date.getMonth();
if(count < levels && months > 0){
var langSingle = "date.month" + (prefix ? "" : ""),
langMultiple = "date.months" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (months > 1 ? langFn(langMultiple,[months]) : langFn(langSingle,[months]));
count ++;
} else {
if(count > 0)
count = 99;
}
var days = date.getDate() - 1;
if(count < levels && days > 0){
var langSingle = "date.day" + (prefix ? "" : ""),
langMultiple = "date.days" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (days > 1 ? langFn(langMultiple,[days]) : langFn(langSingle,[days]));
count ++;
} else {
if(count > 0)
count = 99;
}
var hours = date.getHours();
if(count < levels && hours > 0){
var langSingle = "date.hour" + (prefix ? "" : ""),
langMultiple = "date.hours" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (hours > 1 ? langFn(langMultiple,[hours]) : langFn(langSingle,[hours]));
count ++;
} else {
if(count > 0)
count = 99;
}
var minutes = date.getMinutes();
if(count < levels && minutes > 0){
var langSingle = "date.minute" + (prefix ? "" : ""),
langMultiple = "date.minutes" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (minutes > 1 ? langFn(langMultiple,[minutes]) : langFn(langSingle,[minutes]));
count ++;
} else {
if(count > 0)
count = 99;
}
var seconds = date.getSeconds();
if(count < levels && seconds > 0){
var langSingle = "date.second" + (prefix ? "" : ""),
langMultiple = "date.seconds" + (prefix ? ".prefixed" : "");
returnString += (count > 0 ? ', ' : '') + (seconds > 1 ? langFn(langMultiple,[seconds]) : langFn(langSingle,[seconds]));
count ++;
} else {
if(count > 0)
count = 99;
}
if(prefix){
if(returnString == ""){
returnString = langFn("date.now");
} else if(past)
returnString = langFn("date.past",[returnString]);
else
returnString = langFn("date.future",[returnString]);
}
return returnString;
}
If you are using date-fns and if you dont want to install the Moment.js or the moment-precise-range-plugin. You can use the following date-fns function to get the same result as moment-precise-range-plugin
intervalToDuration({
start: new Date(),
end: new Date("24 Jun 2020")
})
This will give output in a JSON object like below
{
"years": 0,
"months": 0,
"days": 0,
"hours": 19,
"minutes": 35,
"seconds": 24
}
Live Example https://stackblitz.com/edit/react-wvxvql
Link to Documentation https://date-fns.org/v2.14.0/docs/intervalToDuration
Some math is in order.
You can subtract one Date object from another in Javascript, and you'll get the difference between them in milisseconds. From this result you can extract the other parts you want (days, months etc.)
For example:
var a = new Date(2010, 10, 1);
var b = new Date(2010, 9, 1);
var c = a - b; // c equals 2674800000,
// the amount of milisseconds between September 1, 2010
// and August 1, 2010.
Now you can get any part you want. For example, how many days have elapsed between the two dates:
var days = (a - b) / (60 * 60 * 24 * 1000);
// 60 * 60 * 24 * 1000 is the amount of milisseconds in a day.
// the variable days now equals 30.958333333333332.
That's almost 31 days. You can then round down for 30 days, and use whatever remained to get the amounts of hours, minutes etc.
Get the difference between two dates in a human way
This function is capable of returning natural-language-like text. Use it to get responses like:
"4 years, 1 month and 11 days"
"1 year and 2 months"
"11 months and 20 days"
"12 days"
IMPORTANT: date-fns is a dependency
Just copy the code below and plug in a past date into our getElapsedTime function! It will compare the entered date against the present time and return your human-like responses.
import * as dateFns from "https://cdn.skypack.dev/date-fns#2.22.1";
function getElapsedTime(pastDate) {
const duration = dateFns.intervalToDuration({
start: new Date(pastDate),
end: new Date(),
});
let [years, months, days] = ["", "", ""];
if (duration.years > 0) {
years = duration.years === 1 ? "1 year" : `${duration.years} years`;
}
if (duration.months > 0) {
months = duration.months === 1 ? "1 month" : `${duration.months} months`;
}
if (duration.days > 0) {
days = duration.days === 1 ? "1 day" : `${duration.days} days`;
}
let response = [years, months, days].filter(Boolean);
switch (response.length) {
case 3:
response[1] += " and";
response[0] += ",";
break;
case 2:
response[0] += " and";
break;
}
return response.join(" ");
}
Yet another solution, based on some PHP code.
The strtotime function, also based on PHP, can be found here: http://phpjs.org/functions/strtotime/.
Date.dateDiff = function(d1, d2) {
d1 /= 1000;
d2 /= 1000;
if (d1 > d2) d2 = [d1, d1 = d2][0];
var diffs = {
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0
}
$.each(diffs, function(interval) {
while (d2 >= (d3 = Date.strtotime('+1 '+interval, d1))) {
d1 = d3;
++diffs[interval];
}
});
return diffs;
};
Usage:
> d1 = new Date(2000, 0, 1)
Sat Jan 01 2000 00:00:00 GMT+0100 (CET)
> d2 = new Date(2013, 9, 6)
Sun Oct 06 2013 00:00:00 GMT+0200 (CEST)
> Date.dateDiff(d1, d2)
Object {
day: 5
hour: 0
minute: 0
month: 9
second: 0
year: 13
}
Very old thread, I know, but here's my contribution, as the thread is not solved yet.
It takes leap years into consideration and does not asume any fixed number of days per month or year.
It might be flawed in border cases as I haven't tested it thoroughly, but it works for all the dates provided in the original question, thus I'm confident.
function calculate() {
var fromDate = document.getElementById('fromDate').value;
var toDate = document.getElementById('toDate').value;
try {
document.getElementById('result').innerHTML = '';
var result = getDateDifference(new Date(fromDate), new Date(toDate));
if (result && !isNaN(result.years)) {
document.getElementById('result').innerHTML =
result.years + ' year' + (result.years == 1 ? ' ' : 's ') +
result.months + ' month' + (result.months == 1 ? ' ' : 's ') + 'and ' +
result.days + ' day' + (result.days == 1 ? '' : 's');
}
} catch (e) {
console.error(e);
}
}
function getDateDifference(startDate, endDate) {
if (startDate > endDate) {
console.error('Start date must be before end date');
return null;
}
var startYear = startDate.getFullYear();
var startMonth = startDate.getMonth();
var startDay = startDate.getDate();
var endYear = endDate.getFullYear();
var endMonth = endDate.getMonth();
var endDay = endDate.getDate();
// We calculate February based on end year as it might be a leep year which might influence the number of days.
var february = (endYear % 4 == 0 && endYear % 100 != 0) || endYear % 400 == 0 ? 29 : 28;
var daysOfMonth = [31, february, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var startDateNotPassedInEndYear = (endMonth < startMonth) || endMonth == startMonth && endDay < startDay;
var years = endYear - startYear - (startDateNotPassedInEndYear ? 1 : 0);
var months = (12 + endMonth - startMonth - (endDay < startDay ? 1 : 0)) % 12;
// (12 + ...) % 12 makes sure index is always between 0 and 11
var days = startDay <= endDay ? endDay - startDay : daysOfMonth[(12 + endMonth - 1) % 12] - startDay + endDay;
return {
years: years,
months: months,
days: days
};
}
<p><input type="text" name="fromDate" id="fromDate" placeholder="yyyy-mm-dd" value="1999-02-28" /></p>
<p><input type="text" name="toDate" id="toDate" placeholder="yyyy-mm-dd" value="2000-03-01" /></p>
<p><input type="button" name="calculate" value="Calculate" onclick="javascript:calculate();" /></p>
<p />
<p id="result"></p>
let startDate = moment(new Date('2017-05-12')); // yyyy-MM-dd
let endDate = moment(new Date('2018-09-14')); // yyyy-MM-dd
let Years = newDate.diff(date, 'years');
let months = newDate.diff(date, 'months');
let days = newDate.diff(date, 'days');
console.log("Year: " + Years, ", Month: " months-(Years*12), ", Days: " days-(Years*365.25)-((365.25*(days- (Years*12)))/12));
Above snippet will print: Year: 1, Month: 4, Days: 2
Using Plane Javascript:
function dateDiffInDays(start, end) {
var MS_PER_DAY = 1000 * 60 * 60 * 24;
var a = new Date(start);
var b = new Date(end);
const diffTime = Math.abs(a - b);
const diffDays = Math.ceil(diffTime / MS_PER_DAY);
console.log("Days: ", diffDays);
// Discard the time and time-zone information.
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((utc2 - utc1) / MS_PER_DAY);
}
function dateDiffInDays_Months_Years(start, end) {
var m1 = new Date(start);
var m2 = new Date(end);
var yDiff = m2.getFullYear() - m1.getFullYear();
var mDiff = m2.getMonth() - m1.getMonth();
var dDiff = m2.getDate() - m1.getDate();
if (dDiff < 0) {
var daysInLastFullMonth = getDaysInLastFullMonth(start);
if (daysInLastFullMonth < m1.getDate()) {
dDiff = daysInLastFullMonth + dDiff + (m1.getDate() -
daysInLastFullMonth);
} else {
dDiff = daysInLastFullMonth + dDiff;
}
mDiff--;
}
if (mDiff < 0) {
mDiff = 12 + mDiff;
yDiff--;
}
console.log('Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}
function getDaysInLastFullMonth(day) {
var d = new Date(day);
console.log(d.getDay() );
var lastDayOfMonth = new Date(d.getFullYear(), d.getMonth() + 1, 0);
console.log('last day of month:', lastDayOfMonth.getDate() ); //
return lastDayOfMonth.getDate();
}
Using moment.js:
function dateDiffUsingMoment(start, end) {
var a = moment(start,'M/D/YYYY');
var b = moment(end,'M/D/YYYY');
var diffDaysMoment = b.diff(a, 'days');
console.log('Moments.js : ', diffDaysMoment);
preciseDiffMoments(a,b);
}
function preciseDiffMoments( a, b) {
var m1= a, m2=b;
m1.add(m2.utcOffset() - m1.utcOffset(), 'minutes'); // shift timezone of m1 to m2
var yDiff = m2.year() - m1.year();
var mDiff = m2.month() - m1.month();
var dDiff = m2.date() - m1.date();
if (dDiff < 0) {
var daysInLastFullMonth = moment(m2.year() + '-' + (m2.month() + 1),
"YYYY-MM").subtract(1, 'M').daysInMonth();
if (daysInLastFullMonth < m1.date()) { // 31/01 -> 2/03
dDiff = daysInLastFullMonth + dDiff + (m1.date() -
daysInLastFullMonth);
} else {
dDiff = daysInLastFullMonth + dDiff;
}
mDiff--;
}
if (mDiff < 0) {
mDiff = 12 + mDiff;
yDiff--;
}
console.log('getMomentum() Y:', yDiff, ', M:', mDiff, ', D:', dDiff);
}
Tested the above functions using following samples:
var sample1 = all('2/13/2018', '3/15/2018'); // {'M/D/YYYY'} 30, Y: 0 , M: 1 , D: 2
console.log(sample1);
var sample2 = all('10/09/2019', '7/7/2020'); // 272, Y: 0 , M: 8 , D: 29
console.log(sample2);
function all(start, end) {
dateDiffInDays(start, end);
dateDiffInDays_Months_Years(start, end);
try {
dateDiffUsingMoment(start, end);
} catch (e) {
console.log(e);
}
}
by using Moment library and some custom logic, we can get the exact date difference
var out;
out = diffDate(new Date('2014-05-10'), new Date('2015-10-10'));
display(out);
out = diffDate(new Date('2014-05-10'), new Date('2015-10-09'));
display(out);
out = diffDate(new Date('2014-05-10'), new Date('2015-09-09'));
display(out);
out = diffDate(new Date('2014-05-10'), new Date('2015-03-09'));
display(out);
out = diffDate(new Date('2014-05-10'), new Date('2016-03-09'));
display(out);
out = diffDate(new Date('2014-05-10'), new Date('2016-03-11'));
display(out);
function diffDate(startDate, endDate) {
var b = moment(startDate),
a = moment(endDate),
intervals = ['years', 'months', 'weeks', 'days'],
out = {};
for (var i = 0; i < intervals.length; i++) {
var diff = a.diff(b, intervals[i]);
b.add(diff, intervals[i]);
out[intervals[i]] = diff;
}
return out;
}
function display(obj) {
var str = '';
for (key in obj) {
str = str + obj[key] + ' ' + key + ' '
}
console.log(str);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js"></script>
I did it using a bunch of functions. Pure JavaScript and precise.
This code includes functions that calculate time difference in days, months and years. One of them can be used to get precise time difference for example X years, Y months, Z days. At the end of code I provided some tests.
How it works:
getDaysDiff():
Transforms time difference from milliseconds to days.
getYearsDiff():
There is no worries for effect of months and days of both dates. The function calculates difference in years by moving dates back and forward.
getMonthsDiff() (This one has nothing to do with question, but the concept is used in calExactTimeDiff() and I thought someone may need such a function so I insert it):
This one is a little tricky. The hard work is to deal with month and day of both dates.
If the endDate's month is more than startDate's, this means another year (12 months) is passed. But this is being taken care of in monthsOfFullYears, so the only thing is needed is to add subtraction of month of endDate and startDate.
If the startDate's month is more than endDate's then there is no another year. So we should get the difference between them. Imagine we want to go from month 10 of the current year to 2 of the next year. We can go like this: 11, 12, 1, 2. So we passed 4 months. This is equal to 12 - (10 - 2). We get difference between the months and subtract it from months of a whole year.
Next step is to take care of days of months. If day of endDate is more than or equal to startDate this means another month is passed. So we add 1 to it. But if it's less, then there is nothing to worry about. But in my code I did not do this. Because when I added difference between months I assumed that the days of months are equal. So I already added 1. Thus if day of endDate is less than startDate, I have to decrease months by 1.
There is an exception: if months are equal and endDate's day is less than startDate's, month should be 11.
I used the same concept in calExactTimeDiff().
Hope to be useful :)
// time difference in Days
function getDaysDiff(startDate = new Date(), endDate = new Date()) {
if (startDate > endDate) [startDate, endDate] = [endDate, startDate];
let timeDiff = endDate - startDate;
let timeDiffInDays = Math.floor(timeDiff / (1000 * 3600 * 24));
return timeDiffInDays;
}
// time difference in Months
function getMonthsDiff(startDate = new Date(), endDate = new Date()) {
let monthsOfFullYears = getYearsDiff(startDate, endDate) * 12;
let months = monthsOfFullYears;
// the variable below is not necessary, but I kept it for understanding of code
// we can use "startDate" instead of it
let yearsAfterStart = new Date(
startDate.getFullYear() + getYearsDiff(startDate, endDate),
startDate.getMonth(),
startDate.getDate()
);
let isDayAhead = endDate.getDate() >= yearsAfterStart.getDate();
if (startDate.getMonth() == endDate.getMonth() && !isDayAhead) {
months = 11;
return months;
}
if (endDate.getMonth() >= yearsAfterStart.getMonth()) {
let diff = endDate.getMonth() - yearsAfterStart.getMonth();
months += (isDayAhead) ? diff : diff - 1;
}
else {
months += isDayAhead
? 12 - (startDate.getMonth() - endDate.getMonth())
: 12 - (startDate.getMonth() - endDate.getMonth()) - 1;
}
return months;
}
// time difference in Years
function getYearsDiff(startDate = new Date(), endDate = new Date()) {
if (startDate > endDate) [startDate, endDate] = [endDate, startDate];
let yearB4End = new Date(
endDate.getFullYear() - 1,
endDate.getMonth(),
endDate.getDate()
);
let year = 0;
year = yearB4End > startDate
? yearB4End.getFullYear() - startDate.getFullYear()
: 0;
let yearsAfterStart = new Date(
startDate.getFullYear() + year + 1,
startDate.getMonth(),
startDate.getDate()
);
if (endDate >= yearsAfterStart) year++;
return year;
}
// time difference in format: X years, Y months, Z days
function calExactTimeDiff(firstDate, secondDate) {
if (firstDate > secondDate)
[firstDate, secondDate] = [secondDate, firstDate];
let monthDiff = 0;
let isDayAhead = secondDate.getDate() >= firstDate.getDate();
if (secondDate.getMonth() >= firstDate.getMonth()) {
let diff = secondDate.getMonth() - firstDate.getMonth();
monthDiff += (isDayAhead) ? diff : diff - 1;
}
else {
monthDiff += isDayAhead
? 12 - (firstDate.getMonth() - secondDate.getMonth())
: 12 - (firstDate.getMonth() - secondDate.getMonth()) - 1;
}
let dayDiff = 0;
if (isDayAhead) {
dayDiff = secondDate.getDate() - firstDate.getDate();
}
else {
let b4EndDate = new Date(
secondDate.getFullYear(),
secondDate.getMonth() - 1,
firstDate.getDate()
)
dayDiff = getDaysDiff(b4EndDate, secondDate);
}
if (firstDate.getMonth() == secondDate.getMonth() && !isDayAhead)
monthDiff = 11;
let exactTimeDiffUnits = {
yrs: getYearsDiff(firstDate, secondDate),
mths: monthDiff,
dys: dayDiff,
};
return `${exactTimeDiffUnits.yrs} years, ${exactTimeDiffUnits.mths} months, ${exactTimeDiffUnits.dys} days`
}
let s = new Date(2012, 4, 12);
let e = new Date(2008, 5, 24);
console.log(calExactTimeDiff(s, e));
s = new Date(2001, 7, 4);
e = new Date(2016, 6, 9);
console.log(calExactTimeDiff(s, e));
s = new Date(2011, 11, 28);
e = new Date(2021, 3, 6);
console.log(calExactTimeDiff(s, e));
s = new Date(2020, 8, 7);
e = new Date(2021, 8, 6);
console.log(calExactTimeDiff(s, e));
There a a couple of npm packages that help in doing this. Below is a list gathered from various sources. I find the date-fns version to be the most simplest.
1. date-fns
You can use intervalToDuration, formatDuration from date-fns to humanize a duration in desired format like below:
import { intervalToDuration, formatDuration } from 'date-fns'
let totalDuration = intervalToDuration({
start: new Date(1929, 0, 15, 12, 0, 0),
end: new Date(1968, 3, 4, 19, 5, 0)
});
let textDuration = formatDuration(totalDuration, { format: ['years', 'months'], delimiter: ', ' })
// Output: "39 years, 2 months"
clone the above code from here for trying it yourself: https://runkit.com/embed/diu9o3qe53j4
2. luxon + humanize-duration
you can use luxon to extract the duration between dates and humanize that using humanize-duration like below:
const DateTime = luxon.DateTime;
const Interval = luxon.Interval;
const start = DateTime.fromSQL("2020-06-19 11:14:00");
const finish = DateTime.fromSQL("2020-06-21 13:11:00");
const formatted = Interval
.fromDateTimes(start, finish)
.toDuration()
.valueOf();
console.log(humanizeDuration(formatted))
// output: 2 days, 1 hour, 57 minutes
console.log(humanizeDuration(formatted, { language: 'es' }))
// output: 2 días, 1 hora, 57 minutos
console.log(humanizeDuration(formatted, { language: 'ru' }))
// output: 2 дня, 1 час, 57 минут
<script src="https://cdn.jsdelivr.net/npm/luxon#1.25.0/build/global/luxon.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/humanize-duration#3.25.1/humanize-duration.min.js"></script>
reference to above code: https://stackoverflow.com/a/65651515/6908282
I would personally use http://www.datejs.com/, really handy. Specifically, look at the time.js file: http://code.google.com/p/datejs/source/browse/trunk/src/time.js
Time span in full Days, Hours, Minutes, Seconds, Milliseconds:
// Extension for Date
Date.difference = function (dateFrom, dateTo) {
var diff = { TotalMs: dateTo - dateFrom };
diff.Days = Math.floor(diff.TotalMs / 86400000);
var remHrs = diff.TotalMs % 86400000;
var remMin = remHrs % 3600000;
var remS = remMin % 60000;
diff.Hours = Math.floor(remHrs / 3600000);
diff.Minutes = Math.floor(remMin / 60000);
diff.Seconds = Math.floor(remS / 1000);
diff.Milliseconds = Math.floor(remS % 1000);
return diff;
};
// Usage
var a = new Date(2014, 05, 12, 00, 5, 45, 30); //a: Thu Jun 12 2014 00:05:45 GMT+0400
var b = new Date(2014, 02, 12, 00, 0, 25, 0); //b: Wed Mar 12 2014 00:00:25 GMT+0400
var diff = Date.difference(b, a);
/* diff: {
Days: 92
Hours: 0
Minutes: 5
Seconds: 20
Milliseconds: 30
TotalMs: 7949120030
} */
Neither of the codes work for me, so I use this instead for months and days:
function monthDiff(d2, d1) {
var months;
months = (d2.getFullYear() - d1.getFullYear()) * 12;
months -= d1.getMonth() + 1;
months += d2.getMonth() + 1;
return months <= 0 ? 0 : months;
}
function daysInMonth(date) {
return new Date(date.getYear(), date.getMonth() + 1, 0).getDate();
}
function diffDate(date1, date2) {
if (date2 && date2.getTime() && !isNaN(date2.getTime())) {
var months = monthDiff(date1, date2);
var days = 0;
if (date1.getUTCDate() >= date2.getUTCDate()) {
days = date1.getUTCDate() - date2.getUTCDate();
}
else {
months--;
days = date1.getUTCDate() - date2.getUTCDate() + daysInMonth(date2);
}
// Use the variables months and days how you need them.
}
}
The following is an algorithm which gives correct but not totally precise since it does not take into account leap year. It also assumes 30 days in a month. A good usage for example is if someone lives in an address from 12/11/2010 to 11/10/2011, it can quickly tells that the person lives there for 10 months and 29 days. From 12/11/2010 to 11/12/2011 is 11 months and 1 day. For certain types of applications, that kind of precision is sufficient. This is for those types of applications because it aims for simplicity:
var datediff = function(start, end) {
var diff = { years: 0, months: 0, days: 0 };
var timeDiff = end - start;
if (timeDiff > 0) {
diff.years = end.getFullYear() - start.getFullYear();
diff.months = end.getMonth() - start.getMonth();
diff.days = end.getDate() - start.getDate();
if (diff.months < 0) {
diff.years--;
diff.months += 12;
}
if (diff.days < 0) {
diff.months = Math.max(0, diff.months - 1);
diff.days += 30;
}
}
return diff;
};
Unit tests
To calculate the difference between two dates in Years, Months, Days, Minutes, Seconds, Milliseconds using TypeScript/ JavaScript
dateDifference(actualDate) {
// Calculate time between two dates:
const date1 = actualDate; // the date you already commented/ posted
const date2: any = new Date(); // today
let r = {}; // object for clarity
let message: string;
const diffInSeconds = Math.abs(date2 - date1) / 1000;
const days = Math.floor(diffInSeconds / 60 / 60 / 24);
const hours = Math.floor(diffInSeconds / 60 / 60 % 24);
const minutes = Math.floor(diffInSeconds / 60 % 60);
const seconds = Math.floor(diffInSeconds % 60);
const milliseconds =
Math.round((diffInSeconds - Math.floor(diffInSeconds)) * 1000);
const months = Math.floor(days / 31);
const years = Math.floor(months / 12);
// the below object is just optional
// if you want to return an object instead of a message
r = {
years: years,
months: months,
days: days,
hours: hours,
minutes: minutes,
seconds: seconds,
milliseconds: milliseconds
};
// check if difference is in years or months
if (years === 0 && months === 0) {
// show in days if no years / months
if (days > 0) {
if (days === 1) {
message = days + ' day';
} else { message = days + ' days'; }
} else if (hours > 0) {
if (hours === 1) {
message = hours + ' hour';
} else {
message = hours + ' hours';
}
} else {
// show in minutes if no years / months / days
if (minutes === 1) {
message = minutes + ' minute';
} else {message = minutes + ' minutes';}
}
} else if (years === 0 && months > 0) {
// show in months if no years
if (months === 1) {
message = months + ' month';
} else {message = months + ' months';}
} else if (years > 0) {
// show in years if years exist
if (years === 1) {
message = years + ' year';
} else {message = years + ' years';}
}
return 'Posted ' + message + ' ago';
// this is the message a user see in the view
}
However, you can update the above logic for the message to show seconds and milliseconds too or else use the object 'r' to format the message whatever way you want.
If you want to directly copy the code, you can view my gist with the above code here
I know it is an old thread, but I'd like to put my 2 cents based on the answer by #Pawel Miech.
It is true that you need to convert the difference into milliseconds, then you need to make some math. But notice that, you need to do the math in backward manner, i.e. you need to calculate years, months, days, hours then minutes.
I used to do some thing like this:
var mins;
var hours;
var days;
var months;
var years;
var diff = new Date() - new Date(yourOldDate);
// yourOldDate may be is coming from DB, for example, but it should be in the correct format ("MM/dd/yyyy hh:mm:ss:fff tt")
years = Math.floor((diff) / (1000 * 60 * 60 * 24 * 365));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 365));
months = Math.floor((diff) / (1000 * 60 * 60 * 24 * 30));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24 * 30));
days = Math.floor((diff) / (1000 * 60 * 60 * 24));
diff = Math.floor((diff) % (1000 * 60 * 60 * 24));
hours = Math.floor((diff) / (1000 * 60 * 60));
diff = Math.floor((diff) % (1000 * 60 * 60));
mins = Math.floor((diff) / (1000 * 60));
But, of course, this is not precise because it assumes that all years have 365 days and all months have 30 days, which is not true in all cases.
Its very simple please use the code below and it will give the difference in that format according to this //3 years 9 months 3 weeks 5 days 15 hours 50 minutes
Date.getFormattedDateDiff = function(date1, date2) {
var b = moment(date1),
a = moment(date2),
intervals = ['years','months','weeks','days'],
out = [];
for(var i=0; i<intervals.length; i++){
var diff = a.diff(b, intervals[i]);
b.add(diff, intervals[i]);
out.push(diff + ' ' + intervals[i]);
}
return out.join(', ');
};
var today = new Date(),
newYear = new Date(today.getFullYear(), 0, 1),
y2k = new Date(2000, 0, 1);
//(AS OF NOV 29, 2016)
//Time since New Year: 0 years, 10 months, 4 weeks, 0 days
console.log( 'Time since New Year: ' + Date.getFormattedDateDiff(newYear, today) );
//Time since Y2K: 16 years, 10 months, 4 weeks, 0 days
console.log( 'Time since Y2K: ' + Date.getFormattedDateDiff(y2k, today) );
This code should give you desired results
//************************** Enter your dates here **********************//
var startDate = "10/05/2014";
var endDate = "11/3/2016"
//******* and press "Run", you will see the result in a popup *********//
var noofdays = 0;
var sdArr = startDate.split("/");
var startDateDay = parseInt(sdArr[0]);
var startDateMonth = parseInt(sdArr[1]);
var startDateYear = parseInt(sdArr[2]);
sdArr = endDate.split("/")
var endDateDay = parseInt(sdArr[0]);
var endDateMonth = parseInt(sdArr[1]);
var endDateYear = parseInt(sdArr[2]);
console.log(startDateDay+' '+startDateMonth+' '+startDateYear);
var yeardays = 365;
var monthArr = [31,,31,30,31,30,31,31,30,31,30,31];
var noofyears = 0
var noofmonths = 0;
if((startDateYear%4)==0) monthArr[1]=29;
else monthArr[1]=28;
if(startDateYear == endDateYear){
noofyears = 0;
noofmonths = getMonthDiff(startDate,endDate);
if(noofmonths < 0) noofmonths = 0;
noofdays = getDayDiff(startDate,endDate);
}else{
if(endDateMonth < startDateMonth){
noofyears = (endDateYear - startDateYear)-1;
if(noofyears < 1) noofyears = 0;
}else{
noofyears = endDateYear - startDateYear;
}
noofmonths = getMonthDiff(startDate,endDate);
if(noofmonths < 0) noofmonths = 0;
noofdays = getDayDiff(startDate,endDate);
}
alert(noofyears+' year, '+ noofmonths+' months, '+ noofdays+' days');
function getDayDiff(startDate,endDate){
if(endDateDay >=startDateDay){
noofdays = 0;
if(endDateDay > startDateDay) {
noofdays = endDateDay - startDateDay;
}
}else{
if((endDateYear%4)==0) {
monthArr[1]=29;
}else{
monthArr[1] = 28;
}
if(endDateMonth != 1)
noofdays = (monthArr[endDateMonth-2]-startDateDay) + endDateDay;
else
noofdays = (monthArr[11]-startDateDay) + endDateDay;
}
return noofdays;
}
function getMonthDiff(startDate,endDate){
if(endDateMonth > startDateMonth){
noofmonths = endDateMonth - startDateMonth;
if(endDateDay < startDateDay){
noofmonths--;
}
}else{
noofmonths = (12-startDateMonth) + endDateMonth;
if(endDateDay < startDateDay){
noofmonths--;
}
}
return noofmonths;
}
https://jsfiddle.net/moremanishk/hk8c419f/
You should try using date-fns. Here's how I did it using intervalToDuration and formatDuration functions from date-fns.
let startDate = Date.parse("2010-10-01 00:00:00 UTC");
let endDate = Date.parse("2020-11-01 00:00:00 UTC");
let duration = intervalToDuration({start: startDate, end: endDate});
let durationInWords = formatDuration(duration, {format: ["years", "months", "days"]}); //output: 10 years 1 month
since I had to use moment-hijri (hijri calendar) and couldn't use moment.diff() method, I came up with this solution. can also be used with moment.js
var momenti = require('moment-hijri')
//calculate hijri
var strt = await momenti(somedateobject)
var until = await momenti()
var years = await 0
var months = await 0
var days = await 0
while(strt.valueOf() < until.valueOf()){
await strt.add(1, 'iYear');
await years++
}
await strt.subtract(1, 'iYear');
await years--
while(strt.valueOf() < until.valueOf()){
await strt.add(1, 'iMonth');
await months++
}
await strt.subtract(1, 'iMonth');
await months--
while(strt.valueOf() < until.valueOf()){
await strt.add(1, 'day');
await days++
}
await strt.subtract(1, 'day');
await days--
await console.log(years)
await console.log(months)
await console.log(days)
A solution with the ECMAScript "Temporal API" which is currently (as of 5th March 2022) in Stage 3 of Active Proposals, which will the method we will do this in the future (soon).
Here is a solution with the current temporal-polyfill
<script type='module'>
import * as TemporalModule from 'https://cdn.jsdelivr.net/npm/#js-temporal/polyfill#0.3.0/dist/index.umd.js'
const Temporal = temporal.Temporal;
//----------------------------------------
function dateDiff(start, end, maxUnit) {
return (Temporal.PlainDate.from(start).until(Temporal.PlainDate.from(end),{largestUnit:maxUnit}).toString()).match(/(\d*Y)|(\d*M)|(\d*D)/g).join(" ");
}
//----------------------------------------
console.log("Diff in (years, months, days): ",dateDiff("1963-02-03","2022-03-06","year"))
console.log("Diff in (months, days) : ",dateDiff("1963-02-03","2022-03-06","month"))
console.log("Diff in (days) : ",dateDiff("1963-02-03","2022-03-06","day"))
</script>
Your expected output is not correct. For example difference between '2014-05-10' and '2015-03-09' is not 9 months, 27 days
the correct answer is
(05-10 to 05-31) = 21 days
(2014-06 to 2015-03) = 9 months
(03-01 to 03-09) = 9 days
total is 9 months and 30 days
WARNING: An ideal function would be aware of leap years and days count in every month, but I found the results of this function accurate enough for my current task, so I shared it with you
function diffDate(date1, date2)
{
var daysDiff = Math.ceil((Math.abs(date1 - date2)) / (1000 * 60 * 60 * 24));
var years = Math.floor(daysDiff / 365.25);
var remainingDays = Math.floor(daysDiff - (years * 365.25));
var months = Math.floor((remainingDays / 365.25) * 12);
var days = Math.ceil(daysDiff - (years * 365.25 + (months / 12 * 365.25)));
return {
daysAll: daysDiff,
years: years,
months: months,
days:days
}
}
console.log(diffDate(new Date('2014-05-10'), new Date('2015-10-10')));
console.log(diffDate(new Date('2014-05-10'), new Date('2015-10-09')));
console.log(diffDate(new Date('2014-05-10'), new Date('2015-09-09')));
console.log(diffDate(new Date('2014-05-10'), new Date('2015-03-09')));
console.log(diffDate(new Date('2014-05-10'), new Date('2016-03-09')));
console.log(diffDate(new Date('2014-05-10'), new Date('2016-03-11')));