
humantime-js is a dependency-free JavaScript utility that converts JavaScript Date objects into human-friendly timeago labels such as just now, 12 minutes ago, and yesterday.
The library exposes a single synchronous function. You pass a JavaScript Date, and you immediately get a string you can render in a comment feed, a dashboard activity panel, a blog post byline, or any UI where raw timestamps feel cold.
Features:
- Weighs under 1 KB and loads instantly.
- Works in browsers and Node.js.
- Returns strings that use natural singular and plural forms.
- Handles seconds, minutes, hours, days, months, and years.
- ES module, a CommonJS build, and a UMD bundle for direct browser usage.
- Uses no internal timers or state that would require cleanup.
How To Use It:
Installation
Install the package with NPM.
npm install humantime-js
Basic Usage
Import timeAgo() and pass it a valid JavaScript Date object.
import { timeAgo } from 'humantime-js';
// Create a timestamp from 14 minutes earlier.
const articlePublishedAt = new Date(Date.now() - 14 * 60 * 1000);
// Convert the Date object into relative text.
const publishedLabel = timeAgo(articlePublishedAt);
console.log(publishedLabel); // "14 minutes ago"
Browser Usage
Load the local script before code that accesses the HumanTime global.
<script src="/assets/humantime.umd.js"></script>
<script>
// Select an existing timestamp label in the page.
const updatedLabel = document.querySelector('[data-last-updated]');
// Format the stored update date.
const updatedAt = new Date('2026-06-30T13:20:00Z');
updatedLabel.textContent = HumanTime.timeAgo(updatedAt);
</script>
More Examples
Refresh a visible timestamp
import { timeAgo } from 'humantime-js';
const commentCreatedAt = new Date('2026-06-30T13:20:00Z');
const commentAgeLabel = document.querySelector('[data-comment-age]');
function refreshCommentAge() {
commentAgeLabel.textContent = timeAgo(commentCreatedAt);
}
// Render the first value immediately.
refreshCommentAge();
// Refresh the label every 30 seconds.
const commentAgeTimer = window.setInterval(refreshCommentAge, 30000);
// Call clearInterval(commentAgeTimer) when the view is removed.
Render API timestamps after data loads
import { timeAgo } from 'humantime-js';
async function renderLastDeployment() {
const response = await fetch('/api/deployments/latest');
const deployment = await response.json();
const deployedAt = new Date(deployment.completedAt);
const deploymentLabel = document.querySelector('[data-last-deployment]');
deploymentLabel.textContent = Number.isNaN(deployedAt.getTime())
? 'Deployment time unavailable'
: timeAgo(deployedAt);
}
Alternatives:
- Relative Time Element for Time Ago Text
- Convert Timestamp To User-friendly Format: relative-time.js
- Human-friendly Relative Time Formatter: human-time
- Tiny JS Library for Human-Readable Timestamps: little-timestamp
- Lightweight Human Readable Date & Time Library: timeago.js
FAQs:
Q: Does humantime-js update timestamp labels automatically?
A: No. The library returns one formatted string for the time you pass in. Call timeAgo() again when your interface needs a newer label.
Q: Can humantime-js format future dates for upcoming events?
A: No. The distributed formatter focuses on elapsed past time. Use a relative time library with future-tense support for labels such as in 2 hours.
Q: Why does my timestamp show NaN years ago?
A: The supplied value is not a valid date. Create a Date object first and check Number.isNaN(date.getTime()) before calling timeAgo().
Q: Can I pass an ISO timestamp string directly?
A: Convert the string with new Date(isoString) first.







