Generate unique file path and hash

by Paweł Niemczyk

JavaScript

// function hashBase36(key, year, month) {
//   /* ──────────────── guard & defaults ──────────────── */
//   if (typeof key !== 'string') throw new TypeError('key must be a string');

//   const nowMs = Date.now();           // current Unix-epoch ms
//   let deltaMs;

//   if (typeof year === 'number' && Number.isFinite(year)) {
//     // year is provided ─► choose baseline
//     if (typeof month !== 'number' || month < 1 || month > 12) month = 1;
//     const t0 = new Date(year, month - 1, 1).getTime(); // 00:00 first day
//     deltaMs = nowMs - t0;
//   } else {
//     // no year ⇒ use full timestamp from epoch
//     deltaMs = nowMs;
//   }

//   const timePart = Math.abs(deltaMs).toString(36);

//   /* ─────────────── FNV-1a 32-bit of key ────────────── */
//   let h = 0x811c9dc5;                 // offset basis
//   for (let i = 0; i < key.length; i++) {
//     h ^= key.charCodeAt(i);
//     h = Math.imul(h, 0x01000193);     // prime 16777619
//   }
//   const keyPart = (h >>> 0).toString(36);

//   return `${timePart}-${keyPart}`;
// }

function hashBase36(key, year, month) {
  /* time part (base-36) */
  let timePart;
  if (typeof year === 'number' && typeof month === 'number') {
    const base = new Date(year, month - 1, 1).getTime();      // 1st-of-month
    timePart   = Math.abs(Date.now() - base).toString(36);    // delta → 36
  } else {
    timePart = Date.now().toString(36);                       // epoch → 36
  }

  if (!key) { return timePart }
  
  let h = 0x811c9dc5;
  for (let i = 0; i < key.length; i++) {
    h ^= key.charCodeAt(i);
    h = Math.imul(h, 0x01000193);
  }

  const keyPart = (h >>> 0).toString(36);

  return `${timePart}-${keyPart}`;
}

const first = hashBase36('company/accountant', 2025, 7)
const last = hashBase36('company/accountant')
const empty = hashBase36()

document.body.innerHTML = `First ${first}, Last ${last}, Empty ${empty}`