@@ -355,41 +355,59 @@ The `z.iso.datetime()` method enforces ISO 8601; by default, no timezone offsets
355
355
``` ts
356
356
const datetime = z .iso .datetime ();
357
357
358
- datetime .parse (" 2020-01-01T00:00:00Z" ); // ✅
359
- datetime .parse (" 2020-01-01T00:00:00.123Z" ); // ✅
360
- datetime .parse (" 2020-01-01T00:00:00.123456Z" ); // ✅ (arbitrary precision)
361
- datetime .parse (" 2020-01-01T00:00:00+02:00" ); // ❌ (no offsets allowed)
358
+ datetime .parse (" 2020-01-01T06:15:00Z" ); // ✅
359
+ datetime .parse (" 2020-01-01T06:15:00.123Z" ); // ✅
360
+ datetime .parse (" 2020-01-01T06:15:00.123456Z" ); // ✅ (arbitrary precision)
361
+ datetime .parse (" 2020-01-01T06:15:00+02:00" ); // ❌ (offsets not allowed)
362
+ datetime .parse (" 2020-01-01T06:15:00" ); // ❌ (local not allowed)
362
363
```
363
364
364
365
To allow timezone offsets:
365
366
366
367
``` ts
367
368
const datetime = z .iso .datetime ({ offset: true });
368
369
369
- // result is normalized to RFC 3339 format
370
- datetime .parse (" 2020-01-01T00:00:00+02" ); // ✅ "2020-01-01T00:00:00+02:00"
371
- datetime .parse (" 2020-01-01T00:00:00+0200" ); // ✅ "2020-01-01T00:00:00+02:00"
372
- datetime .parse (" 2020-01-01T00:00:00+02:00" ); // ✅ "2020-01-01T00:00:00+02:00"
370
+ // allows timezone offsets
371
+ datetime .parse (" 2020-01-01T06:15:00+02:00" ); // ✅
372
+
373
+ // basic offsets not allowed
374
+ datetime .parse (" 2020-01-01T06:15:00+02" ); // ❌
375
+ datetime .parse (" 2020-01-01T06:15:00+0200" ); // ❌
373
376
374
377
// Z is still supported
375
- datetime .parse (" 2020-01-01T00:00 :00Z" ); // ✅
378
+ datetime .parse (" 2020-01-01T06:15 :00Z" ); // ✅
376
379
```
377
380
378
381
To allow unqualified (timezone-less) datetimes:
379
382
380
383
``` ts
381
384
const schema = z .iso .datetime ({ local: true });
382
- schema .parse (" 2020-01-01T00:00:00" ); // ✅
385
+ schema .parse (" 2020-01-01T06:15:01" ); // ✅
386
+ schema .parse (" 2020-01-01T06:15" ); // ✅ seconds optional
383
387
```
384
388
385
- To constrain the allowable ` precision ` (by default, arbitrary sub-second precision is supported) .
389
+ To constrain the allowable time ` precision ` . By default, seconds are optional and arbitrary sub-second precision is allowed .
386
390
387
391
``` ts
388
- const datetime = z .iso .datetime ({ precision: 3 });
392
+ const a = z .iso .datetime ();
393
+ a .parse (" 2020-01-01T06:15Z" ); // ✅
394
+ a .parse (" 2020-01-01T06:15:00Z" ); // ✅
395
+ a .parse (" 2020-01-01T06:15:00.123Z" ); // ✅
396
+
397
+ const b = z .iso .datetime ({ precision: - 1 }); // minute precision (no seconds)
398
+ b .parse (" 2020-01-01T06:15Z" ); // ✅
399
+ b .parse (" 2020-01-01T06:15:00Z" ); // ❌
400
+ b .parse (" 2020-01-01T06:15:00.123Z" ); // ❌
389
401
390
- datetime .parse (" 2020-01-01T00:00:00.123Z" ); // ✅
391
- datetime .parse (" 2020-01-01T00:00:00Z" ); // ❌
392
- datetime .parse (" 2020-01-01T00:00:00.123456Z" ); // ❌
402
+ const c = z .iso .datetime ({ precision: 0 }); // second precision only
403
+ c .parse (" 2020-01-01T06:15Z" ); // ❌
404
+ c .parse (" 2020-01-01T06:15:00Z" ); // ✅
405
+ c .parse (" 2020-01-01T06:15:00.123Z" ); // ❌
406
+
407
+ const d = z .iso .datetime ({ precision: 3 }); // millisecond precision only
408
+ d .parse (" 2020-01-01T06:15Z" ); // ❌
409
+ d .parse (" 2020-01-01T06:15:00Z" ); // ❌
410
+ d .parse (" 2020-01-01T06:15:00.123Z" ); // ✅
393
411
```
394
412
395
413
### ISO dates
@@ -406,29 +424,31 @@ date.parse("2020-01-32"); // ❌
406
424
407
425
### ISO times
408
426
409
- > Added in Zod 3.23
410
-
411
- 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.
427
+ The ` z.iso.time() ` method validates strings in the format ` HH:MM[:SS[.s+]] ` . By default seconds are optional, as are sub-second deciams.
412
428
413
429
``` ts
414
430
const time = z .iso .time ();
415
431
416
- time .parse (" 00:00:00" ); // ✅
417
- time .parse (" 09:52:31" ); // ✅
418
- time .parse (" 23:59:59.9999999" ); // ✅ (arbitrary precision)
419
-
420
- time .parse (" 00:00:00.123Z" ); // ❌ (no `Z` allowed)
421
- time .parse (" 00:00:00.123+02:00" ); // ❌ (no offsets allowed)
432
+ time .parse (" 03:15" ); // ✅
433
+ time .parse (" 03:15:00" ); // ✅
434
+ time .parse (" 03:15:00.9999999" ); // ✅ (arbitrary precision)
422
435
```
423
436
424
- You can set the ` precision ` option to constrain the allowable decimal precision .
437
+ No offsets of any kind are allowed .
425
438
426
439
``` ts
427
- const time = z .iso .time ({ precision: 3 });
440
+ time .parse (" 03:15:00Z" ); // ❌ (no `Z` allowed)
441
+ time .parse (" 03:15:00+02:00" ); // ❌ (no offsets allowed)
442
+ ```
428
443
429
- time .parse (" 00:00:00.123" ); // ✅
430
- time .parse (" 00:00:00.123456" ); // ❌
431
- time .parse (" 00:00:00" ); // ❌
444
+ Use the ` precision ` parameter to constrain the allowable decimal precision.
445
+
446
+ ``` ts
447
+ z .iso .time ({ precision: - 1 }); // HH:MM (minute precision)
448
+ z .iso .time ({ precision: 0 }); // HH:MM:SS (second precision)
449
+ z .iso .time ({ precision: 1 }); // HH:MM:SS.s (decisecond precision)
450
+ z .iso .time ({ precision: 2 }); // HH:MM:SS.ss (centisecond precision)
451
+ z .iso .time ({ precision: 3 }); // HH:MM:SS.sss (millisecond precision)
432
452
```
433
453
434
454
### IP addresses
@@ -597,7 +617,7 @@ Use `z.date()` to validate `Date` instances.
597
617
598
618
``` ts
599
619
z .date ().safeParse (new Date ()); // success: true
600
- z .date ().safeParse (" 2022-01-12T00:00 :00.000Z" ); // success: false
620
+ z .date ().safeParse (" 2022-01-12T06:15 :00.000Z" ); // success: false
601
621
```
602
622
603
623
To customize the error message:
@@ -1586,7 +1606,7 @@ const Person = z.record(Keys, z.string());
1586
1606
const myRecord: MyRecord = { a: " foo" }; // ❌ missing required key `b`
1587
1607
```
1588
1608
1589
- In Zod 3, exhaustiveness was not checked. To replicate the Zod 3 behavior, use ` z.partialRecord() ` .
1609
+ In Zod 3, exhaustiveness was not checked. To replicate the old behavior, use ` z.partialRecord() ` .
1590
1610
1591
1611
</Callout >
1592
1612
0 commit comments