Relative Time Formatting (ago, in, just now)

Implement relative time displays like '5 minutes ago' and 'in 3 days'. Learn Intl.RelativeTimeFormat, library solutions, and best practices for user-friendly timestamps.

Concepts

Detailed Explanation

Relative Time Formatting

Relative time displays like "5 minutes ago", "in 2 hours", or "yesterday" are more intuitive than absolute timestamps for recent events. Every social media platform, chat app, and notification system uses this pattern.

Intl.RelativeTimeFormat (Native JavaScript)

Modern browsers and Node.js support the Intl.RelativeTimeFormat API:

const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" });

rtf.format(-1, "day");     // "yesterday"
rtf.format(-5, "minute");  // "5 minutes ago"
rtf.format(3, "hour");     // "in 3 hours"
rtf.format(0, "day");      // "today"

// With numeric: "always"
const rtf2 = new Intl.RelativeTimeFormat("en", { numeric: "always" });
rtf2.format(-1, "day");    // "1 day ago"

Localization

// Japanese
new Intl.RelativeTimeFormat("ja").format(-5, "minute");
// "5 分前"

// German
new Intl.RelativeTimeFormat("de").format(-1, "day");
// "vor 1 Tag"

// French
new Intl.RelativeTimeFormat("fr").format(2, "hour");
// "dans 2 heures"

Implementation Logic

The typical algorithm for choosing the appropriate unit:

function relativeTime(date) {
  const diff = Date.now() - date.getTime();
  const abs = Math.abs(diff);
  const sign = diff > 0 ? -1 : 1;

  if (abs < 60_000)        return "just now";
  if (abs < 3_600_000)     return rtf.format(sign * Math.floor(abs / 60_000), "minute");
  if (abs < 86_400_000)    return rtf.format(sign * Math.floor(abs / 3_600_000), "hour");
  if (abs < 2_592_000_000) return rtf.format(sign * Math.floor(abs / 86_400_000), "day");
  if (abs < 31_536_000_000) return rtf.format(sign * Math.floor(abs / 2_592_000_000), "month");
  return rtf.format(sign * Math.floor(abs / 31_536_000_000), "year");
}

Library Solutions

Library Function Example
date-fns formatDistanceToNow() "5 minutes ago"
Day.js dayjs().fromNow() "5 minutes ago"
moment.js moment().fromNow() "5 minutes ago"
Luxon DateTime.toRelative() "5 minutes ago"

Best Practices

  1. Show absolute time on hover/long-press — always let users see the exact timestamp
  2. Stop updating after a threshold — switch to absolute dates after 7 days or 30 days
  3. Use "just now" for < 1 minute — avoid "0 seconds ago"
  4. Consider real-time updates — use setInterval or requestAnimationFrame for live feeds
  5. Respect locale — use Intl API or library i18n for proper pluralization rules

Use Case

Relative time formatting is essential for social media feeds (Twitter, Reddit), chat applications (Slack, Discord), notification systems, comment sections, email clients (inbox timestamps), version control history (commit dates), and any UI where recent activity is displayed.

Try It — Date Format Reference & Tester

Open full tool