import { describe, expect, it } from "vitest"; import { canonicalSymbol, makeInstrumentId, parseTimestamp, splitPair, tzOffsetMs, zonedParts, zonedTimeToUtc } from "./index.js"; describe("ids", () => { it("canonicalizes symbol variants to one form", () => { for (const v of ["BRK.B", "BRK-B", "BRK/B", "BRK B", "brk.b"]) expect(canonicalSymbol(v)).toBe("brk_b"); }); it("builds stable ids per asset class", () => { expect(makeInstrumentId("EQUITY", { symbol: "AAPL", mic: "XNAS", country: "US" })).toBe("eq_us_xnas_aapl"); expect(makeInstrumentId("CRYPTO", { symbol: "BTC-USD", base: "BTC", quote: "USD" })).toBe("crypto_btc_usd"); expect(makeInstrumentId("FOREX", { symbol: "EURUSD", base: "EUR", quote: "USD" })).toBe("fx_eur_usd"); expect(makeInstrumentId("INDEX", { symbol: "_SPX", country: "US" })).toBe("index_us_spx"); expect(makeInstrumentId("TREASURY", { symbol: "US10Y", country: "US" })).toBe("rate_us_us10y"); expect(makeInstrumentId("ETF", { symbol: "SPY", mic: "ARCX", country: "US" })).toBe("etf_us_arcx_spy"); }); it("splits pairs", () => { expect(splitPair("BTC-USD")).toEqual({ base: "BTC", quote: "USD" }); expect(splitPair("EURUSD")).toEqual({ base: "EUR", quote: "USD" }); expect(splitPair("AAPL")).toBeNull(); }); }); describe("time", () => { it("converts Eastern wall clock to UTC across DST", () => { expect(new Date(zonedTimeToUtc("2026-09-11T15:59:59", "America/New_York")!).toISOString()).toBe("2026-09-11T19:59:59.000Z"); // EDT expect(new Date(zonedTimeToUtc("2026-01-15T16:00:00", "America/New_York")!).toISOString()).toBe("2026-01-15T21:00:00.000Z"); // EST expect(new Date(zonedTimeToUtc("2026-09-11", "UTC")!).toISOString()).toBe("2026-09-11T00:00:00.000Z"); }); it("computes offsets and parts", () => { expect(tzOffsetMs(Date.UTC(2026, 6, 1), "Asia/Tokyo")).toBe(9 * 3_600_000); const p = zonedParts(Date.UTC(2026, 8, 11, 19, 59, 59), "America/New_York"); expect(p.date).toBe("2026-09-11"); expect(p.time).toBe("15:59"); expect(p.weekday).toBe(5); }); it("parses timestamps in s, ms, µs, ns and ISO", () => { expect(parseTimestamp(1789199657)).toBe(1789199657000); expect(parseTimestamp(1789199657016)).toBe(1789199657016); expect(parseTimestamp("1789199660123")).toBe(1789199660123); expect(parseTimestamp(1789199657016000)).toBe(1789199657016); expect(parseTimestamp("2026-09-12T07:54:03.482921Z")).toBe(Date.parse("2026-09-12T07:54:03.482Z")); expect(parseTimestamp("garbage")).toBeNull(); }); });