NNicheStackTutorials
← All tutorials
Frontend Tools

epochkit: Unix Timestamps With Timezone Sanity and Saved Favorites

Debugging webhook logs across UTC and local. Converter plus localStorage favorites for the five API environments I juggle daily.

·10 min read·Frontend Tools
epochkit: Unix Timestamps With Timezone Sanity and Saved Favorites cover

Problem: Log line said 1714521600. Is that seconds or milliseconds? Built a tool that detects both and remembers my staging server offset.

Full tool

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Timestamp Converter</title>
  <style>
    body { font-family: system-ui; max-width: 640px; margin: 2rem auto; padding: 0 1rem; }
    input { width: 100%; padding: .5rem; font-family: monospace; margin: .25rem 0; }
    .grid { display: grid; gap: .75rem; }
    .fav { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: 1rem; }
    .fav button { font-size: 12px; }
  </style>
</head>
<body>
  <h1>Timestamp Converter</h1>
  <div class="grid">
    <label>Unix timestamp <input id="ts" placeholder="1714521600"></label>
    <label>ISO / local <input id="iso" placeholder="2024-05-01T00:00:00"></label>
    <label>Human <output id="human"></output></label>
  </div>
  <button id="now">Now</button>
  <button id="save">Save favorite</button>
  <div class="fav" id="favs"></div>
  <script>
    const ts = document.getElementById('ts');
    const iso = document.getElementById('iso');
    const human = document.getElementById('human');
    const favsEl = document.getElementById('favs');
    const KEY = 'epochkit-favs';

    function loadFavs() {
      try { return JSON.parse(localStorage.getItem(KEY) || '[]'); }
      catch { return []; }
    }
    function saveFavs(arr) { localStorage.setItem(KEY, JSON.stringify(arr)); }

    function parseTs(raw) {
      const n = Number(String(raw).trim());
      if (!Number.isFinite(n)) return null;
      if (String(raw).length >= 13) return n;
      return n * 1000;
    }

    function fromTs() {
      const ms = parseTs(ts.value);
      if (ms == null) return;
      const d = new Date(ms);
      iso.value = d.toISOString().slice(0, 19);
      human.textContent = d.toLocaleString();
    }

    function fromIso() {
      const d = new Date(iso.value);
      if (isNaN(d)) return;
      ts.value = Math.floor(d.getTime() / 1000);
      human.textContent = d.toLocaleString();
    }

    ts.oninput = fromTs;
    iso.oninput = fromIso;

    document.getElementById('now').onclick = () => {
      const d = new Date();
      ts.value = Math.floor(d.getTime() / 1000);
      fromTs();
    };

    document.getElementById('save').onclick = () => {
      const label = prompt('Label for this timestamp?', iso.value);
      if (!label) return;
      const favs = loadFavs();
      favs.push({ label, ts: ts.value });
      saveFavs(favs.slice(-10));
      renderFavs();
    };

    function renderFavs() {
      favsEl.innerHTML = '';
      loadFavs().forEach((f, i) => {
        const b = document.createElement('button');
        b.textContent = f.label;
        b.onclick = () => { ts.value = f.ts; fromTs(); };
        favsEl.appendChild(b);
      });
    }
    renderFavs();
  </script>
</body>
</html>

Milliseconds vs seconds

10-digit → multiply by 1000. 13-digit → use as-is. Stops the classic 1970 vs 2024 confusion.

localStorage quota

10 favorites max. Each is ~50 bytes — nowhere near 5MB limit.

Verify

Click Now → both fields populate Save favorite → reload page → button restores timestamp Enter 1714521600 → shows May 2024 UTC

Tags: TimestampDatelocalStorageVanilla JS