如何在 SqlAlchemy / Mysql 中存储时区感知日期时间值?
Posted
技术标签:
【中文标题】如何在 SqlAlchemy / Mysql 中存储时区感知日期时间值?【英文标题】:How to store timezone aware datetime values in SqlAlchemy / Mysql? 【发布时间】:2020-07-19 15:58:51 【问题描述】:我想在 mysql 数据库中存储一个 Python 时区感知日期时间属性。我使用 SqlAlchemy。在 SqlAlchemy 类定义中,我通过以下方式指定列:
a_utcDatetime = Column(DATETIME(fsp=6))
我意识到在数据库中该列不再有时区信息。 此外,从数据库中读取后,该变量也丢失了其时区信息。
有什么方法可以在定义时将a_utcDatetime
配置为时区感知?
【问题讨论】:
【参考方案1】:如果您真的想存储时区偏移量(而不仅仅是遵循将所有日期/时间值存储为 UTC 的约定),那么您需要一个单独的列来存储该偏移量值。我刚刚用 MySQL 试过这个,它似乎工作:
from datetime import datetime, timezone, timedelta
from sqlalchemy import (
create_engine,
Column,
Integer,
String,
text,
__version__ as sa_version,
DATETIME,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
connection_uri = "mysql+pymysql://root:toot@localhost:3307/mydb"
engine = create_engine(connection_uri, echo=False)
Base = declarative_base()
with engine.begin() as conn:
conn.execute(text("DROP TABLE IF EXISTS event_log"))
class EventLog(Base):
__tablename__ = "event_log"
id = Column(Integer, primary_key=True)
event = Column(String(50))
local_datetime = Column(DATETIME)
tz_offset_minutes = Column(Integer)
@property
def dt_aware(self):
return self.local_datetime.replace(
tzinfo=timezone(timedelta(minutes=self.tz_offset_minutes))
)
@dt_aware.setter
def dt_aware(self, value):
self.local_datetime = value.replace(tzinfo=None)
self.tz_offset_minutes = (
value.tzinfo.utcoffset(value).total_seconds() // 60
)
def __repr__(self):
return (
f"<EventLog(id=self.id, "
f"event=repr(self.event), "
f"str(dt_aware)='self.dt_aware'>"
)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
my_event_start = datetime(
2020, 4, 20, 16, 20, 0, tzinfo=timezone(timedelta(hours=-7))
)
my_event = EventLog(id=1, event="an event", dt_aware=my_event_start)
session.add(my_event)
session.commit()
# check results by querying database directly
sql = text("SELECT * FROM event_log ORDER BY id")
with engine.begin() as conn:
result = conn.execute(sql).fetchall()
print(result)
""" console output:
[(1, 'an event', datetime.datetime(2020, 4, 20, 16, 20), -420)]
"""
print(my_event)
""" console output:
<EventLog(id=1, event='an event', str(dt_aware)='2020-04-20 16:20:00-07:00'>
"""
print(type(my_event.dt_aware)) # <class 'datetime.datetime'>
【讨论】:
我可以在 *** 上找到多少帅哥。精彩的!所以这个解决方案看起来很不错。谢谢你。也许我更容易听从您的建议,将值作为纯 UTC 保存在数据库中。以上是关于如何在 SqlAlchemy / Mysql 中存储时区感知日期时间值?的主要内容,如果未能解决你的问题,请参考以下文章
每当 MySQL 抛出警告时,我如何通知 sqlalchemy 引发错误?
如何使用 Python+SQLAlchemy 远程连接 MySQL 数据库?
如何使用 sqlalchemy 在 mysql 中设置 DEFAULT ON UPDATE CURRENT_TIMESTAMP?