39 lines
1.2 KiB
JavaScript
39 lines
1.2 KiB
JavaScript
// Simple, timezone-safe if you pass UTC (…Z) in the datetime
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const els = document.querySelectorAll('time.countdown');
|
|
if (!els.length) return;
|
|
|
|
const plural = (n, w) => `${n} ${w}${n === 1 ? '' : 's'}`;
|
|
|
|
const render = (el) => {
|
|
const raw = el.getAttribute('datetime');
|
|
const label = el.dataset.label || '';
|
|
const target = new Date(raw); // Prefer ISO like 2025-12-31T00:00:00Z
|
|
if (isNaN(target)) { el.textContent = '—'; return; }
|
|
|
|
const now = new Date();
|
|
let diff = target - now;
|
|
|
|
if (diff <= 0) {
|
|
el.textContent = `${label ? label + ' ' : ''}today`;
|
|
el.classList.add('expired');
|
|
return;
|
|
}
|
|
|
|
const d = Math.floor(diff / 86400000); diff -= d * 86400000;
|
|
const h = Math.floor(diff / 3600000); diff -= h * 3600000;
|
|
const m = Math.floor(diff / 60000); diff -= m * 60000;
|
|
const s = Math.floor(diff / 1000);
|
|
|
|
const pieces = [];
|
|
if (d) pieces.push(plural(d, 'day'));
|
|
pieces.push(`${h}h ${m}m ${s}s`);
|
|
|
|
el.textContent = `${label ? label + ' in : ' : ''}${pieces.join(' ')}`;
|
|
};
|
|
|
|
const tick = () => els.forEach(render);
|
|
tick();
|
|
setInterval(tick, 1000); // update every second
|
|
});
|