Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

formatTimeAgo

Formats a date into a relative time string like "5 minutes ago".

TypeScript
Copied!
1/**
2 * Formats a date into a relative time string like "5 minutes ago".
3 *
4 * @param date - The date to format.
5 * @param now - Optional reference date (defaults to current time).
6 * @returns A human-readable relative time string.
7 */
8export function formatTimeAgo(date: Date, now: Date = new Date()): string {
9  const diffMs = now.getTime() - date.getTime();
10  const diffSec = Math.floor(diffMs / 1000);
11
12  const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
13
14  if (diffSec < 60) return rtf.format(-diffSec, 'second');
15  
16  const diffMin = Math.floor(diffSec / 60);
17  if (diffMin < 60) return rtf.format(-diffMin, 'minute');
18  
19  const diffHr = Math.floor(diffMin / 60);
20  if (diffHr < 24) return rtf.format(-diffHr, 'hour');
21  
22  const diffDay = Math.floor(diffHr / 24);
23  if (diffDay < 30) return rtf.format(-diffDay, 'day');
24  
25  const diffMonth = Math.floor(diffDay / 30);
26  if (diffMonth < 12) return rtf.format(-diffMonth, 'month');
27  
28  const diffYear = Math.floor(diffMonth / 12);
29  return rtf.format(-diffYear, 'year');
30}
  • Human-Friendly Output

    Generates natural language strings like “2 hours ago” or “last month” using Intl.RelativeTimeFormat, enhancing user experience.

  • Locale-Safe and Future-Proof

    Leverages the built-in internationalization API, making it robust and adaptable to multilingual needs if expanded.

  • Granular Time Resolution

    Covers multiple levels of time granularity — from seconds to years — without extra dependencies.

  • Optional Reference Date

    Allows comparison against a custom reference (now), enabling testing or simulation scenarios.

  • Clean Fallbacks

    Uses numeric: 'auto' to allow friendly strings like "yesterday" instead of rigid numerical formats.

Tests | Examples

TypeScript
Copied!
1const now = new Date('2024-06-27T12:00:00Z');
2
3test('formats seconds ago', () => {
4  const date = new Date('2024-06-27T11:59:45Z');
5  expect(formatTimeAgo(date, now)).toBe('15 seconds ago');
6});
7
8test('formats minutes ago', () => {
9  const date = new Date('2024-06-27T11:57:00Z');
10  expect(formatTimeAgo(date, now)).toBe('3 minutes ago');
11});
12
13test('formats hours ago', () => {
14  const date = new Date('2024-06-27T09:00:00Z');
15  expect(formatTimeAgo(date, now)).toBe('3 hours ago');
16});
17
18test('formats days ago', () => {
19  const date = new Date('2024-06-25T12:00:00Z');
20  expect(formatTimeAgo(date, now)).toBe('2 days ago');
21});
22
23test('formats months ago', () => {
24  const date = new Date('2024-03-27T12:00:00Z');
25  expect(formatTimeAgo(date, now)).toBe('3 months ago');
26});
27
28test('formats years ago', () => {
29  const date = new Date('2022-06-27T12:00:00Z');
30  expect(formatTimeAgo(date, now)).toBe('2 years ago');
31});

Common Use Cases

  • Social Media Timestamps

    Show when a post, comment, or message was created in a natural, compact way.

  • Notification Logs

    Display how recently a user received alerts, warnings, or updates.

  • Activity Feeds

    Communicate recency of user activity (e.g. "signed in 2 days ago").

  • Data Versioning or Sync Info

    Indicate how stale or fresh certain cached or synced data is.

  • UI Enhancements in Time-Based Apps

    Improve UX in calendars, schedules, or time trackers by showing relative dates.

Codebase: Utilities -> Dates -> formatTimeAgo | Yevhen Klymentiev