56 lines
2.2 KiB
JavaScript
56 lines
2.2 KiB
JavaScript
// retoor <retoor@molodetz.nl>
|
|
import { Poller } from "./Poller.js";
|
|
|
|
export class LocalTime {
|
|
constructor() {
|
|
this.dateFormat = new Intl.DateTimeFormat("en-GB", { day: "2-digit", month: "2-digit", year: "numeric" });
|
|
this.timeFormat = new Intl.DateTimeFormat("en-GB", { hour: "2-digit", minute: "2-digit" });
|
|
this.fullFormat = new Intl.DateTimeFormat("en-GB", { dateStyle: "full", timeStyle: "long" });
|
|
this.relative = new Intl.RelativeTimeFormat("en-GB", { numeric: "auto" });
|
|
this.renderAll(document);
|
|
this.observer = new MutationObserver((mutations) => {
|
|
mutations.forEach((mutation) => mutation.addedNodes.forEach((node) => node.nodeType === 1 && this.renderAll(node)));
|
|
});
|
|
this.observer.observe(document.body, { childList: true, subtree: true });
|
|
this.poller = new Poller(() => this.renderAll(document, "ago"), 60000, { pauseHidden: true }).start();
|
|
}
|
|
|
|
renderAll(root, onlyMode = null) {
|
|
const nodes = root.matches?.("time[data-dt]") ? [root] : root.querySelectorAll("time[data-dt]");
|
|
nodes.forEach((node) => {
|
|
if (!onlyMode || node.dataset.mode === onlyMode) {
|
|
this.render(node);
|
|
}
|
|
});
|
|
}
|
|
|
|
render(node) {
|
|
const date = new Date(node.dataset.dt);
|
|
if (Number.isNaN(date.getTime())) {
|
|
return;
|
|
}
|
|
const mode = node.dataset.mode || "datetime";
|
|
node.title = this.fullFormat.format(date);
|
|
if (mode === "date") {
|
|
node.textContent = this.dateFormat.format(date).replaceAll("-", "/");
|
|
} else if (mode === "time") {
|
|
node.textContent = this.timeFormat.format(date);
|
|
} else if (mode === "ago") {
|
|
node.textContent = this.ago(date);
|
|
} else {
|
|
node.textContent = `${this.dateFormat.format(date).replaceAll("-", "/")} ${this.timeFormat.format(date)}`;
|
|
}
|
|
}
|
|
|
|
ago(date) {
|
|
const seconds = Math.round((date.getTime() - Date.now()) / 1000);
|
|
const steps = [["year", 31536000], ["month", 2592000], ["day", 86400], ["hour", 3600], ["minute", 60]];
|
|
for (const [unit, size] of steps) {
|
|
if (Math.abs(seconds) >= size) {
|
|
return this.relative.format(Math.round(seconds / size), unit);
|
|
}
|
|
}
|
|
return this.relative.format(seconds, "second");
|
|
}
|
|
}
|