TypeScript-first schema validation library with static type inference. Define schemas, validate data, and get type safety with zero dependencies.
Validators for ISO 8601 formatted datetime, date, time, and duration strings with precision and timezone configuration.
Creates a string schema that validates ISO 8601 datetime format with configurable precision and timezone handling.
/**
* Create an ISO 8601 datetime string validator
* @param params - Optional configuration for precision and timezone
* @returns String schema with ISO datetime validation
*/
namespace iso {
function datetime(params?: ISODateTimeParams): ZodISODateTime;
}
interface ISODateTimeParams extends StringParams {
precision?: number;
offset?: boolean;
local?: boolean;
}
interface StringParams {
errorMap?: ErrorMapFunction;
invalid_type_error?: string;
required_error?: string;
description?: string;
}Usage Examples:
import * as z from 'zod';
// Basic ISO datetime
const DateTime = z.iso.datetime();
DateTime.parse('2024-01-15T10:30:00.000Z'); // => valid
DateTime.parse('2024-01-15T10:30:00Z'); // => valid
DateTime.parse('2024-01-15T10:30:00+05:30'); // => valid
// With millisecond precision
const PreciseDateTime = z.iso.datetime({ precision: 3 });
PreciseDateTime.parse('2024-01-15T10:30:00.123Z'); // => valid
// Require timezone offset
const WithOffset = z.iso.datetime({ offset: true });
WithOffset.parse('2024-01-15T10:30:00+00:00'); // => valid
// WithOffset.parse('2024-01-15T10:30:00'); // throws (no offset)
// Local datetime (no timezone)
const LocalDateTime = z.iso.datetime({ local: true });
LocalDateTime.parse('2024-01-15T10:30:00'); // => valid
// LocalDateTime.parse('2024-01-15T10:30:00Z'); // throws (has timezone)
// Combined options
const CustomDateTime = z.iso.datetime({
precision: 6,
offset: true,
invalid_type_error: 'Must be a valid ISO datetime',
});
// In object schemas
const Event = z.object({
id: z.string(),
name: z.string(),
startTime: z.iso.datetime(),
endTime: z.iso.datetime(),
});
// Transform to Date
const DateTimeToDate = z.iso.datetime().transform((str) => new Date(str));ISO datetime validation is also available as a method on string schemas:
import * as z from 'zod';
const DateTime = z.string().datetime();
const PreciseDateTime = z.string().datetime({ precision: 3 });
const WithOffset = z.string().datetime({ offset: true });Creates a string schema that validates ISO 8601 date format (YYYY-MM-DD).
/**
* Create an ISO 8601 date string validator
* @param params - Optional configuration for error handling
* @returns String schema with ISO date validation
*/
namespace iso {
function date(params?: ISODateParams): ZodISODate;
}
interface ISODateParams extends StringParams {}Usage Examples:
import * as z from 'zod';
// Basic ISO date
const Date = z.iso.date();
Date.parse('2024-01-15'); // => valid
Date.parse('2024-12-31'); // => valid
Date.parse('1999-01-01'); // => valid
// Date.parse('2024-1-5'); // throws (must be zero-padded)
// Date.parse('2024/01/15'); // throws (wrong format)
// In object schemas
const DateRange = z.object({
start: z.iso.date(),
end: z.iso.date(),
});
DateRange.parse({
start: '2024-01-01',
end: '2024-12-31',
}); // => valid
// Transform to Date object
const DateToObject = z.iso.date().transform((str) => new Date(str));
// Validation with refinement
const FutureDate = z.iso.date().refine((dateStr) => {
const date = new Date(dateStr);
return date > new Date();
}, 'Date must be in the future');
// Birth date
const BirthDate = z.iso.date().refine((dateStr) => {
const date = new Date(dateStr);
const age = new Date().getFullYear() - date.getFullYear();
return age >= 18 && age <= 120;
}, 'Invalid birth date');ISO date validation is also available as a method on string schemas:
import * as z from 'zod';
const Date = z.string().date();
const BirthDate = z.string().date().refine((d) => new Date(d) < new Date());Creates a string schema that validates ISO 8601 time format (HH:mm:ss).
/**
* Create an ISO 8601 time string validator
* @param params - Optional configuration for precision
* @returns String schema with ISO time validation
*/
namespace iso {
function time(params?: ISOTimeParams): ZodISOTime;
}
interface ISOTimeParams extends StringParams {
precision?: number;
}Usage Examples:
import * as z from 'zod';
// Basic ISO time
const Time = z.iso.time();
Time.parse('10:30:00'); // => valid
Time.parse('23:59:59'); // => valid
Time.parse('00:00:00'); // => valid
// With millisecond precision
const PreciseTime = z.iso.time({ precision: 3 });
PreciseTime.parse('10:30:00.123'); // => valid
PreciseTime.parse('14:25:30.000'); // => valid
// With microsecond precision
const MicroTime = z.iso.time({ precision: 6 });
MicroTime.parse('10:30:00.123456'); // => valid
// In object schemas
const Schedule = z.object({
openTime: z.iso.time(),
closeTime: z.iso.time(),
});
Schedule.parse({
openTime: '09:00:00',
closeTime: '17:00:00',
}); // => valid
// Business hours validation
const BusinessHours = z.object({
open: z.iso.time(),
close: z.iso.time(),
}).refine((data) => {
const open = parseTime(data.open);
const close = parseTime(data.close);
return close > open;
}, 'Close time must be after open time');
function parseTime(timeStr: string): number {
const [hours, minutes, seconds] = timeStr.split(':').map(Number);
return hours * 3600 + minutes * 60 + seconds;
}
// Time with timezone
const TimeWithZone = z.string().time({ precision: 3 }).regex(/[+-]\d{2}:\d{2}$/);ISO time validation is also available as a method on string schemas:
import * as z from 'zod';
const Time = z.string().time();
const PreciseTime = z.string().time({ precision: 3 });Creates a string schema that validates ISO 8601 duration format (P[n]Y[n]M[n]DT[n]H[n]M[n]S).
/**
* Create an ISO 8601 duration string validator
* @param params - Optional configuration for error handling
* @returns String schema with ISO duration validation
*/
namespace iso {
function duration(params?: ISODurationParams): ZodISODuration;
}
interface ISODurationParams extends StringParams {}Usage Examples:
import * as z from 'zod';
// Basic ISO duration
const Duration = z.iso.duration();
Duration.parse('P1Y'); // => valid (1 year)
Duration.parse('P3Y6M4D'); // => valid (3 years, 6 months, 4 days)
Duration.parse('PT12H30M5S'); // => valid (12 hours, 30 minutes, 5 seconds)
Duration.parse('P1DT12H'); // => valid (1 day and 12 hours)
Duration.parse('PT0.5S'); // => valid (0.5 seconds)
// Common durations
Duration.parse('PT1H'); // 1 hour
Duration.parse('PT30M'); // 30 minutes
Duration.parse('P7D'); // 7 days
Duration.parse('P1W'); // 1 week
Duration.parse('P1M'); // 1 month
Duration.parse('P1Y'); // 1 year
// In object schemas
const Video = z.object({
title: z.string(),
duration: z.iso.duration(),
});
Video.parse({
title: 'Tutorial',
duration: 'PT15M30S', // 15 minutes 30 seconds
}); // => valid
// Subscription period
const Subscription = z.object({
plan: z.enum(['monthly', 'yearly']),
billingPeriod: z.iso.duration(),
});
Subscription.parse({
plan: 'monthly',
billingPeriod: 'P1M',
}); // => valid
// Transform to milliseconds
const DurationToMs = z.iso.duration().transform((dur) => {
// Parse duration and convert to milliseconds
return parseDurationToMs(dur);
});
function parseDurationToMs(duration: string): number {
// Implementation would parse ISO 8601 duration
return 0;
}
// Time interval
const TimeInterval = z.object({
start: z.iso.datetime(),
duration: z.iso.duration(),
});ISO duration validation is also available as a method on string schemas:
import * as z from 'zod';
const Duration = z.string().duration();
const VideoDuration = z.string().duration().refine((d) => {
const ms = parseDurationToMs(d);
return ms <= 3600000; // Max 1 hour
}, 'Video too long');
function parseDurationToMs(duration: string): number {
return 0; // Implementation
}Common patterns for using ISO datetime schemas together:
import * as z from 'zod';
// Event with date and time
const Event = z.object({
title: z.string(),
date: z.iso.date(),
startTime: z.iso.time(),
endTime: z.iso.time(),
duration: z.iso.duration(),
});
// API timestamp fields
const ApiRecord = z.object({
id: z.string(),
createdAt: z.iso.datetime(),
updatedAt: z.iso.datetime(),
deletedAt: z.iso.datetime().nullable(),
});
// Schedule with recurrence
const RecurringEvent = z.object({
title: z.string(),
startDate: z.iso.date(),
startTime: z.iso.time(),
duration: z.iso.duration(),
recurrence: z.object({
frequency: z.enum(['daily', 'weekly', 'monthly']),
interval: z.number().int().positive(),
}),
});
// Date range query
const DateRangeQuery = z.object({
from: z.iso.date(),
to: z.iso.date(),
}).refine((data) => data.to >= data.from, {
message: 'End date must be after start date',
path: ['to'],
});
// Transform ISO strings to Date objects
const TimestampedRecord = z.object({
id: z.string(),
timestamp: z.iso.datetime().transform((s) => new Date(s)),
date: z.iso.date().transform((s) => new Date(s)),
});
type TimestampedRecord = z.infer<typeof TimestampedRecord>;
// { id: string; timestamp: Date; date: Date }class ZodISODateTime {
readonly _type: 'ZodISODateTime';
readonly precision?: number;
readonly offset?: boolean;
readonly local?: boolean;
parse(data: unknown): string;
safeParse(data: unknown): SafeParseReturnType<unknown, string>;
}
class ZodISODate {
readonly _type: 'ZodISODate';
parse(data: unknown): string;
safeParse(data: unknown): SafeParseReturnType<unknown, string>;
}
class ZodISOTime {
readonly _type: 'ZodISOTime';
readonly precision?: number;
parse(data: unknown): string;
safeParse(data: unknown): SafeParseReturnType<unknown, string>;
}
class ZodISODuration {
readonly _type: 'ZodISODuration';
parse(data: unknown): string;
safeParse(data: unknown): SafeParseReturnType<unknown, string>;
}
type ErrorMapFunction = (
issue: ZodIssueOptionalMessage,
ctx: ErrorMapCtx
) => { message: string };
interface ErrorMapCtx {
defaultError: string;
data: any;
}
type SafeParseReturnType<Input, Output> =
| { success: true; data: Output }
| { success: false; error: ZodError<Input> };
class ZodError<T = any> extends Error {
issues: ZodIssue[];
}Install with Tessl CLI
npx tessl i tessl/npm-zoddocs
guides
reference