From e9e1ed49ed7164b0265ad684376277d04dc7f307 Mon Sep 17 00:00:00 2001 From: Rafal Witczak Date: Mon, 2 Jan 2023 14:04:05 +0100 Subject: [PATCH] Allow also "[+-]hh" as datetime offset --- README.md | 1 + deno/lib/README.md | 1 + deno/lib/__tests__/string.test.ts | 3 +++ deno/lib/types.ts | 6 +++--- src/__tests__/string.test.ts | 3 +++ src/types.ts | 6 +++--- 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d0a97ea105..76e4949875 100644 --- a/README.md +++ b/README.md @@ -631,6 +631,7 @@ const datetime = z.string().datetime({ offset: true }); datetime.parse("2020-01-01T00:00:00+02:00"); // pass datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional) datetime.parse("2020-01-01T00:00:00.123+0200"); // pass (millis optional) +datetime.parse("2020-01-01T00:00:00.123+02"); // pass (only offset hours) datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported) ``` diff --git a/deno/lib/README.md b/deno/lib/README.md index d0a97ea105..76e4949875 100644 --- a/deno/lib/README.md +++ b/deno/lib/README.md @@ -631,6 +631,7 @@ const datetime = z.string().datetime({ offset: true }); datetime.parse("2020-01-01T00:00:00+02:00"); // pass datetime.parse("2020-01-01T00:00:00.123+02:00"); // pass (millis optional) datetime.parse("2020-01-01T00:00:00.123+0200"); // pass (millis optional) +datetime.parse("2020-01-01T00:00:00.123+02"); // pass (only offset hours) datetime.parse("2020-01-01T00:00:00Z"); // pass (Z still supported) ``` diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index da4085a2dc..25162a2a6b 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -246,6 +246,7 @@ test("datetime parsing", () => { 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"); + datetimeOffset.parse("2020-10-14T17:42:29+03"); expect(() => datetimeOffset.parse("tuna")).toThrow(); expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow(); @@ -256,6 +257,7 @@ test("datetime parsing", () => { datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z"); datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00"); 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:00:00.000Z")).toThrow(); expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); @@ -268,6 +270,7 @@ test("datetime parsing", () => { datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z"); datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00"); datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000"); + datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00"); expect(() => datetimeOffset4Ms.parse("tuna")).toThrow(); expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow(); expect(() => diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 62818249d8..9059b72a49 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -533,7 +533,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { if (args.precision) { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp( @@ -543,7 +543,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { } else if (args.precision === 0) { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$`); @@ -551,7 +551,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { } else { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp( diff --git a/src/__tests__/string.test.ts b/src/__tests__/string.test.ts index b20be70a64..c39f550659 100644 --- a/src/__tests__/string.test.ts +++ b/src/__tests__/string.test.ts @@ -245,6 +245,7 @@ test("datetime parsing", () => { 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"); + datetimeOffset.parse("2020-10-14T17:42:29+03"); expect(() => datetimeOffset.parse("tuna")).toThrow(); expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow(); @@ -255,6 +256,7 @@ test("datetime parsing", () => { datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z"); datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00"); 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:00:00.000Z")).toThrow(); expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow(); @@ -267,6 +269,7 @@ test("datetime parsing", () => { datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z"); datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00"); datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000"); + datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00"); expect(() => datetimeOffset4Ms.parse("tuna")).toThrow(); expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow(); expect(() => diff --git a/src/types.ts b/src/types.ts index ae8eb3bc33..9809bd05ad 100644 --- a/src/types.ts +++ b/src/types.ts @@ -533,7 +533,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { if (args.precision) { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{${args.precision}}(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp( @@ -543,7 +543,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { } else if (args.precision === 0) { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp(`^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$`); @@ -551,7 +551,7 @@ const datetimeRegex = (args: { precision: number | null; offset: boolean }) => { } else { if (args.offset) { return new RegExp( - `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(([+-]\\d{2}:?\\d{2})|Z)$` + `^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(([+-]\\d{2}(:?\\d{2})?)|Z)$` ); } else { return new RegExp(