Showing "time ago" in a Social Feed using Intl.RelativeTimeFormat

madsstoumann

Mads Stoumann

Posted on January 18, 2022

Showing "time ago" in a Social Feed using Intl.RelativeTimeFormat

I'm currently implementing a Social Feed for a client, and had some issues with vulnerabilities in node_modules and an old "time-ago"-library.

Inspecting the code, I could see, that the code took a Date-object with .getTime(), compared it with the current time — new Date().getTime() — and then used a lot of code to return strings like "3 minutes ago", "2 days ago" etc.

Instead of finding another and newer "time-ago"-library, I decided to give it a go myself, and stumbled upon the RelativeTimeFormat of the Intl-API — supported in all browsers except Internet Explorer.

These wonderful methods greatly simplifies the code needed for a "time-ago"-library, so I wrote this simple method:

function timeAgo (timestamp, locale = 'en') => {
  let value;
  const diff = (new Date().getTime() - timestamp.getTime()) / 1000;
  const minutes = Math.floor(diff / 60);
  const hours = Math.floor(minutes / 60);
  const days = Math.floor(hours / 24);
  const months = Math.floor(days / 30);
  const years = Math.floor(months / 12);
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });

  if (years > 0) {
    value = rtf.format(0 - years, "year");
  } else if (months > 0) {
    value = rtf.format(0 - months, "month");
  } else if (days > 0) {
    value = rtf.format(0 - days, "day");
  } else if (hours > 0) {
    value = rtf.format(0 - hours, "hour");
  } else if (minutes > 0) {
    value = rtf.format(0 - minutes, "minute");
  } else {
    value = rtf.format(0 - diff, "second");
  }
  return value;
}
Enter fullscreen mode Exit fullscreen mode

It's 387 bytes minified, and just 244 bytes gzipped.


Testing it

I'm writing this on January 18th 2022, so this snippet:

const date1 = new Date('2022-01-01');
console.log(timeAgo(date1));
Enter fullscreen mode Exit fullscreen mode

... returns "17 days ago".

Let's change the locale to German:

console.log(timeAgo(date1, 'de'));
Enter fullscreen mode Exit fullscreen mode

This returns "vor 17 Tagen"´. With the locale fr, it returns "il y a 17 jours".

Try it yourself with your own language-locale.


Now, let's try a timestamp, that is just a few minutes in the past (as of time of writing!):

const date1 = new Date('2022-01-18T08:30:00.000Z');
Enter fullscreen mode Exit fullscreen mode

This returns "6 minutes ago" with an english locale.

If you just parse new Date(), the string will be "now" with an english locale.

If your Date() is in the future, it will be "[years|months|days|hours|minutes|seconds] from now".


Not all months are 30 days

Some of you might have wondered about this line of code:

const months = Math.floor(days / 30);
Enter fullscreen mode Exit fullscreen mode

And yes, this is not super-accurate, but an average value.
If you have timelines with very old entries, you might want to add a bit more code to handle months and years!


Photo by KoolShooters from Pexels

💖 💪 🙅 🚩
madsstoumann
Mads Stoumann

Posted on January 18, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related