8000 fix!: write date and timestamp years outside 0000-9999 as ISO 8601 does by colinhacks · Pull Request #153 · colinhacks/reylo · GitHub
[go: up one dir, main page]

Skip to content

fix!: write date and timestamp years outside 0000-9999 as ISO 8601 does - #153

Merged
colinhacks merged 2 commits into
mainfrom
extended-iso-years
Nov 2, 2026
Merged

colinhacks merged 2 commits into
mainfrom
extended-iso-years

Conversation

@colinhacks
Copy link
Copy Markdown
Owner

A date or timestamp whose year is before 1 AD or past 9999 came back as Postgres's own text (0002-06-01 BC, 12345-01-01, 0002-06-01T12:00:00 BC), which Temporal.PlainDate.from and Temporal.PlainDateTime.from refuse. They now take the extended year a timestamptz already had: four digits for 0000–9999, else a sign and six digits, the year 0000 being 1 BC.

  • '0002-06-01 BC'::date → -000001-06-01
  • '12345-01-01'::date → +012345-01-01
  • '0002-06-01 12:00:00 BC'::timestamp → -000001-06-01T12:00:00
  • '10000-01-01 00:00:00'::timestamp → +010000-01-01T00:00:00
  • infinity and -infinity stay those words; a four-digit AD year is untouched (the fast path checks only where the first - falls and a trailing BC).

A date past 999999 AD (Postgres's date reaches 5874897) keeps the sign and takes the digits it needs, +5874897-12-31: ISO 8601 leaves the number of extended digits to agreement, Temporal holds no such date in any form, and a sign keeps every year outside 0000–9999 in one form. The parameter conversion now reads a sign followed by six or more digits, so every value .run() returns for these types goes back in.

The same text comes from every driver: the server's text (pg, pg-promise, postgres.js, PGlite, Neon, Slonik, Standard Query), arrays element by element, and Bun.sql's Dates, which previously wrote a five-digit year without a sign.

This changes the text of those values, hence !.

Tests: tests/values.test.ts (BC, five-, six- and seven-digit years for both types, Temporal reading each, the parameter round trip, infinity, date[] and timestamp[], Dates), tests/execute.test.ts (the parameters sent), tests/decode.test.ts (Bun.sql), tests/representation.test.ts (a BC date, a five-digit timestamp and a timestamp[] on every live driver). Docs: postgres.mdx's "Years past 9999 or before 1 AD".

A date or timestamp before 1 AD or past 9999 came back as the server's text (`0002-06-01 BC`, `12345-01-01`), which Temporal refuses; it now takes the extended year a timestamptz already had (`-000001-06-01`, `+012345-01-01`), and a parameter reads it back.
Copilot AI balanced review requested due to automatic review settings November 2, 2026 21:21
@vercel
vercel Bot commented Nov 2, 2026 •
Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reylo Ready Ready Preview Nov 2, 2026 9:33pm UTC

Request Review

Copilot AI left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the ISO 8601 date and timestamp formatting changes.

No open issues 🎉

What changed in this PR

This PR makes Reylo’s Postgres date and timestamp output use ISO 8601 year formatting, consistent with timestamptz. This is a breaking change for BC years and years past 9999; ordinary AD dates and infinity values remain unchanged.

Changes:

  • Normalizes extended years in server text, arrays, and driver-provided Dates.
  • Accepts signed years with six or more digits when converting parameters back to Postgres.
  • Adds decoding, parameter round-trip, and cross-driver regression coverage, and documents the new representation.
File Description
tests/​values.test.ts Tests extended years, Temporal compatibility, arrays, and round trips.
tests/​representation.test.ts Adds cross-driver cases for BC dates and extended-year timestamps.
tests/​execute.test.ts Checks conversion of BC timestamps and seven-digit date parameters.
tests/​decode.test.ts Updates Bun.sql Date decoding expectations and adds an extended-year case.
src/​values.ts Normalizes output years and expands parameter year parsing.
site/​content/​docs/​postgres.mdx Documents extended-year formatting and Temporal limitations.

Review effort: Balanced

@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ℹ️ No code issues found — one docs gap inline.

Reviewed changes

Reviewed the change that writes Postgres date and timestamp years outside 0000–9999 in ISO 8601's extended form, as timestamptz already did.

  • isoDate decoder — date and timestamp text (and their arrays, through textDecoder) now become -000001-06-01 / +012345-01-01; four-digit AD years and ±infinity take the fast path untouched.
  • Bun.sql Dates — utcText writes the year with isoYear and no longer appends BC, so Bun's values match the server text path.
  • Parameter round trip — postgresYear accepts [+-]\d{6,}, so a seven-digit date (+5874897-12-31) goes back in as 5874897-12-31.
  • Docs — postgres.mdx's "Years past 9999 or before 1 AD" now covers all three types.

I traced every Postgres decode path (pg, pg-promise, postgres.js .raw(), PGlite, Slonik, Standard Query) to textDecoder, and confirmed MySQL, SQLite and DuckDB don't use TEXT_DECODERS. The touched unit tests in values, decode and execute pass locally; the new values test needs a global Temporal, just like the existing timestamptz test.

Pullfrog  | Fix all ➔ | Fix 👍s ➔ | View workflow run | Using claude-opus-5-5 | 𝕏

Comment thread site/content/docs/postgres.mdx Resolved
@pullfrog pullfrog Bot left a comment
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found — the docs gap from the last review is closed.

Reviewed changes

Reviewed the one docs commit pushed since the last Pullfrog review.

  • Added JSON vs column note — the "Values inside a document" section of postgres.mdx now says a date or timestamp before 1 AD or past 9999 keeps Postgres's own year inside JSON. It includes the pair jsonb_build_object('d', '0002-06-01 BC'::date) → { d: "0002-06-01 BC" }. That matches how Postgres writes JSON dates: EncodeDateOnly with USE_XSD_DATES adds the BC suffix.

Pullfrog  | View workflow run | Using claude-opus-5-5 | 𝕏

@colinhacks
colinhacks merged commit 54fab26 into main Nov 2, 2026
10 checks passed
@colinhacks
colinhacks deleted the extended-iso-years branch November 2, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

0