All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 28s
38 lines
1.3 KiB
JavaScript
38 lines
1.3 KiB
JavaScript
// Relative timestamp ("time ago") for <time> elements
|
|
(function () {
|
|
function timeAgo(date) {
|
|
const now = new Date();
|
|
const seconds = Math.floor((now - date) / 1000);
|
|
if (seconds < 5) return 'just now';
|
|
if (seconds < 60) return seconds + 's ago';
|
|
const minutes = Math.floor(seconds / 60);
|
|
if (minutes < 60) return minutes + 'm ago';
|
|
const hours = Math.floor(minutes / 60);
|
|
if (hours < 24) return hours + 'h ago';
|
|
const days = Math.floor(hours / 24);
|
|
if (days < 7) return days + 'd ago';
|
|
if (days < 30) return Math.floor(days / 7) + 'w ago';
|
|
if (days < 365) return Math.floor(days / 30) + 'mo ago';
|
|
return Math.floor(days / 365) + 'y ago';
|
|
}
|
|
|
|
function updateTimes() {
|
|
document.querySelectorAll('time[datetime]').forEach(function (el) {
|
|
var raw = el.getAttribute('datetime');
|
|
// SQLite stores UTC dates without a 'Z' suffix — add it so the browser
|
|
// parses them as UTC instead of local time
|
|
if (raw && !/[Z+\-]\d{0,4}$/i.test(raw)) {
|
|
raw = raw.replace(' ', 'T') + 'Z';
|
|
}
|
|
var d = new Date(raw);
|
|
if (!isNaN(d)) {
|
|
el.textContent = timeAgo(d);
|
|
el.title = d.toLocaleString();
|
|
}
|
|
});
|
|
}
|
|
|
|
updateTimes();
|
|
setInterval(updateTimes, 30000); // refresh every 30s
|
|
})();
|