SQLAlchemy DateTime timezone

前端 未结 4 1116
情话喂你
情话喂你 2021-01-31 07:54

SQLAlchemy\'s DateTime type allows for a timezone=True argument to save a non-naive datetime object to the database, and to return it as such. Is there

4条回答
  •  误落风尘
    2021-01-31 08:08

    One way to solve this issue is to always use timezone-aware fields in the database. But note that the same time can be expressed differently depending on the timezone, and even though this is not a problem for computers it is very inconvenient for us:

    2003-04-12 23:05:06 +01:00
    2003-04-13 00:05:06 +02:00 # This is the same time as above!
    

    Also Postgresql stores all timezone-aware dates and times internally in UTC. They are converted to local time in the zone specified by the timezone configuration parameter before being displayed to the client.

    Instead, I recommend to use UTC timestamps both throughout the app and timezone-naive dates and times in the database, and only convert them to users local timezone before user sees them.

    This strategy lets you have the cleanest code, avoiding any timezone conversions and confusions, and makes your database and app work consistently independent of the "local timezone" differences. For example, you might have your development machine and production server running on cloud in different timezones.

    To achieve this, tell Postgresql that you want to see timezones in UTC before initializing the engine.

    In SqlAlchemy you do it like this:

    engine = create_engine(..., connect_args={"options": "-c timezone=utc"})
    

    And if you are using tornado-sqlalchemy you can use:

    factory = make_session_factory(..., connect_args={"options": "-c timezone=utc"})
    

    Since we use all UTC timezones everywhere, we simply use timezone-naive dates and times in the model:

    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime)
    

    And the same in case if you are using alembic:

    sa.Column('created_at', sa.DateTime()),
    sa.Column('updated_at', sa.DateTime()),
    

    And in the code use UTC time:

    from datetime import datetime
    ...
    model_object.updated_at = datetime.now(timezone.utc)
    

提交回复
热议问题