ProvenPin Install

chrono-node natural language dates with a fixed reference and timezone: working versions (tested 2026-10-15)

Parse phrases like "tomorrow at 9am", weekday names, ranges and dates inside sentences with chrono-node against a fixed reference instant and UTC offset, plus en.GB day-first parsing.

passed7 passed · 0 failed2026-10-15 20:08 UTC
Status
passed
Last passed
2026-10-15 20:08 UTC
Tests
7 / 7
Language
TypeScript
Runtime
node v22.23.3
pinned versions3
chrono-node@2.10.3@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false
npm test
test environment
node v22.23.3
linux 6.17.0-1022-azure
x64
runner: github-actions 38799498972

The code

Exactly the files that passed. Your agent can pull them with get_recipe("chrono-node-reference-date") (install), or see them on GitHub.

package.json
{
  "name": "chrono-node-reference-date",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "node --import tsx --test test/*.test.ts"
  },
  "dependencies": {
    "chrono-node": "2.10.3"
  },
  "devDependencies": {
    "@types/node": "26.6.5",
    "tsx": "4.23.15"
  }
}
src/parse.ts
import * as chrono from "chrono-node";

/**
 * Parse natural-language dates against a fixed reference instant and timezone offset
 * (minutes from UTC), so results never depend on the machine clock or TZ.
 */
export function parseWhen(text: string, ref: Date, tzOffsetMinutes: number, forwardDate = true) {
  const results = chrono.parse(text, { instant: ref, timezone: tzOffsetMinutes }, { forwardDate });
  return results.map((r) => ({
    text: r.text,
    index: r.index,
    start: r.start.date().toISOString(),
    end: r.end?.date().toISOString() ?? null,
    certainHour: r.start.isCertain("hour"),
  }));
}

export const parseOne = (text: string, ref: Date, tz: number) => chrono.parseDate(text, { instant: ref, timezone: tz }, { forwardDate: true })?.toISOString() ?? null;

/** British-style day/month input via the en.GB locale parser. */
export const parseGB = (text: string, ref: Date) => chrono.en.GB.parseDate(text, { instant: ref, timezone: 0 })?.toISOString() ?? null;
test/parse.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { parseWhen, parseOne, parseGB } from "../src/parse.ts";

// Thursday 2026-10-15 12:00 in Alaska (UTC-8) = 20:00Z
const ref = new Date("2026-10-15T20:00:00Z");
const AK = -480;

test("relative day and time in a fixed offset", () => {
  assert.equal(parseOne("tomorrow at 9am", ref, AK), "2026-10-16T17:00:00.000Z");
  assert.equal(parseOne("in 3 days", ref, AK), "2026-10-18T20:00:00.000Z");
});

test("weekday name with forwardDate picks the next one", () => {
  assert.equal(parseOne("monday 8:30", ref, AK), "2026-10-19T16:30:00.000Z");
});

test("ranges give start and end", () => {
  const [r] = parseWhen("Oct 20 2pm - 4pm", ref, AK);
  assert.equal(r.start, "2026-10-20T22:00:00.000Z");
  assert.equal(r.end, "2026-10-21T00:00:00.000Z");
});

test("finds dates inside a sentence with position and certainty", () => {
  const rs = parseWhen("Class moved to Nov 1st, signup closes Friday", ref, AK);
  assert.equal(rs.length, 2);
  assert.equal(rs[0].text, "Nov 1st");
  assert.equal(rs[0].index, 15);
  assert.equal(rs[0].certainHour, false);
  assert.equal(rs[1].text, "Friday");
});

test("UTC offset changes the instant", () => {
  assert.equal(parseOne("2026-11-01 10:00", ref, 0), "2026-11-01T10:00:00.000Z");
  assert.equal(parseOne("2026-11-01 10:00", ref, AK), "2026-11-01T18:00:00.000Z");
});

test("en.GB reads day before month", () => {
  assert.equal(parseGB("03/04/2027 noon", ref), "2027-04-03T12:00:00.000Z");
});

test("no date returns empty", () => {
  assert.deepEqual(parseWhen("bring your hard hat", ref, AK), []);
  assert.equal(parseOne("nothing here", ref, AK), null);
});

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.