【问题标题】:How to change date format in pydantic如何在pydantic中更改日期格式
【发布时间】:2021-06-07 10:36:36
【问题描述】:

如何更改 pydantic 中的日期格式以进行验证和序列化? 为了验证,我使用@validator。两种情况都有解决方案吗?

【问题讨论】:

标签: python python-3.x pydantic


【解决方案1】:

如果您不一定要将此行为应用于所有日期时间,您可以创建一个扩展 datetime 的自定义类型。例如,要创建一个始终确保我们有一个将 tzinfo 设置为 UTC 的日期时间的自定义类型:

from datetime import datetime, timezone

from pydantic.datetime_parse import parse_datetime


class utc_datetime(datetime):
    @classmethod
    def __get_validators__(cls):
        yield parse_datetime  # default pydantic behavior
        yield cls.ensure_tzinfo

    @classmethod
    def ensure_tzinfo(cls, v):
        # if TZ isn't provided, we assume UTC, but you can do w/e you need
        if v.tzinfo is None:
            return v.replace(tzinfo=timezone.utc)
        # else we convert to utc
        return v.astimezone(timezone.utc)
    
    @staticmethod
    def to_str(dt:datetime) -> str:
        return dt.isoformat() # replace with w/e format you want

那么你的 pydantic 模型看起来像:

from pydantic import BaseModel

class SomeObject(BaseModel):
    some_datetime_in_utc: utc_datetime

    class Config:
        json_encoders = {
            utc_datetime: utc_datetime.to_str
        }

走这条路有助于可重用性和关注点分离:)

【讨论】:

  • 以任何方式在其他任何地方声明该配置,这是一种糟糕的做法......
  • 我想可以在对象本身上实现自定义 json 函数,覆盖默认值。我希望有更好的方法,特别是因为在调用 @987654325 时没有考虑编码器@ 代替。
【解决方案2】:

您可以使用 pydantic's custom json encoders 实现自定义 json 序列化程序。然后,与pydantic's custom validator 一起,您可以同时拥有这两种功能。


from datetime import datetime, timezone
from pydantic import BaseModel, validator


def convert_datetime_to_iso_8601_with_z_suffix(dt: datetime) -> str:
    return dt.strftime('%Y-%m-%dT%H:%M:%SZ')


def transform_to_utc_datetime(dt: datetime) -> datetime:
    return dt.astimezone(tz=timezone.utc)


class DateTimeSpecial(BaseModel):
    datetime_in_utc_with_z_suffix: datetime

    # custom input conversion for that field
    _normalize_datetimes = validator(
        "datetime_in_utc_with_z_suffix",
        allow_reuse=True)(transform_to_utc_datetime)

    class Config:
        json_encoders = {
            # custom output conversion for datetime
            datetime: convert_datetime_to_iso_8601_with_z_suffix
        }


if __name__ == "__main__":
    special_datetime = DateTimeSpecial(datetime_in_utc_with_z_suffix="2042-3-15T12:45+01:00")  # note the different timezone

    # input conversion
    print(special_datetime.datetime_in_utc_with_z_suffix)  # 2042-03-15 11:45:00+00:00

    # output conversion
    print(special_datetime.json())  # {"datetime_in_utc_with_z_suffix": "2042-03-15T11:45:00Z"}

这个变体也适用于我实际以这种方式使用它的 fastapi 的序列化程序。

【讨论】:

    【解决方案3】:

    我认为预验证器在这里可以提供帮助。

    from datetime import datetime, date
    
    from pydantic import BaseModel, validator
    
    
    class OddDate(BaseModel):
        birthdate: date
    
        @validator("birthdate", pre=True)
        def parse_birthdate(cls, value):
            return datetime.strptime(
                value,
                "%d/%m/%Y"
            ).date()
    
    
    if __name__ == "__main__":
        odd_date = OddDate(birthdate="12/04/1992")
        print(odd_date.json()) #{"birthdate": "1992-04-12"}
    

    【讨论】:

    • 这就是我实现验证器的方式。以及如何制作序列化器?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 2019-01-09
    • 2015-08-26
    • 2017-11-08
    • 2011-11-11
    • 2020-05-18
    相关资源
    最近更新 更多