diff --git a/deno/lib/README.md b/deno/lib/README.md index 125a56bc1..97cf7a725 100644 --- a/deno/lib/README.md +++ b/deno/lib/README.md @@ -855,19 +855,14 @@ z.string().regex(regex); z.string().includes(string); z.string().startsWith(string); z.string().endsWith(string); -<<<<<<< HEAD z.string().datetime(); // ISO 8601; by default only `Z` timezone allowed z.string().date(); // ISO date format (YYYY-MM-DD) z.string().time(); // ISO time format (HH:mm:ss[.SSSSSS]) +z.string().duration(); // ISO 8601 duration z.string().ip(); // defaults to allow both IPv4 and IPv6 z.string().base64(); -======= -z.string().datetime(); // ISO 8601; default is without UTC offset, see below for options -z.string().duration(); // ISO 8601 Duration -z.string().ip(); // defaults to IPv4 and IPv6, see below for options ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) -// transformations +// transforms z.string().trim(); // trim whitespace z.string().toLowerCase(); // toLowerCase z.string().toUpperCase(); // toUpperCase diff --git a/deno/lib/ZodError.ts b/deno/lib/ZodError.ts index f587e0e99..e757cd8ba 100644 --- a/deno/lib/ZodError.ts +++ b/deno/lib/ZodError.ts @@ -99,12 +99,9 @@ export type StringValidation = | "cuid2" | "ulid" | "datetime" -<<<<<<< HEAD | "date" | "time" -======= | "duration" ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) | "ip" | "base64" | { includes: string; position?: number } diff --git a/deno/lib/__tests__/string.test.ts b/deno/lib/__tests__/string.test.ts index fee7da743..3f5b95562 100644 --- a/deno/lib/__tests__/string.test.ts +++ b/deno/lib/__tests__/string.test.ts @@ -548,7 +548,6 @@ test("datetime parsing", () => { ).toThrow(); }); -<<<<<<< HEAD test("date", () => { const a = z.string().date(); expect(a.isDate).toEqual(true); @@ -670,7 +669,8 @@ test("time parsing", () => { // expect(() => time4.parse("00:00:00.0")).toThrow(); // expect(() => time4.parse("00:00:00.000")).toThrow(); // expect(() => time4.parse("00:00:00.000+00:00")).toThrow(); -======= +}); + test("duration", () => { const duration = z.string().duration(); expect(duration.isDuration).toEqual(true); @@ -723,7 +723,6 @@ test("duration", () => { expect(result.error.issues[0].message).toEqual("Invalid duration"); } ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) }); test("IP validation", () => { diff --git a/deno/lib/benchmarks/datetime.ts b/deno/lib/benchmarks/datetime.ts index 35dab11c1..8de021a5a 100644 --- a/deno/lib/benchmarks/datetime.ts +++ b/deno/lib/benchmarks/datetime.ts @@ -6,15 +6,6 @@ const DATA = "2021-01-01"; const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]); const MONTHS_30 = new Set([4, 6, 9, 11]); -function generateRandomDatetime(): string { - const year = Math.floor(Math.random() * 3000); - const month = Math.floor(Math.random() * 12) + 1; - const day = Math.floor(Math.random() * 31) + 1; - return `${year}-${month.toString().padStart(2, "0")}-${day - .toString() - .padStart(2, "0")}`; -} - const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/; const datetimeRegexNoLeapYearValidation = /^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/; diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 4af0d141c..1895e435d 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -553,7 +553,6 @@ export type ZodStringCheck = precision: number | null; message?: string; } -<<<<<<< HEAD | { kind: "date"; // withDate: true; @@ -564,12 +563,9 @@ export type ZodStringCheck = precision: number | null; message?: string; } + | { kind: "duration"; message?: string } | { kind: "ip"; version?: IpVersion; message?: string } | { kind: "base64"; message?: string }; -======= - | { kind: "duration"; message?: string } - | { kind: "ip"; version?: IpVersion; message?: string }; ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) export interface ZodStringDef extends ZodTypeDef { checks: ZodStringCheck[]; @@ -584,13 +580,10 @@ const ulidRegex = /^[0-9A-HJKMNP-TV-Z]{26}$/; // /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; const uuidRegex = /^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i; -<<<<<<< HEAD const nanoidRegex = /^[a-z0-9_-]{21}$/i; -======= const durationRegex = /^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/; ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) // from https://stackoverflow.com/a/46181/1550155 // old version: too slow, didn't support unicode // const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; @@ -893,7 +886,6 @@ export class ZodString extends ZodType { }); status.dirty(); } -<<<<<<< HEAD } else if (check.kind === "date") { const regex = dateRegex; @@ -914,14 +906,16 @@ export class ZodString extends ZodType { addIssueToContext(ctx, { code: ZodIssueCode.invalid_string, validation: "time", -======= + message: check.message, + }); + status.dirty(); + } } else if (check.kind === "duration") { if (!durationRegex.test(input.data)) { ctx = this._getOrReturnCtx(input, ctx); addIssueToContext(ctx, { validation: "duration", code: ZodIssueCode.invalid_string, ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) message: check.message, }); status.dirty(); @@ -1160,17 +1154,15 @@ export class ZodString extends ZodType { return !!this._def.checks.find((ch) => ch.kind === "datetime"); } -<<<<<<< HEAD get isDate() { return !!this._def.checks.find((ch) => ch.kind === "date"); } get isTime() { return !!this._def.checks.find((ch) => ch.kind === "time"); -======= + } get isDuration() { return !!this._def.checks.find((ch) => ch.kind === "duration"); ->>>>>>> 29773e8 (feat: Add support for ISO-8601 Durations) } get isEmail() { diff --git a/src/benchmarks/datetime.ts b/src/benchmarks/datetime.ts index 35dab11c1..8de021a5a 100644 --- a/src/benchmarks/datetime.ts +++ b/src/benchmarks/datetime.ts @@ -6,15 +6,6 @@ const DATA = "2021-01-01"; const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]); const MONTHS_30 = new Set([4, 6, 9, 11]); -function generateRandomDatetime(): string { - const year = Math.floor(Math.random() * 3000); - const month = Math.floor(Math.random() * 12) + 1; - const day = Math.floor(Math.random() * 31) + 1; - return `${year}-${month.toString().padStart(2, "0")}-${day - .toString() - .padStart(2, "0")}`; -} - const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/; const datetimeRegexNoLeapYearValidation = /^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/;