Functional Weave
Code in Rust

time.iso-to-unix@1.0.0

impl/typescript.ts

1,903 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { epochDayFromIso } from "./dates_add_days.ts";  ← from dates.add-days ^1.0.0 · built alongside by fune

function isDigit(text: string, i: number): boolean {
  const c = text.charCodeAt(i);
  return c >= 48 && c <= 57;
}

function num(text: string, from: number, to: number): number {
  let n = 0;
  for (let i = from; i < to; i++) n = n * 10 + (text.charCodeAt(i) - 48);
  return n;
}

/**
 * An RFC 3339 date-time to Unix seconds. Parsed by position, not with a
 * regular expression or Date.parse, which accepts a dozen other shapes and
 * reads a zoneless time in the machine's own zone.
 */
export function isoToUnix(timestamp: string): number {
  const bad = (): Error => new RangeError(`"${timestamp}" is not an RFC 3339 timestamp such as 2026-09-26T12:00:00Z`);
  if (typeof timestamp !== "string") throw bad();
  const t = timestamp;
  if (t.length < 20) throw bad();
  for (const i of [0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 14, 15, 17, 18]) {
    if (!isDigit(t, i)) throw bad();
  }
  if (t[4] !== "-" || t[7] !== "-" || (t[10] !== "T" && t[10] !== "t") || t[13] !== ":" || t[16] !== ":") throw bad();
  let i = 19;
  if (t[i] === ".") {
    i++;
    const start = i;
    while (i < t.length && isDigit(t, i)) i++;
    if (i === start) throw bad();
  }
  let offset = 0;
  if ((t[i] === "Z" || t[i] === "z") && i + 1 === t.length) {
    offset = 0;
  } else if ((t[i] === "+" || t[i] === "-") && i + 6 === t.length && isDigit(t, i + 1) && isDigit(t, i + 2) && t[i + 3] === ":" && isDigit(t, i + 4) && isDigit(t, i + 5)) {
    const oh = num(t, i + 1, i + 3);
    const om = num(t, i + 4, i + 6);
    if (oh > 23 || om > 59) throw bad();
    offset = (t[i] === "+" ? 1 : -1) * (oh * 3600 + om * 60);
  } else {
    throw bad();
  }
  const h = num(t, 11, 13);
  const m = num(t, 14, 16);
  const s = num(t, 17, 19);
  if (h > 23 || m > 59 || s > 59) throw bad();
  return epochDayFromIso(t.slice(0, 10)) * 86400 + h * 3600 + m * 60 + s - offset;
}