Skip to content

Commit 6330c3b

Browse files
authored
fix(orm): more robust timezone adjustment for postgres (#461)
* fix(orm): more robust timezone adjustment for postgres * update
1 parent 0492085 commit 6330c3b

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

packages/orm/src/client/crud/dialects/postgresql.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
type SelectQueryBuilder,
1010
} from 'kysely';
1111
import { match } from 'ts-pattern';
12+
import z from 'zod';
1213
import type { BuiltinType, FieldDef, GetModels, SchemaDef } from '../../../schema';
1314
import { DELEGATE_JOINED_FIELD_PREFIX } from '../../constants';
1415
import type { FindArgs } from '../../crud-types';
@@ -26,6 +27,8 @@ import {
2627
import { BaseCrudDialect } from './base-dialect';
2728

2829
export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDialect<Schema> {
30+
private isoDateSchema = z.iso.datetime({ local: true, offset: true });
31+
2932
constructor(schema: Schema, options: ClientOptions<Schema>) {
3033
super(schema, options);
3134
}
@@ -106,10 +109,16 @@ export class PostgresCrudDialect<Schema extends SchemaDef> extends BaseCrudDiale
106109

107110
private transformOutputDate(value: unknown) {
108111
if (typeof value === 'string') {
109-
// PostgreSQL's jsonb_build_object serializes timestamptz as ISO 8601 strings
110-
// in UTC but without the 'Z' suffix (e.g., "2023-01-01T12:00:00.123456").
111-
// We add 'Z' to explicitly mark them as UTC for correct Date object creation.
112-
return new Date(value.endsWith('Z') ? value : `${value}Z`);
112+
// PostgreSQL's jsonb_build_object serializes timestamp as ISO 8601 strings
113+
// without timezone, (e.g., "2023-01-01T12:00:00.123456"). Since Date is always
114+
// stored as UTC `timestamp` type, we add 'Z' to explicitly mark them as UTC for
115+
// correct Date object creation.
116+
if (this.isoDateSchema.safeParse(value).success) {
117+
const hasOffset = value.endsWith('Z') || /[+-]\d{2}:\d{2}$/.test(value);
118+
return new Date(hasOffset ? value : `${value}Z`);
119+
} else {
120+
return value;
121+
}
113122
} else if (value instanceof Date && this.options.fixPostgresTimezone !== false) {
114123
// SPECIAL NOTES:
115124
// node-pg has a terrible quirk that it returns the date value in local timezone

0 commit comments

Comments
 (0)