Skip to main content

Temporal and Duration Validation

Validate dates, times, and durations using the temporal schema types in pydantic-core. These schemas support strict or lax validation, range constraints, timezone enforcement, and precision handling.

Basic Temporal Validation

To validate a datetime, use cs.datetime_schema(). In lax mode (default), it accepts datetime objects, date objects, ISO8601 strings, and Unix timestamps.

from datetime import datetime, timezone
from pydantic_core import SchemaValidator, core_schema as cs

# Basic datetime validation
v = SchemaValidator(cs.datetime_schema())

# Validates from datetime object
v.validate_python(datetime(2022, 6, 8, 12, 13, 14))

# Validates from ISO8601 string (Lax mode)
v.validate_python('2022-06-08T12:13:14Z')

# Validates from Unix timestamp (Lax mode)
v.validate_python(1654646400)
# Returns: datetime(2022, 6, 8, 0, 0, tzinfo=timezone.utc)

Strict Mode

Enforce strict validation to reject strings and numeric timestamps, requiring actual Python objects.

v = SchemaValidator(cs.datetime_schema(strict=True))

# This will raise a ValidationError
try:
v.validate_python('2022-06-08T12:13:14')
except Exception as e:
print(e)

Range Constraints

All temporal schemas (DateSchema, TimeSchema, DatetimeSchema, TimedeltaSchema) support range constraints: le (less than or equal), ge (greater than or equal), lt (less than), and gt (greater than).

from datetime import datetime
from pydantic_core import SchemaValidator, core_schema as cs

# Datetime must be after Jan 1st, 2022
v = SchemaValidator(cs.datetime_schema(gt=datetime(2022, 1, 1)))

v.validate_python(datetime(2022, 6, 8)) # OK
# v.validate_python(datetime(2021, 12, 31)) # Raises ValidationError

Timezone Constraints

Use tz_constraint to enforce timezone awareness or specific offsets for DatetimeSchema and TimeSchema.

Enforcing Awareness

Set tz_constraint to 'aware' or 'naive'.

# Require timezone-aware datetimes
v = SchemaValidator(cs.datetime_schema(tz_constraint='aware'))

v.validate_python('2022-06-08T12:13:14Z') # OK
# v.validate_python('2022-06-08T12:13:14') # Raises ValidationError

Specific Offsets

Set tz_constraint to an integer representing the required UTC offset in seconds.

# Require UTC (offset 0)
v = SchemaValidator(cs.datetime_schema(tz_constraint=0))

v.validate_python('2022-06-08T12:13:14Z') # OK
# v.validate_python('2022-06-08T12:13:14+01:00') # Raises ValidationError (offset 3600)

Relative Validation (Past/Future)

DateSchema and DatetimeSchema support now_op for validating values relative to the current time.

# Validate that a date is in the past
v = SchemaValidator(cs.date_schema(now_op='past'))

# If today is 2023-10-27:
v.validate_python('2022-01-01') # OK
# v.validate_python('2099-01-01') # Raises ValidationError

You can control the "now" reference point using now_utc_offset. If not provided, it defaults to the local system's UTC offset.

Timedelta Formats

TimedeltaSchema supports a wide variety of input formats in lax mode, including ISO8601 durations, numeric seconds, and human-readable strings.

from datetime import timedelta
from pydantic_core import SchemaValidator, core_schema as cs

v = SchemaValidator(cs.timedelta_schema())

# ISO8601 Duration
v.validate_python('P2DT1H') # 2 days, 1 hour

# Numeric seconds
v.validate_python(3601) # 1 hour, 1 second

# Human readable
v.validate_python('123days, 12:34') # 123 days, 12 hours, 34 minutes

Microsecond Precision

By default, sub-microsecond precision is truncated. You can change this behavior using microseconds_precision.

# Fail if precision would be lost
v = SchemaValidator(cs.time_schema(microseconds_precision='error'))

# 6 digits is fine
v.validate_python('12:13:14.123456')

# 7 digits raises ValidationError
# v.validate_python('12:13:14.1234567')

Troubleshooting

Timezone Comparison Gotchas

When using now_op with timezone-naive inputs, the comparison is performed "dumbly" against the system time. If your input is naive but represents a time in a different zone, it may fail unexpectedly.

Unix Timestamp Limits

Unix timestamps are supported for dates between 0000-01-01 and 9999-12-31. Values outside this range (e.g., year 10000) will raise a ValidationError.

Date from Datetime

When validating a DateSchema, if a datetime object or string is provided, it must have zero time (midnight).

v = SchemaValidator(cs.date_schema())
v.validate_python('2022-06-08T00:00:00') # OK
# v.validate_python('2022-06-08T12:00:00') # Raises date_from_datetime_inexact

Temporal Units

When validating from numbers, the unit (seconds vs milliseconds) can be configured via the val_temporal_unit setting in the validator config. Options are 'seconds', 'milliseconds', or 'infer'.