Relative Time Formatter
Turn two timestamps into a friendly relative time phrase.
Overview
The Relative Time Formatter takes two timestamps — or one timestamp and "now" — and renders the difference as a friendly phrase like "5 minutes ago," "in 3 days," or "about 2 years ago." The output matches the conventions used by Twitter, GitHub, Slack, and other social or collaboration tools that show timestamps relative to the current moment.
Useful for developers wanting a quick reference for how a given delta would render, content writers crafting microcopy, QA engineers verifying that their app's relative timestamps match expectations across edge cases, and translators previewing how phrasing changes around the singular/plural boundary.
How it works
The formatter implements the same buckets used by the JavaScript Intl.RelativeTimeFormat API and the popular date-fns and moment.js libraries: under a minute → "just now," under an hour → "N minutes ago," under a day → "N hours ago," then days, weeks, months, and years. Negative deltas (in the future) get an "in N units" prefix.
Boundary rounding follows the standard convention of rounding to the nearest larger unit once the smaller unit hits 75% — so 44 days reads "1 month ago" and 22 hours reads "1 day ago." The result is locale-independent in the strict sense (English only) but the bucket boundaries match the ICU rules for every supported language.
Examples
Now − 30 seconds → "just now"
Now − 45 minutes → "45 minutes ago"
Now − 22 hours → "about 1 day ago"
Now + 3 days → "in 3 days"
Now − 50 days → "about 2 months ago"
FAQ
Why does 22 hours round to "1 day"?
The convention used by most popular libraries rounds at 75% of the next unit. 22 hours is past the 18-hour threshold, so it bumps up to "about 1 day ago." It avoids the awkward "23 hours ago" reading just before midnight.
Are months calendar-aware?
No — once you cross into months and years, the formatter uses average lengths (30 days per month, 365 days per year) for the threshold checks. The phrase says "about" to flag the approximation.
How does it handle future times?
The "in" prefix replaces "ago": in 5 minutes, in 2 days. The unit buckets are identical to the past-direction version.
Why does it say "just now" for anything under a minute?
Sub-minute precision is rarely useful to humans and clashes with clock skew between client and server. "Just now" is the standard fallback across every major library.
Is it locale-aware?
This tool emits English text. For other languages, use the ICU MessageFormat or Intl.RelativeTimeFormat API in the destination application — the bucket logic translates cleanly.