如何在Fast API中将Unix时间戳解析为不带时区的日期时间格式

7
假设我有一个Pydantic模型。
class EventEditRequest(BaseModel):
    uid: UUID
    name: str
    start_dt: datetime
    end_dt: datetime

我发送了一个带有body的请求b'{"uid":"a38a7543-20ca-4a50-ab4e-e6a3ae379d3c","name":"test event2222","start_dt":1600414328,"end_dt":1600450327}'

因此,start_dtend_dt都是Unix时间戳。 但在终点处,它们变成带有时区的日期时间。

@app.put('...')
def edit_event(event_data: EventEditRequest):
    event_data.start_dt.tzinfo is not None  # True

我不想在端点函数中手动编辑start_dtend_dt来消除时区。我该如何设置我的pydantic模型,使它生成没有时区的datetime?

我想到的一个解决方案是创建一个中间件,在将Unix时间戳转换为Pydantic对象之前,将其替换为不带时区的日期时间。但是我认为这并不是最好的解决方案。 - sashaaero
3个回答

7

您可以使用自己的@validator手动解析datetime

from datetime import datetime

from pydantic import BaseModel, validator


class Model(BaseModel):
    dt: datetime = None


class ModelNaiveDt(BaseModel):
    dt: datetime = None

    @validator("dt", pre=True)
    def dt_validate(cls, dt):
        return datetime.fromtimestamp(dt)


print(Model(dt=1600414328))
print(ModelNaiveDt(dt=1600414328))

输出:

dt=datetime.datetime(2020, 9, 18, 7, 32, 8, tzinfo=datetime.timezone.utc)
dt=datetime.datetime(2020, 9, 18, 10, 32, 8)

5

正如sashaaero在他们的回答中提到的那样,您可以通过自定义类型来实现此目的。但是,您可以使用Pydantic中现有的验证器,然后仅删除时区信息,而无需创建自己的验证。

from pydantic.datetime_parse import parse_datetime


class OffsetNaiveDatetime(datetime):

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        v = parse_datetime(v)
        v = v.replace(tzinfo=None)
        return v

但要小心,仅在不需要任何时区信息或不适用时使用它。


3
创建自定义类型是另一种实现它的方法。
class UnixDatetime(datetime):
    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v):
        if isinstance(v, datetime):
            print('Some request sends datetime not in UNIX format', file=sys.stderr)
            return v.replace(tzinfo=None)
        elif isinstance(v, int):
            return datetime.fromtimestamp(v)
        assert False, 'Datetime came of %s type' % type(v)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接