STET

agent_patch

runs/2026-02-27__21-30-28__gpt-5-4/flux-pr-4680/flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/agent-logs/agent.patch

23360 bytes

Back to adjudication
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/docs/content/api.mdx b/app/packages/docs/content/api.mdx
index 47e792c..43ad374 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/docs/content/api.mdx
+++ b/app/packages/docs/content/api.mdx
@@ -350,14 +350,16 @@ schema.parse("http://example.com"); // ❌
 
 As you may have noticed, Zod string includes a few date/time related validations. These validations are regular expression based, so they are not as strict as a full date/time library. However, they are very convenient for validating user input.
 
-The `z.iso.datetime()` method enforces ISO 8601; by default, no timezone offsets are allowed:
+The `z.iso.datetime()` method validates ISO 8601 datetimes. By default it accepts a trailing `Z`, allows minute-only values like `HH:MMZ`, and makes seconds and fractional seconds optional:
 
 ```ts
 const datetime = z.iso.datetime();
 
+datetime.parse("2020-01-01T00:00Z"); // ✅
 datetime.parse("2020-01-01T00:00:00Z"); // ✅
 datetime.parse("2020-01-01T00:00:00.123Z"); // ✅
 datetime.parse("2020-01-01T00:00:00.123456Z"); // ✅ (arbitrary precision)
+datetime.parse("2020-01-01T00:00"); // ❌ (local time disabled)
 datetime.parse("2020-01-01T00:00:00+02:00"); // ❌ (no offsets allowed)
 ```
 
@@ -366,30 +368,38 @@ To allow timezone offsets:
 ```ts
 const datetime = z.iso.datetime({ offset: true });
 
-// result is normalized to RFC 3339 format
-datetime.parse("2020-01-01T00:00:00+02");    // ✅ "2020-01-01T00:00:00+02:00"
-datetime.parse("2020-01-01T00:00:00+0200");  // ✅ "2020-01-01T00:00:00+02:00"
-datetime.parse("2020-01-01T00:00:00+02:00"); // ✅ "2020-01-01T00:00:00+02:00"
+datetime.parse("2020-01-01T00:00+02:00"); // ✅
+datetime.parse("2020-01-01T00:00:00+02"); // ✅
+datetime.parse("2020-01-01T00:00:00+0200"); // ✅
+datetime.parse("2020-01-01T00:00:00+02:00"); // ✅
 
 // Z is still supported
-datetime.parse("2020-01-01T00:00:00Z"); // ✅ 
+datetime.parse("2020-01-01T00:00:00Z"); // ✅
 ```
 
 To allow unqualified (timezone-less) datetimes:
 
 ```ts
 const schema = z.iso.datetime({ local: true });
+schema.parse("2020-01-01T00:00"); // ✅
 schema.parse("2020-01-01T00:00:00"); // ✅
 ```
 
-To constrain the allowable `precision` (by default, arbitrary sub-second precision is supported).
+To constrain `precision`, use one of the named levels from `z.TimePrecision` or pass the number directly:
 
 ```ts
-const datetime = z.iso.datetime({ precision: 3 });
+const a = z.iso.datetime({ precision: z.TimePrecision.Minute });
+const b = z.iso.datetime({ precision: -1 });
+const c = z.iso.datetime({ precision: z.TimePrecision.Second });
+const d = z.iso.datetime({ precision: z.TimePrecision.Millisecond });
 
-datetime.parse("2020-01-01T00:00:00.123Z"); // ✅
-datetime.parse("2020-01-01T00:00:00Z"); // ❌
-datetime.parse("2020-01-01T00:00:00.123456Z"); // ❌
+a.parse("2020-01-01T00:00Z"); // ✅
+b.parse("2020-01-01T00:00Z"); // ✅
+c.parse("2020-01-01T00:00:00Z"); // ✅
+d.parse("2020-01-01T00:00:00.123Z"); // ✅
+
+d.parse("2020-01-01T00:00:00Z"); // ❌
+d.parse("2020-01-01T00:00:00.123456Z"); // ❌
 ```
 
 ### ISO dates
