size: 1 KiB
const millisecondsPerSecond = 1000; const secondsPerMinute = 60; const minutesPerHour = 60; const hoursPerDay = 24; const daysPerWeek = 7; const daysPerMonth = 31; const daysPerYear = 365; // getting imprecise here, but no big deal const intervals = { year: millisecondsPerSecond * secondsPerMinute * minutesPerHour * hoursPerDay * daysPerYear, month: millisecondsPerSecond * secondsPerMinute * minutesPerHour * hoursPerDay * daysPerMonth, week: millisecondsPerSecond * secondsPerMinute * minutesPerHour * hoursPerDay * daysPerWeek, day: millisecondsPerSecond * secondsPerMinute * minutesPerHour * hoursPerDay, hour: millisecondsPerSecond * secondsPerMinute * minutesPerHour, minute: millisecondsPerSecond * secondsPerMinute, second: millisecondsPerSecond, }; const relativeDateFormat = new Intl.RelativeTimeFormat("en", { style: "long" }); // https://stackoverflow.com/a/78704662 function formatRelativeTime(isoStr) { const diff = new Date(isoStr) - new Date(); for (const interval in intervals) { if (intervals[interval] <= Math.abs(diff)) { return relativeDateFormat.format( Math.trunc(diff / intervals[interval]), interval, ); } } return relativeDateFormat.format(diff / 1000, "second"); } document.addEventListener("DOMContentLoaded", function () { // Progressive enhancement: If javascript is enabled, certain <time> elements // will be rewritten from ISO datetime strings to human-readable relative text // (e.g. 2 days ago). document.querySelectorAll("time.relative").forEach((element) => { const timeStr = element.getAttribute("datetime"); if (!timeStr) return; const relativeTimeStr = formatRelativeTime(timeStr); element.innerHTML = relativeTimeStr; }); });