Repository navigation
driver-sql on MySQL reads a year 0..99 back a century late — REST create stores placed_on: "0009-03-04" correctly, and …/query returns "1909-03-04"; a datetime 0009-03-04T10:00Z returns 2004-09-03T10:00Z #20280
Description
Filing gate: ① a defect with a named landing site: packages/drivers/driver-sql/src/sql-driver.ts, the mysql2 connection options (withUtcSession sets timezone: 'Z', and a URL connection reaches it too through withConnectBound) and the MySQL read presentation. They feed mysql2 3.23.1's lib/packets/packet.js parseDate / parseDateTime.
Finding class (a). reach: was measured at the public REST door (below).
The domain:engine execution seat 1 (session_01Bvd69VPa6puiNzzPUroDBx) filed this from its #20240 dev's patch-round report (finding 5), re-measured by the delta review of PR #20261 (record 5858382903). ⛔ Filed bare: routing and grading are triage's. ⛔ Not a claim.
What happens
Measured at e46218674b (base) and at PR #20261's head, which are identical for every cell below. The stack is SqlDriver on a live MySQL 8.0.46 (server time_zone='+08:00', as CI runs it) through mysql2 3.23.1, via REST POST /api/v1/data/:object and POST /api/v1/data/:object/query.
| field | written | stored (CAST(… AS CHAR)) |
returned by …/query |
|---|---|---|---|
date |
"0009-03-04" |
0009-03-04 |
"1909-03-04" |
date |
"0099-03-04" |
0099-03-04 |
"1999-03-04" |
date |
"0000-06-15" |
0000-06-15 |
"1900-06-15" |
date |
"0999-06-15" |
0999-06-15 |
"999-06-15" at base; "0999-06-15" once PR #20261 lands |
datetime |
"0009-03-04T10:00:00.000Z" |
0009-03-04 10:00:00.000 |
"2004-09-03T10:00:00.000Z" |
datetime |
0099-… / 0000-… |
stored right | 1999-03-04T10:00Z / 2000-06-15T10:00Z |
- The write is right and the read is wrong.
where placed_on $eq "0009-03-04"finds the row, then presents it as1909-03-04.$eq "1909-03-04"finds nothing. - Mechanism (read from source, measured live):
parseDateundertimezone: 'Z'rebuilds a DATE asnew Date(Date.UTC(y, m-1, d)), and the default /'local'zones usenew Date(y, m-1, d). Both map a year 0..99 to 1900..1999.parseDateTimehands'0009-03-04 10:00:00.000Z'to V8's non-ISODateparser, which reads it as 2004-09-03.- SQLite and PostgreSQL read these years right.
- No measured writer stores these years. The reach is the public door, not an observed caller.
Suggested shape (⛔ not a ruling)
- The review measured two remedy hints.
dateStrings: true(forDATEandDATETIME) hands back the exact stored text. A'+00:00'zone takes mysql2's padded string-constructor arm forDATEonly. - Whichever is chosen, the read presentation must then go through the one storage rule (
temporalStorageForm), as the other dialects do. - Pin it on live MySQL for years 9, 99, 0, 999 and a 2026 control, on
dateanddatetime, through the engine and REST.
Filing-gate answers
- Class: ① (a defect with a named landing site); finding class (a), measured.
- Acting reader: this lane's seat (
domain:engine, the owner ofdriver-sql). It is a different mechanism and position from temporal values outside the years a four-digit text or a backend holds: adatetimecomparand for year 10000 or −1 misorders on memory/SQLite and 500s on PostgreSQL; adatein year 0000 500s on PostgreSQL; adatewrite stores+010000-…verbatim #20264 (years outside what a text or backend holds) and coretemporalStorageForm: thedatearm leaves a year outside 1000..9999 unpadded — over REST the epoch-ms number for 0999-06-15 counts$gt0 /$lt7 on InMemoryDriver and SQLite (correct 6 / 0); its ISO string counts 6 / 0 #20240 (the rule's padding), so it is not folded into either. - Dedupe, MCP semantic issue search in this repo,
closedincluded:mysql date year below 100 read back 1900s mysql2 parseDate→ temporal values outside the years a four-digit text or a backend holds: adatetimecomparand for year 10000 or −1 misorders on memory/SQLite and 500s on PostgreSQL; adatein year 0000 500s on PostgreSQL; adatewrite stores+010000-…verbatim #20264, MySQL: Field.datetime maps to TIMESTAMP (range ends 2038-01-19) and binds a Date in the process-local timezone #3942 and Field.date defaultValue NOW() records the server-timezone calendar day on Postgres — and the DDL is invalid on MySQL 8.0 #4022, none this;mysql2 timezone Z date read wrong century Date.UTC two digit year→ MySQL: Field.datetime maps to TIMESTAMP (range ends 2038-01-19) and binds a Date in the process-local timezone #3942, driver-sql: every Field.date read from PostgreSQL is one day early when the process TZ is east of UTC — toDateOnly() reads UTC components off a local-midnight Date #11389 (PostgreSQL day-early, fixed) and Field.date defaultValue NOW() records the server-timezone calendar day on Postgres — and the DDL is invalid on MySQL 8.0 #4022, none this.
Dedupe words: mysql date year below 100 read back 1900s · mysql2 parseDate Date.UTC year 0009 1909 · mysql datetime year 9 presented 2004
Activity