You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pydantic 1转2:Timestamp/NaT转换验证失败问题求助

解决Pydantic 2中pd.NaT与pd.Timestamp类型校验冲突问题

问题原因

Pydantic 2的类型校验严格度高于Pydantic 1,而pd.NaT的实际类型是NaTType,并非pd.Timestamp的实例。即便你在前置验证器中将字符串'NaT'转换为pd.NaT,字段类型pd.Timestamp的校验依然会失败。

解决方案

方案1:扩展字段类型,兼容NaTType

直接修改字段类型,同时接受pd.Timestamp实例和pd.NaT的类型:

from typing import Union
import pydantic
from pydantic import BaseModel, ConfigDict
import pandas as pd

class CheckTimestamp(BaseModel):
    # 同时兼容pd.Timestamp和pd.NaT的类型
    ts: Union[pd.Timestamp, type(pd.NaT)]

    model_config = ConfigDict(arbitrary_types_allowed=True)

    @pydantic.field_validator('ts', mode='before')
    def convert_to_timestamp(value: Union[str, pd.Timestamp]):
        if value == "NaT":
            return pd.NaT
        return pd.Timestamp(value)

# 测试通过
sample_model = CheckTimestamp(ts='NaT')
print(sample_model.ts)  # 输出: NaT

方案2:自定义后置校验逻辑,放行pd.NaT

如果不想修改字段类型,可以在后置验证器中添加逻辑,让Pydantic认可pd.NaT为合法值:

import pydantic
from pydantic import BaseModel, ConfigDict
import pandas as pd

class CheckTimestamp(BaseModel):
    ts: pd.Timestamp

    model_config = ConfigDict(arbitrary_types_allowed=True)

    @pydantic.field_validator('ts', mode='before')
    def convert_to_timestamp(value):
        if value == "NaT":
            return pd.NaT
        return pd.Timestamp(value)

    @pydantic.field_validator('ts', mode='after')
    def allow_nat(value):
        # 允许pd.NaT通过校验
        if pd.isna(value):
            return value
        # 非空值仍需是pd.Timestamp实例
        assert isinstance(value, pd.Timestamp), "必须是pd.Timestamp实例或pd.NaT"
        return value

# 测试通过
sample_model = CheckTimestamp(ts='NaT')
print(sample_model.ts)  # 输出: NaT

方案3:封装自定义类型(更优雅)

通过自定义Pydantic类型,统一处理pd.Timestamp和pd.NaT的转换与校验:

import pydantic
from pydantic import BaseModel, GetCoreSchemaHandler
from pydantic_core import core_schema
import pandas as pd

class TimestampWithNaT:
    @classmethod
    def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        return core_schema.no_info_after_validator_function(
            cls.validate,
            core_schema.union_schema([
                core_schema.is_instance_schema(pd.Timestamp),
                core_schema.is_instance_schema(type(pd.NaT))
            ]),
        )

    @classmethod
    def validate(cls, value):
        if isinstance(value, str):
            if value == "NaT":
                return pd.NaT
            return pd.Timestamp(value)
        return value

class CheckTimestamp(BaseModel):
    ts: TimestampWithNaT

    model_config = ConfigDict(arbitrary_types_allowed=True)

# 测试通过
sample_model = CheckTimestamp(ts='NaT')
print(sample_model.ts)  # 输出: NaT

内容的提问来源于stack exchange,提问作者ak_slick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:22:18