Files
ad/molodetz/static/js/utils/LocalTime.js
T

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");
}
}