@@ -408,11 +418,12 @@ date.parse("2020-01-32"); // ❌
 
 > Added in Zod 3.23
 
-The `z.iso.time()` method validates strings in the format `HH:MM:SS[.s+]`. The second can include arbitrary decimal precision. It does not allow timezone offsets of any kind.
+The `z.iso.time()` method validates strings in the format `HH:MM` or `HH:MM:SS[.s+]`. It does not allow timezone offsets of any kind.
 
 ```ts
 const time = z.iso.time();
 
+time.parse("00:00"); // ✅
 time.parse("00:00:00"); // ✅
 time.parse("09:52:31"); // ✅
 time.parse("23:59:59.9999999"); // ✅ (arbitrary precision)
@@ -421,14 +432,18 @@ time.parse("00:00:00.123Z"); // ❌ (no `Z` allowed)
 time.parse("00:00:00.123+02:00"); // ❌ (no offsets allowed)
 ```
 
-You can set the `precision` option to constrain the allowable decimal precision.
+You can set `precision` to require a specific level.
 
 ```ts
-const time = z.iso.time({ precision: 3 });
+z.iso.time({ precision: -1 }); // HH:MM (minute precision)
+z.iso.time({ precision: 0 }); // HH:MM:SS (second precision)
+z.iso.time({ precision: 3 }); // HH:MM:SS.sss (millisecond precision)
 
-time.parse("00:00:00.123"); // ✅
-time.parse("00:00:00.123456"); // ❌
+const time = z.iso.time({ precision: z.TimePrecision.Microsecond });
+
+time.parse("00:00:00.123456"); // ✅
 time.parse("00:00:00"); // ❌
+time.parse("00:00:00.123"); // ❌
 ```
 
 ### IP addresses
