JavaScript Human-Readable Time Diff (“5 Hours Ago”, “Will Be In A Day”,…)

Some time ago, I’ve wrote an article iCompile – PHP Human-Readable Time Diff (“5 Hours Ago”, “Will Be In A Day”,…),
running the “main action” procedure in a recursive-loop, I could improve the spectrum of the result, so it will include also complex time-periods (“5 hours, 100 milliseconds”, “3 years, 12 days”, “3 days, 14 seconds”, etc…)
among other code improvements :)

[also available in my github’s gist: https://gist.github.com/eladkarako/65b3b395c5c9d5233f104eceeb7cede4]

```function human_time_diff(from, to){ /*accept unix-datetime integer, Date object or date string, fallback is current date*/
"use strict";

var now, diff;

/*---*/
function difference(diff){
var
MINUTE_IN_SECONDS = 60
, HOUR_IN_SECONDS   = 60  * MINUTE_IN_SECONDS
, DAY_IN_SECONDS    = 24  * HOUR_IN_SECONDS
, MONTH_IN_SECONDS  = 30  * DAY_IN_SECONDS
, YEAR_IN_SECONDS   = 365 * DAY_IN_SECONDS
, since
, milliseconds, seconds, minutes, hours, days, months, years
;

if(0 === diff){
since = "0 seconds";
}
else if(diff > 0 && diff < 1){
milliseconds = Math.trunc(diff * 1000);
since = milliseconds + " " + (1 === milliseconds ? "millisecond" : "milliseconds");
}
else if(diff >= 1 && diff < MINUTE_IN_SECONDS){
seconds = Math.trunc(diff);
seconds = Math.max(diff, 1);
since = seconds + " " + (1 === seconds ? "second" : "seconds");

diff = diff - (seconds);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}
else if(diff >= MINUTE_IN_SECONDS && diff < HOUR_IN_SECONDS){
minutes = Math.trunc(diff / MINUTE_IN_SECONDS);
minutes = Math.max(minutes, 1);
since = minutes + " " + (1 === minutes ? "minute" : "minutes");

diff  = diff - (minutes * MINUTE_IN_SECONDS);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}
else if(diff >= HOUR_IN_SECONDS && diff < DAY_IN_SECONDS){
hours = Math.trunc(diff / HOUR_IN_SECONDS);
hours = Math.max(hours, 1);
since = hours + " " + (1 === hours ? "hour" : "hours");

diff  = diff - (hours * HOUR_IN_SECONDS);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}
else if(diff >= DAY_IN_SECONDS && diff < MONTH_IN_SECONDS){
days = Math.trunc(diff / DAY_IN_SECONDS);
days = Math.max(days, 1);
since = days + " " + (1 === days ? "day" : "days");

diff  = diff - (days * DAY_IN_SECONDS);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}
else if(diff >= MONTH_IN_SECONDS && diff < YEAR_IN_SECONDS){
months = Math.trunc(diff / MONTH_IN_SECONDS);
months = Math.max(months, 1);
since = months + " " + (1 === months ? "month" : "months");

diff  = diff - (months * MONTH_IN_SECONDS);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}
else if (diff >= YEAR_IN_SECONDS){
years = Math.trunc(diff / YEAR_IN_SECONDS);
years = Math.max(diff, 1);
since = years + " " + (1 === years ? "year" : "years");

diff  = diff - (years * YEAR_IN_SECONDS);
if(diff > 0)
since = since + ", " + difference(diff);                             /* calculate leftover time, recursively */
}

return since;
}
/*---*/

now  = new Date();

from = ("number" === typeof from)                                                   ? Math.max(from, 0)      :
("string" === typeof from)                                                   ? Number(new Date(from)) :
("object" === typeof from && "date" === from.constructor.name.toLowerCase()) ? Number(from)           : Number(now)
;

to   = ("number" === typeof to)                                                     ? Math.max(to, 0)        :
("string" === typeof to)                                                     ? Number(new Date(to))   :
("object" === typeof to && "date" === to.constructor.name.toLowerCase())     ? Number(to)             : Number(now)

if("nan" === String(from).toLowerCase())  throw new Error("Error While Converting Date (first argument)" );
if("nan" === String(to).toLowerCase())    throw new Error("Error While Converting Date (second argument)");

diff = Math.abs(from - to);
console.log(from,to,diff);
return difference(diff);
}

/*
human_time_diff();                                // 0 seconds
human_time_diff("22:15:40");                      // ERROR (invalid date format)
human_time_diff(  Number(new Date()) - 2000  );   // 33 minutes, 20 seconds
human_time_diff( Number(new Date()) - 300 );      // 5 minutes
human_time_diff( Number(new Date()) - 300.123 );  // 5 minutes, 123 milliseconds
*/
```