Temporal Data Handling
Temporal data handling in pydantic-core is managed through four specialized schemas defined in pydantic_core.core_schema: DateSchema, TimeSchema, DatetimeSchema, and TimedeltaSchema. These schemas provide robust validation for Python's native datetime module types, supporting range constraints, timezone enforcement, and precision control.
Core Temporal Schemas
The implementation relies on TypedDict structures that define the validation parameters for each type.
- DateSchema: Validates
datetime.dateobjects and compatible strings/integers. - TimeSchema: Validates
datetime.timeobjects, supporting timezone and precision constraints. - DatetimeSchema: A comprehensive schema for
datetime.datetime, combining features of both date and time validation. - TimedeltaSchema: Validates durations (
datetime.timedelta), supporting ISO8601 duration strings and numeric (seconds) input.
Shared Comparison Constraints
All four temporal schemas support standard comparison operators: le (less than or equal), ge (greater than or equal), lt (less than), and gt (greater than). These constraints must be of the same type as the schema (e.g., le in a DateSchema must be a datetime.date).
from datetime import date
from pydantic_core import SchemaValidator, core_schema
# Example: Date range validation
schema = core_schema.date_schema(le=date(2020, 1, 1), ge=date(2019, 1, 1))
v = SchemaValidator(schema)
assert v.validate_python(date(2019, 6, 1)) == date(2019, 6, 1)
Relative Validation with now_op
DateSchema and DatetimeSchema support relative validation using the now_op field. This allows enforcing that a value is in the past or future relative to the moment of validation.
now_op: Either'past'or'future'.now_utc_offset: An integer representing the UTC offset in seconds (defaults to the local system offset).
In pydantic-core/tests/validators/test_date.py, this is used to validate dates relative to the current time:
# Validating a date is in the past
v = SchemaValidator(core_schema.date_schema(now_op='past'))
# Fails for future dates
# v.validate_python('2068-06-08') -> ValidationError: Date should be in the past
Timezone Management
TimeSchema and DatetimeSchema use the tz_constraint to enforce timezone requirements. This is critical for APIs that require consistent timezone handling.
'aware': Requires the input to have timezone information.'naive': Requires the input to NOT have timezone information.int: Requires a specific fixed UTC offset in seconds.
Example from pydantic-core/tests/validators/test_datetime.py:
# Enforcing timezone awareness
v = SchemaValidator(core_schema.datetime_schema(tz_constraint='aware'))
v.validate_python('2022-06-08T12:13:14Z') # Success
# v.validate_python('2022-06-08T12:13:14') -> ValidationError: Input should have timezone info
Precision Handling
TimeSchema, DatetimeSchema, and TimedeltaSchema include a microseconds_precision setting to control how sub-microsecond data is handled.
'truncate'(default): Silently drops any precision beyond microseconds.'error': Raises aValidationErrorif the input contains more than 6 digits of fractional seconds.
Example from pydantic-core/tests/validators/test_time.py:
# Raising an error on excessive precision
v = SchemaValidator(core_schema.time_schema(microseconds_precision='error'))
# v.validate_python('00:00:00.1234567') -> ValidationError: second fraction value is more than 6 digits long
Duration Validation (TimedeltaSchema)
The TimedeltaSchema is unique in its support for multiple input formats, including ISO8601 duration strings (e.g., P3DT1H) and numeric values interpreted as seconds.
from datetime import timedelta
from pydantic_core import SchemaValidator, core_schema
v = SchemaValidator(core_schema.timedelta_schema())
# ISO8601 string support
assert v.validate_python('P0Y0M3D2WT1H2M3.5S') == timedelta(days=17, hours=1, minutes=2, seconds=3, milliseconds=500)
# Numeric (seconds) support
assert v.validate_python(3601) == timedelta(hours=1, seconds=1)
Serialization Configuration
Serialization behavior for temporal types is configured globally via CoreConfig or per-schema via SerSchema.
ser_json_temporal: Controls JSON output for all temporal types. Options include'iso8601','seconds', and'milliseconds'.ser_json_timedelta: Specifically fortimedelta. Options are'iso8601'or'float'. Note that this is ignored ifser_json_temporalis explicitly set.
These settings ensure that validated temporal objects are converted back to strings or numbers consistently during to_json() operations.
Common Validation Behaviors
Date from Datetime
When using DateSchema, validating a datetime object or string will succeed in lax mode (default) only if the time component is zero. If the time is non-zero, it is considered "inexact" and will fail unless strict=False is explicitly handled or the input is a pure date.
Numeric Limits
TimedeltaSchema enforces internal limits on numeric inputs. For example, durations exceeding 999,999,999 days (or their equivalent in seconds) will trigger a validation error, as seen in pydantic-core/tests/validators/test_timedelta.py.