@@ -2542,4 +2557,3 @@ const MyFunction = z.function({
 
 const computeTrimmedLength = MyFunction.implement((input) => input.trim.length);
 ```
-
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/external.ts b/app/packages/zod/src/v4/classic/external.ts
index eccc470..9a0f47e 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/external.ts
+++ b/app/packages/zod/src/v4/classic/external.ts
@@ -22,6 +22,7 @@ export {
   $brand,
   clone,
   regexes,
+  TimePrecision,
   treeifyError,
   prettifyError,
   formatError,
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/index.test.ts b/app/packages/zod/src/v4/classic/tests/index.test.ts
index 2f24eb6..a5b502e 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/index.test.ts
+++ b/app/packages/zod/src/v4/classic/tests/index.test.ts
@@ -82,10 +82,10 @@ test("z.coerce.date", () => {
 });
 
 test("z.iso.datetime", () => {
-  const d1 = "2021-01-01T00:00:00Z";
+  const d1 = "2021-01-01T00:00Z";
   const d2 = "2021-01-01T00:00:00.123Z";
   const d3 = "2021-01-01T00:00:00";
-  const d4 = "2021-01-01T00:00:00+07:00";
+  const d4 = "2021-01-01T00:00+07:00";
   const d5 = "bad data";
 
   // local: false, offset: false, precision: null
@@ -116,6 +116,13 @@ test("z.iso.datetime", () => {
   expect(z.safeParse(d, d3).success).toEqual(false);
   expect(z.safeParse(d, d4).success).toEqual(false);
   expect(z.safeParse(d, d5).success).toEqual(false);
+
+  const e = z.iso.datetime({ precision: z.TimePrecision.Minute });
+  expect(z.safeParse(e, d1).success).toEqual(true);
+  expect(z.safeParse(e, d2).success).toEqual(false);
+  expect(z.safeParse(e, d3).success).toEqual(false);
+  expect(z.safeParse(e, d4).success).toEqual(false);
+  expect(z.safeParse(e, d5).success).toEqual(false);
 });
 
 test("z.iso.date", () => {
@@ -132,7 +139,7 @@ test("z.iso.date", () => {
 });
 
 test("z.iso.time", () => {
-  const d1 = "00:00:00";
+  const d1 = "00:00";
   const d2 = "00:00:00.123";
   const d3 = "bad data";
 
@@ -150,6 +157,11 @@ test("z.iso.time", () => {
   expect(z.safeParse(c, d1).success).toEqual(true);
   expect(z.safeParse(c, d2).success).toEqual(true);
   expect(z.safeParse(c, d3).success).toEqual(false);
+
+  const d = z.iso.time({ precision: z.TimePrecision.Minute });
+  expect(z.safeParse(d, d1).success).toEqual(true);
+  expect(z.safeParse(d, d2).success).toEqual(false);
+  expect(z.safeParse(d, d3).success).toEqual(false);
 });
 
 test("z.iso.duration", () => {
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/string.test.ts b/app/packages/zod/src/v4/classic/tests/string.test.ts
index 0de8bee..9fe275d 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/string.test.ts
+++ b/app/packages/zod/src/v4/classic/tests/string.test.ts
@@ -755,6 +755,7 @@ test("lowerCase", () => {
 
 test("datetime parsing", () => {
   const datetime = z.string().datetime();
+  datetime.parse("1970-01-01T00:00Z");
   datetime.parse("1970-01-01T00:00:00.000Z");
   datetime.parse("2022-10-13T09:52:31.816Z");
   datetime.parse("2022-10-13T09:52:31.8162314Z");
@@ -764,12 +765,21 @@ test("datetime parsing", () => {
   expect(() => datetime.parse("foo")).toThrow();
   expect(() => datetime.parse("2020-10-14")).toThrow();
   expect(() => datetime.parse("T18:45:12.123")).toThrow();
+  expect(() => datetime.parse("2020-10-14T17:42")).toThrow();
   expect(() => datetime.parse("2020-10-14T17:42:29+00:00")).toThrow();
 
+  const datetimeMinute = z.string().datetime({ precision: -1 });
+  datetimeMinute.parse("1970-01-01T00:00Z");
+  datetimeMinute.parse("2022-10-13T09:52Z");
+  expect(() => datetimeMinute.parse("tuna")).toThrow();
+  expect(() => datetimeMinute.parse("1970-01-01T00:00:00Z")).toThrow();
+  expect(() => datetimeMinute.parse("2022-10-13T09:52:31.816Z")).toThrow();
+
   const datetimeNoMs = z.string().datetime({ precision: 0 });
   datetimeNoMs.parse("1970-01-01T00:00:00Z");
   datetimeNoMs.parse("2022-10-13T09:52:31Z");
   expect(() => datetimeNoMs.parse("tuna")).toThrow();
+  expect(() => datetimeNoMs.parse("1970-01-01T00:00Z")).toThrow();
   expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
   expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
   expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
@@ -783,10 +793,12 @@ test("datetime parsing", () => {
   expect(() => datetime3Ms.parse("2022-10-13T09:52:31Z")).toThrow();
 
   const datetimeOffset = z.string().datetime({ offset: true });
+  datetimeOffset.parse("2020-10-14T17:42Z");
   datetimeOffset.parse("1970-01-01T00:00:00.000Z");
   datetimeOffset.parse("2022-10-13T09:52:31.816234134Z");
   datetimeOffset.parse("1970-01-01T00:00:00Z");
   datetimeOffset.parse("2022-10-13T09:52:31.4Z");
+  datetimeOffset.parse("2020-10-14T17:42+00:00");
   datetimeOffset.parse("2020-10-14T17:42:29+00:00");
   datetimeOffset.parse("2020-10-14T17:42:29+03:15");
   datetimeOffset.parse("2020-10-14T17:42:29+0315");
@@ -801,11 +813,21 @@ test("datetime parsing", () => {
   datetimeOffsetNoMs.parse("2020-10-14T17:42:29+0000");
   datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00");
   expect(() => datetimeOffsetNoMs.parse("tuna")).toThrow();
+  expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00Z")).toThrow();
   expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
   expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
   expect(() => datetimeOffsetNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
   expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
 
+  const datetimeOffsetMinute = z.string().datetime({ offset: true, precision: -1 });
+  datetimeOffsetMinute.parse("1970-01-01T00:00Z");
+  datetimeOffsetMinute.parse("2020-10-14T17:42+00:00");
+  datetimeOffsetMinute.parse("2020-10-14T17:42+0000");
+  datetimeOffsetMinute.parse("2020-10-14T17:42+00");
+  expect(() => datetimeOffsetMinute.parse("tuna")).toThrow();
+  expect(() => datetimeOffsetMinute.parse("1970-01-01T00:00:00Z")).toThrow();
+  expect(() => datetimeOffsetMinute.parse("2020-10-14T17:42:29+00:00")).toThrow();
+
   const datetimeOffset4Ms = z.string().datetime({ offset: true, precision: 4 });
   datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z");
   datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00");
@@ -816,7 +838,7 @@ test("datetime parsing", () => {
   expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
 });
 
-test("datetime offset normalization", () => {
+test("datetime offset preservation", () => {
   const a = z.iso.datetime({ offset: true });
   expect({
     a: a.parse("2020-10-14T17:42:29+02"),
@@ -824,8 +846,8 @@ test("datetime offset normalization", () => {
     c: a.parse("2020-10-14T17:42:29+02:00"),
   }).toMatchInlineSnapshot(`
     {
-      "a": "2020-10-14T17:42:29+02:00",
-      "b": "2020-10-14T17:42:29+02:00",
+      "a": "2020-10-14T17:42:29+02",
+      "b": "2020-10-14T17:42:29+0200",
       "c": "2020-10-14T17:42:29+02:00",
     }
   `);
@@ -887,6 +909,7 @@ test("date parsing", () => {
 
 test("time parsing", () => {
   const time = z.string().time();
+  time.parse("00:00");
   time.parse("00:00:00");
   time.parse("23:00:00");
   time.parse("00:59:00");
@@ -898,6 +921,7 @@ test("time parsing", () => {
   expect(() => time.parse("foo")).toThrow();
   expect(() => time.parse("00:00:00Z")).toThrow();
   expect(() => time.parse("0:00:00")).toThrow();
+  expect(() => time.parse("0:00")).toThrow();
   expect(() => time.parse("00:0:00")).toThrow();
   expect(() => time.parse("00:00:0")).toThrow();
   expect(() => time.parse("00:00:00.000+00:00")).toThrow();
@@ -907,6 +931,15 @@ test("time parsing", () => {
   expect(() => time.parse("00:00:60")).toThrow();
   expect(() => time.parse("24:60:60")).toThrow();
 
+  const timeMinute = z.string().time({ precision: -1 });
+  timeMinute.parse("00:00");
+  timeMinute.parse("09:52");
+  timeMinute.parse("23:59");
+  expect(() => timeMinute.parse("")).toThrow();
+  expect(() => timeMinute.parse("foo")).toThrow();
+  expect(() => timeMinute.parse("00:00:00")).toThrow();
+  expect(() => timeMinute.parse("00:00Z")).toThrow();
+
   const time2 = z.string().time({ precision: 2 });
   time2.parse("00:00:00.00");
   time2.parse("09:52:31.12");
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/template-literal.test.ts b/app/packages/zod/src/v4/classic/tests/template-literal.test.ts
index e46dccd..be61ecd 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/template-literal.test.ts
+++ b/app/packages/zod/src/v4/classic/tests/template-literal.test.ts
@@ -551,7 +551,7 @@ test("regexes", () => {
   expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][^\\s-]{8,}ZZZ$"`);
   expect(cuid2._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9a-z]+$"`);
   expect(datetime._zod.pattern.source).toMatchInlineSnapshot(
-    `"^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$"`
+    `"^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?(Z)$"`
   );
   expect(email._zod.pattern.source).toMatchInlineSnapshot(
     `"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"`
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/to-json-schema.test.ts b/app/packages/zod/src/v4/classic/tests/to-json-schema.test.ts
index 7c32b03..9ab1bd4 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/classic/tests/to-json-schema.test.ts
+++ b/app/packages/zod/src/v4/classic/tests/to-json-schema.test.ts
@@ -62,7 +62,7 @@ describe("toJSONSchema", () => {
       {
         "$schema": "https://json-schema.org/draft/2020-12/schema",
         "format": "date-time",
-        "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$",
+        "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?(Z)$",
         "type": "string",
       }
     `);
@@ -78,7 +78,7 @@ describe("toJSONSchema", () => {
       {
         "$schema": "https://json-schema.org/draft/2020-12/schema",
         "format": "time",
-        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?$",
+        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?$",
         "type": "string",
       }
     `);
@@ -277,7 +277,7 @@ describe("toJSONSchema", () => {
       {
         "$schema": "https://json-schema.org/draft/2020-12/schema",
         "format": "date-time",
-        "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?(Z)$",
+        "pattern": "^((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))T([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?(Z)$",
         "type": "string",
       }
     `);
@@ -294,7 +294,7 @@ describe("toJSONSchema", () => {
       {
         "$schema": "https://json-schema.org/draft/2020-12/schema",
         "format": "time",
-        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(\\.\\d+)?$",
+        "pattern": "^([01]\\d|2[0-3]):[0-5]\\d(:[0-5]\\d(\\.\\d+)?)?$",
         "type": "string",
       }
     `);
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/api.ts b/app/packages/zod/src/v4/core/api.ts
index ab6efb7..03f9841 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/api.ts
+++ b/app/packages/zod/src/v4/core/api.ts
@@ -451,6 +451,14 @@ export function _jwt<T extends schemas.$ZodJWT>(
 }
 
 // ISODateTime
+export const TimePrecision = {
+  Any: null,
+  Minute: -1,
+  Second: 0,
+  Millisecond: 3,
+  Microsecond: 6,
+} as const;
+
 export type $ZodISODateTimeParams = StringFormatParams<schemas.$ZodISODateTime, "pattern">;
 export type $ZodCheckISODateTimeParams = CheckStringFormatParams<schemas.$ZodISODateTime, "pattern">;
 export function _isoDateTime<T extends schemas.$ZodISODateTime>(
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/regexes.ts b/app/packages/zod/src/v4/core/regexes.ts
index 9cc1d48..54543b0 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/regexes.ts
+++ b/app/packages/zod/src/v4/core/regexes.ts
@@ -81,15 +81,18 @@ const dateSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][04
 export const date: RegExp = /*@__PURE__*/ new RegExp(`^${dateSource}$`);
 
 function timeSource(args: { precision?: number | null }) {
-  // let regex = `\\d{2}:\\d{2}:\\d{2}`;
-  let regex = `([01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d`;
+  const prefix = `([01]\\d|2[0-3]):[0-5]\\d`;
+  if (args.precision === -1) return prefix;
 
-  if (args.precision) {
-    regex = `${regex}\\.\\d{${args.precision}}`;
+  let seconds = `[0-5]\\d`;
+  if (args.precision && args.precision > 0) {
+    seconds = `${seconds}\\.\\d{${args.precision}}`;
   } else if (args.precision == null) {
-    regex = `${regex}(\\.\\d+)?`;
+    seconds = `${seconds}(\\.\\d+)?`;
   }
-  return regex;
+
+  const secondsQuantifier = args.precision == null ? "?" : "";
+  return `${prefix}(:${seconds})${secondsQuantifier}`;
 }
 export function time(args: {
   precision?: number | null;
@@ -106,9 +109,8 @@ export function datetime(args: {
   let regex = `${dateSource}T${timeSource(args)}`;
 
   const opts: string[] = [];
-  opts.push(args.local ? `Z?` : `Z`);
-  // if (args.offset) opts.push(`([+-]\\d{2}:?\\d{2})`);
-  // minutes, colon optional
+  if (args.local) opts.push(`Z?`);
+  else opts.push(`Z`);
   if (args.offset) opts.push(`([+-]\\d{2}(?::?\\d{2})?)`);
   regex = `${regex}(${opts.join("|")})`;
   return new RegExp(`^${regex}$`);
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/schemas.ts b/app/packages/zod/src/v4/core/schemas.ts
index e2ace79..0ee0032 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/core/schemas.ts
+++ b/app/packages/zod/src/v4/core/schemas.ts
@@ -604,20 +604,6 @@ export const $ZodISODateTime: core.$constructor<$ZodISODateTime> = /*@__PURE__*/
   (inst, def): void => {
     def.pattern ??= regexes.datetime(def);
     $ZodStringFormat.init(inst, def);
-
-    const _super = inst._zod.check;
-    inst._zod.check = (payload) => {
-      _super(payload);
-
-      // normalize timezone offset
-      // add colon & minutes if missing
-      // if no offset, return early
-      const curr = payload.value;
-      if (/[+-]\d\d$/.test(curr)) payload.value = curr + ":00";
-      else if (/[+-]\d\d\d\d$/.test(curr)) {
-        payload.value = curr.slice(0, -2) + ":" + curr.slice(-2);
-      }
-    };
   }
 );
 
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/mini/external.ts b/app/packages/zod/src/v4/mini/external.ts
index 4b23cf4..8bd1760 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/mini/external.ts
+++ b/app/packages/zod/src/v4/mini/external.ts
@@ -14,6 +14,7 @@ export {
   function,
   clone,
   regexes,
+  TimePrecision,
   treeifyError,
   prettifyError,
   formatError,
diff --git a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/mini/tests/index.test.ts b/app/packages/zod/src/v4/mini/tests/index.test.ts
index 7563865..77c08cc 100644
--- a/tmp/agent-patch-flux-pr-4680.1-of-1.2026-02-27__21-30-28__gpt-5-4/app/packages/zod/src/v4/mini/tests/index.test.ts
+++ b/app/packages/zod/src/v4/mini/tests/index.test.ts
@@ -82,10 +82,10 @@ test("z.coerce.date", () => {
 });
 
 test("z.iso.datetime", () => {
-  const d1 = "2021-01-01T00:00:00Z";
+  const d1 = "2021-01-01T00:00Z";
   const d2 = "2021-01-01T00:00:00.123Z";
   const d3 = "2021-01-01T00:00:00";
-  const d4 = "2021-01-01T00:00:00+07:00";
+  const d4 = "2021-01-01T00:00+07:00";
   const d5 = "bad data";
 
   // local: false, offset: false, precision: null
@@ -116,6 +116,13 @@ test("z.iso.datetime", () => {
   expect(z.safeParse(d, d3).success).toEqual(false);
   expect(z.safeParse(d, d4).success).toEqual(false);
   expect(z.safeParse(d, d5).success).toEqual(false);
+
+  const e = z.iso.datetime({ precision: z.TimePrecision.Minute });
+  expect(z.safeParse(e, d1).success).toEqual(true);
+  expect(z.safeParse(e, d2).success).toEqual(false);
+  expect(z.safeParse(e, d3).success).toEqual(false);
+  expect(z.safeParse(e, d4).success).toEqual(false);
+  expect(z.safeParse(e, d5).success).toEqual(false);
 });
 
 test("z.iso.date", () => {
@@ -132,7 +139,7 @@ test("z.iso.date", () => {
 });
 
 test("z.iso.time", () => {
-  const d1 = "00:00:00";
+  const d1 = "00:00";
   const d2 = "00:00:00.123";
   const d3 = "bad data";
 
@@ -150,6 +157,11 @@ test("z.iso.time", () => {
   expect(z.safeParse(c, d1).success).toEqual(true);
   expect(z.safeParse(c, d2).success).toEqual(true);
   expect(z.safeParse(c, d3).success).toEqual(false);
+
+  const d = z.iso.time({ precision: z.TimePrecision.Minute });
+  expect(z.safeParse(d, d1).success).toEqual(true);
+  expect(z.safeParse(d, d2).success).toEqual(false);
+  expect(z.safeParse(d, d3).success).toEqual(false);
 });
 
 test("z.iso.duration", () => {