Relative date time web component
A simple, progressive web component to show a relative "time ago" for a date time.
<html>
<body>
<h1>Relative time web component examples</h1>
<p>
Published
<time is="relative-time" datetime="2024-01-22T12:00:00Z">
January 22, 2024
</time>
</p>
<p>
Published
<time is="relative-time" datetime="2024-01-15T12:00:00Z">
January 15, 2024
</time>
</p>
<h2>International Support</h2>
<p>
Publicado
<time is="relative-time" datetime="2023-12-22T12:00:00Z" lang="es">
22 de diciembre de 2023
</time>
</p>
<script>
class RelativeTime extends HTMLTimeElement {
connectedCallback() {
const date = new Date(this.dateTime);
const now = new Date();
const elapsed = now - date;
const lang = this.lang || "en";
const formatter = new Intl.RelativeTimeFormat(lang, {
numeric: "auto",
});
const minutes = Math.floor(elapsed / 60000);
const hours = Math.floor(elapsed / 3600000);
const days = Math.floor(elapsed / 86400000);
const weeks = Math.floor(elapsed / 604800000);
const months = Math.floor(elapsed / 2628000000);
const years = Math.floor(elapsed / 31540000000);
let relativeTime;
if (minutes < 1) {
relativeTime = formatter.format(0, "minute");
} else if (minutes < 60) {
relativeTime = formatter.format(-minutes, "minute");
} else if (hours < 24) {
relativeTime = formatter.format(-hours, "hour");
} else if (days < 7) {
relativeTime = formatter.format(-days, "day");
} else if (weeks < 4) {
relativeTime = formatter.format(-weeks, "week");
} else if (months < 12) {
relativeTime = formatter.format(-months, "month");
} else {
relativeTime = formatter.format(-years, "year");
}
this.textContent = relativeTime;
}
}
customElements.define("relative-time", RelativeTime, {
extends: "time",
});
</script>
</body>
</html>
Key features
- Progressive enhancement - Falls back to original date text if JavaScript fails
- Accessible - Extends semantic
<time>element - Internationalised - Uses
Intl.RelativeTimeFormatwithlangattribute support - One-time calculation - Calculates relative time on page load (doesn't auto-update)
Note: This calculates once when the component loads. For live updating times, you'd need to add an interval timer.