Temporal is the modern replacement for Date and is now shipping in runtimes (Node 26, etc.). Passing a Temporal value to escape() today falls through to the generic object handling and produces broken SQL:
escape(Temporal.Instant.from('2012-05-07T11:42:03.002Z'));
// currently => garbage / object expansion, not a valid literal
Date is already special-cased; Temporal deserves the same treatment.
Proposed API
Mirror the existing Date behavior, mapping each Temporal type to its natural MySQL literal:
| Temporal type |
Treated as |
Output |
Instant, ZonedDateTime |
absolute time |
dateToString, honoring the timezone arg exactly like Date (ms precision) |
PlainDateTime |
wall-clock |
DATETIME literal, timezone ignored |
PlainDate |
wall-clock |
DATE literal |
PlainTime |
wall-clock |
TIME literal |
others (Duration, PlainYearMonth, ...) |
— |
ISO-string fallback |
Detection via Object.prototype.toString (Symbol.toStringTag, i.e. [object Temporal.*]), so the Temporal global is never referenced and runtimes without Temporal are unaffected.
Open questions for maintainers
- Precision —
Instant via epochMilliseconds gives millisecond precision (identical to Date). Should sub-ms (µs/ns) be preserved for DATETIME(6), or is matching Date preferred?
SqlValue typing — upgrade to TS 6.0.3 to support the esnext.temporal lib? https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html#new-types-for-temporal
- Type coverage — include only the 5 date/time-mapped types in the
SqlValue union, or all Temporal types?
Reference
Opened #42 as a concrete starting point (structural-typing variant). Happy to adjust the API based on the discussion here.
Temporal is the modern replacement for
Dateand is now shipping in runtimes (Node 26, etc.). Passing a Temporal value toescape()today falls through to the generic object handling and produces broken SQL:Dateis already special-cased; Temporal deserves the same treatment.Proposed API
Mirror the existing
Datebehavior, mapping each Temporal type to its natural MySQL literal:Instant,ZonedDateTimedateToString, honoring thetimezonearg exactly likeDate(ms precision)PlainDateTimeDATETIMEliteral,timezoneignoredPlainDateDATEliteralPlainTimeTIMEliteralDuration,PlainYearMonth, ...)Detection via
Object.prototype.toString(Symbol.toStringTag, i.e.[object Temporal.*]), so theTemporalglobal is never referenced and runtimes without Temporal are unaffected.Open questions for maintainers
InstantviaepochMillisecondsgives millisecond precision (identical toDate). Should sub-ms (µs/ns) be preserved forDATETIME(6), or is matchingDatepreferred?SqlValuetyping — upgrade to TS 6.0.3 to support theesnext.temporallib? https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html#new-types-for-temporalSqlValueunion, or all Temporal types?Reference
Opened #42 as a concrete starting point (structural-typing variant). Happy to adjust the API based on the discussion here.