# Get the difference between two dates, in the most convenient unit

I use the following code in Javascript to get the difference between two Date objects. I want the result to return the difference in:

• seconds if the result is less than 60 secs
• minutes if the result is less than 60 mins
• hours if the result is less than 24 hours
• days otherwise

The code is very long and I see lots of code duplication. Isn't there a smarter/shorter way to do this (without using a library)?

function dateDiff(a, b) {
let utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate(), a.getUTCHours(), a.getUTCMinutes(), a.getUTCSeconds());
let utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate(), b.getUTCHours(), b.getUTCMinutes(), b.getUTCSeconds());

let result = (utc2 - utc1) / (1000 * 60 * 60 * 24);
let floor = Math.floor(result);
if (floor > 0) return floor + "d";

result *= 24;
floor = Math.floor(result);
if (floor > 0) return floor + "h";

result *= 60;
floor = Math.floor(result);
if (floor > 0) return floor + "min";

result *= 60;
floor = Math.floor(result);
if (floor > 0) return floor + "sec";
}


## migrated from stackoverflow.comJan 15 '17 at 8:21

This question came from our site for professional and enthusiast programmers.

• Can't you just use Math.floor once? You're multiplying by whole numbers. – David Archibald Jan 14 '17 at 21:29

Use getTime instead of the UTC transformation it'll return the timeStamp.

So your diff would be:

b.getTime() - a.getTime()


This will give you the milliseconds if you want the seconds you would divide it by 1000 so you would get:

var secondsDiff = (b.getTIme() - a.getTime())/1000


Then for the return

if (secondsDiff > 86400)  {
return Math.floor(secondsDiff/86400) + ' D'
}
if (secondsDiff > 3600)  {
return Math.floor(secondsDiff/3600) + ' h'
}
if (secondsDiff > 60)  {
return Math.floor(secondsDiff/60) + ' min'
}
if (secondsDiff > 0) {
return secondsDiff + ' sec'
}

• How about some details. I didn't downvote, but a one sentence answer isn't quite long enough. How about comment something like this next time. – David Archibald Jan 14 '17 at 21:23
• Well it's a broad field of make the code more efficient, but from the start the first thing that catchs the eye is the Utc misuse when you could have getTime. Plus I put the link but there isn't really much to say about getTime – FabioCosta Jan 14 '17 at 21:25
• This is kind of the gray zone. Yes, it's an answer, but I feel that it can be improved and you've been downvoted likely because it's not detailed enough. So if it can be improved, why not improve it? Up to you. – David Archibald Jan 14 '17 at 21:27
• Ok expanded the answer then. – FabioCosta Jan 14 '17 at 21:36
• If you combined this with trincot's answer (using a for loop) your code would become even shorter and I'd love to accept it as the right answer codereview.stackexchange.com/a/152683/128754 – Timo Jan 20 '17 at 13:08

I wanted to play with the fact that 3 out of 4 if tests are comparing to exponent of 60 (0, 60 and 3600) and came up with the code that is maybe a line shorter but much less readble. However, was interested if it's faster. I compared it on jsperf.com with FabioCosta's solution as was cutious. https://jsperf.com/datediff-compare2

Performance test result are maybe not enough to reach a conclusion, but out of 10 tests it turns out to be from -2% to +14% faster on Chrome55/Linux.

  function dateDiff2(d1,d2) {
var a = (d1.getTime() - d2.getTime())/1000;
if (a >= 86400) return Math.floor(a/86400) + ' D';
var labels=["sec","min","h"];
var p = Math.floor((Math.log(a) / Math.log(60)));
return Math.floor(a/Math.pow(60,p)) + labels[p];
}

/* test data */
var dates=[
[new Date(1483225200000),new Date(1483225199000)],
[new Date(1483225200000),new Date(1483225139000)],
[new Date(1483225200000),new Date(1483221599000)],
[new Date(1483225200000),new Date(1483138799000)]
]

console.log(dates.map(test=>dateDiff2(test[0],test[1])));

You could put it in a loop if you store the specifics about the time units in an array. This is ES6 code:

function dateDiff(a, b) {
const units = [{size: 60*60*24, name: 'd'  },
{size: 60*60,    name: 'h'  },
{size: 60,       name: 'min'},
{size: 1,        name: 'sec'}];
const result = (b.getTime() - a.getTime()) / 1000;
const unit = units.find( unit => result >= unit.size );
return Math.floor(result / unit.size) + unit.name;
}

console.log(dateDiff(new Date(2016, 0, 14, 20), new Date(2016, 0, 14, 23, 58, 20)));

• How about a simple hashmap for units, like {d : 60 * 60* 24, … }? – lxg Jan 14 '17 at 21:50
• @lxg, sure, but then you have to specify d, h, min, ... twice, since you need to make sure you iterate in the correct order. – trincot Jan 15 '17 at 8:56