Diff -- /var/www/vhosts/3dshawn.com/site1/assets/js/tz_localize.js

O Operator
Diff

/var/www/vhosts/3dshawn.com/site1/assets/js/tz_localize.js

added on local at 2026-07-10 23:21:48

Added
+77
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to e24b30de2fde
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1/*
2 * DriftSense -- viewer-local time renderer.
3 *
4 * Server stores everything in server-local time (or UTC). Perl emits every
5 * user-facing timestamp as:
6 *
7 * <span class="ts" data-ts="1720658362" data-fmt="datetime">2026-07-10 22:19:22</span>
8 *
9 * data-ts = UNIX epoch seconds (single source of truth, no ambiguity).
10 * data-fmt = "datetime" | "date" | "time" | "relative" | "date-short"
11 *
12 * This script rewrites the visible text to the viewer's browser locale +
13 * timezone. Runs once at DOMContentLoaded and again whenever `ts-refresh`
14 * is dispatched (for AJAX-inserted rows).
15 *
16 * Original server-side text stays inside as the graceful no-JS fallback.
17 */
18(function () {
19 'use strict';
20
21 function fmt(el) {
22 var raw = el.getAttribute('data-ts');
23 if (!raw) return;
24 var epoch = parseInt(raw, 10);
25 if (!epoch || isNaN(epoch)) return;
26 var d = new Date(epoch * 1000);
27 var kind = el.getAttribute('data-fmt') || 'datetime';
28 var out;
29 switch (kind) {
30 case 'date':
31 out = d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
32 break;
33 case 'date-short':
34 out = d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });
35 break;
36 case 'time':
37 out = d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
38 break;
39 case 'relative':
40 out = relative(epoch);
41 break;
42 default:
43 out = d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
44 + ' ' + d.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
45 }
46 el.textContent = out;
47 if (!el.title) el.title = d.toString(); // full timezone-aware tooltip
48 }
49
50 function relative(epoch) {
51 var now = Math.floor(Date.now() / 1000);
52 var s = now - epoch;
53 var future = s < 0;
54 s = Math.abs(s);
55 var unit, n;
56 if (s < 60) { n = s; unit = 'second'; }
57 else if (s < 3600) { n = Math.floor(s / 60); unit = 'minute'; }
58 else if (s < 86400) { n = Math.floor(s / 3600); unit = 'hour'; }
59 else if (s < 2592000){n = Math.floor(s / 86400); unit = 'day'; }
60 else if (s < 31536000){n= Math.floor(s / 2592000); unit = 'month';}
61 else { n = Math.floor(s / 31536000); unit = 'year';}
62 var plural = n === 1 ? '' : 's';
63 return future ? ('in ' + n + ' ' + unit + plural) : (n + ' ' + unit + plural + ' ago');
64 }
65
66 function localizeAll(root) {
67 (root || document).querySelectorAll('span.ts[data-ts], time[data-ts]').forEach(fmt);
68 }
69
70 if (document.readyState === 'loading') {
71 document.addEventListener('DOMContentLoaded', function () { localizeAll(); });
72 } else {
73 localizeAll();
74 }
75 window.addEventListener('ts-refresh', function () { localizeAll(); });
76 window.tzLocalize = localizeAll; // for programmatic use
77})();