@@ -84,6 +84,37 @@ export function createQuerySchemaFactory(clientOrSchema: any, options?: any) {
8484 return new ZodSchemaFactory ( clientOrSchema , options ) ;
8585}
8686
87+ /**
88+ * Builds a `DateTime` value schema that accepts a `Date` object or any string
89+ * the JS `Date` constructor parses, and coerces it to a `Date`. ISO datetime,
90+ * ISO date, and time-only strings (e.g. `"09:00:00"` for `@db.Time` fields,
91+ * anchored to the Unix epoch) are the documented happy paths; other formats
92+ * accepted by `new Date(...)` also pass through, mirroring Prisma's pre-3.5
93+ * behaviour. Strings the engine can't parse fall through and are rejected by
94+ * `z.date()` with the standard error.
95+ *
96+ * @see https://github.com/zenstackhq/zenstack/issues/2631
97+ */
98+ export function coercedDateTimeSchema ( ) : ZodType {
99+ // The schema keeps the original `z.iso.datetime() | z.iso.date() | z.date()`
100+ // union so the generated OpenAPI spec still documents the accepted ISO
101+ // forms. Preprocess runs first and coerces strings into `Date` objects,
102+ // so the union's `z.date()` arm catches everything that successfully
103+ // parses — including non-ISO formats like `"2024/01/15"` for Prisma
104+ // compatibility (rejected with the standard error if `new Date(...)`
105+ // returns Invalid Date).
106+ return z . preprocess ( ( val ) => {
107+ if ( typeof val !== 'string' ) return val ;
108+ if ( / ^ \d { 2 } : \d { 2 } (?: : \d { 2 } (?: \. \d + ) ? ) ? (?: Z | [ + - ] \d \d (?: : \d \d ) ? ) ? $ / . test ( val ) ) {
109+ const hasTz = val . endsWith ( 'Z' ) || / [ + - ] \d \d (?: : \d \d ) ? $ / . test ( val ) ;
110+ const d = new Date ( `1970-01-01T${ val } ${ hasTz ? '' : 'Z' } ` ) ;
111+ return isNaN ( d . getTime ( ) ) ? val : d ;
112+ }
113+ const d = new Date ( val ) ;
114+ return isNaN ( d . getTime ( ) ) ? val : d ;
115+ } , z . union ( [ z . iso . datetime ( ) , z . iso . date ( ) , z . date ( ) ] ) ) ;
116+ }
117+
87118/**
88119 * Options for creating Zod schemas.
89120 */
@@ -864,7 +895,7 @@ export class ZodSchemaFactory<
864895
865896 @cache ( )
866897 private makeDateTimeValueSchema ( ) : ZodType {
867- const schema = z . union ( [ z . iso . datetime ( ) , z . iso . date ( ) , z . date ( ) ] ) ;
898+ const schema = coercedDateTimeSchema ( ) ;
868899 this . registerSchema ( 'DateTime' , schema ) ;
869900 return schema ;
870901 }
0 commit comments