Skip to content

Postgres adapter: TIMESTAMP/TIMESTAMPTZ passed as PostgreSQL format, not ISO 8601 #1152

@hubyrod

Description

@hubyrod

Bug: Date columns not normalized to ISO 8601

Version: @skip-adapter/postgres@0.0.19

Problem

TIMESTAMP and TIMESTAMPTZ columns from PostgreSQL are passed through to mappers/enrichers as raw PostgreSQL-formatted strings (e.g., 2024-01-15 10:30:00+00) instead of ISO 8601 strings (2024-01-15T10:30:00.000Z).

While new Date("2024-01-15 10:30:00+00") works in V8 (Node.js/Bun), it fails to parse on some JavaScript runtimes — notably React Native's Hermes engine, which only supports the ISO 8601 format per the ECMAScript spec.

Reproduction

Given a table:

CREATE TABLE photos (
  id TEXT PRIMARY KEY,
  caption TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

In a mapper:

class PhotoEnricher implements Mapper<string, DbPhoto, string, EnrichedPhoto> {
  mapEntry(key: string, values: Values<DbPhoto>): Iterable<[string, EnrichedPhoto]> {
    const photo = values.getUnique();

    console.log(photo.created_at);
    // Actual:   "2024-01-15 10:30:00+00"  (PostgreSQL format)
    // Expected: "2024-01-15T10:30:00.000Z" (ISO 8601)

    // On Hermes (React Native):
    const date = new Date(photo.created_at);
    console.log(date.toString()); // "Invalid Date"

    return [[key, { ...photo, createdAt: photo.created_at }]];
  }
}

Impact

  • Mobile clients (React Native / Hermes) crash or display "Invalid Date" when consuming timestamps from the reactive graph
  • Backend enrichers must manually normalize every date field in every mapper
  • Inconsistent date formats across the API surface

Current workaround

A helper function applied to every timestamp field in every enricher:

function toISODateString(value: string): string {
  const date = new Date(value);
  return isNaN(date.getTime()) ? value : date.toISOString();
}

// In every enricher:
createdAt: toISODateString(photo.created_at),
updatedAt: toISODateString(photo.updated_at),

Expected behavior

The postgres adapter should normalize TIMESTAMP and TIMESTAMPTZ columns to ISO 8601 format (YYYY-MM-DDTHH:mm:ss.sssZ) before passing them into the reactive graph.

The pg driver supports custom type parsers — this could be done by registering a parser for OIDs 1114 (TIMESTAMP) and 1184 (TIMESTAMPTZ) that returns ISO 8601 strings.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions