SQLAlchemy使用SQLi丢失时区信息

2024-10-01 07:46:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到了一个问题,SQLAlchemy(版本0.6.4&0.6.8)在提交到一个带有SQLAlchemy的DateTime类定义的列的SQLite数据库时丢失了datetime对象的时区信息。(我意识到SQLAlchemy正在将其转换为字符串并返回,这是我认为问题的一半)。在

代码胜于雄辩,我有以下示例/复制程序:

import datetime, pytz, sqlalchemy
from sqlalchemy import create_engine, Column, Integer, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()

Session = sessionmaker(bind=engine)
session = Session()

class Example(Base):
    __tablename__ = "example"
    id = Column(Integer, primary_key=True)
    date = Column(DateTime(timezone=True))

    def __init__(self, date):
        self.date = date

Base.metadata.create_all(engine)

aucklandtz = pytz.timezone('Pacific/Auckland')
exdatetime = datetime.datetime(2011,8,8,2,23)

print aucklandtz, exdatetime

# inject TZ to exdatetime:
injdatetime = aucklandtz.localize(exdatetime)

print injdatetime

newrecord = Example(injdatetime)
print newrecord.date
session.add(newrecord)
session.commit()
print newrecord.date

从控制台输出来看,主要的事情是它将记录作为值'2011-08-08 02:23:00.000000'插入到SQLite中。在

有没有一种简单的方法来解决这个问题,或者我需要将TZ信息添加到一个单独的列中/将所有内容都存储为时间戳并在格式之间进行转换?在


Tags: fromimporttruedatetimedatesqlalchemycreatecolumn
2条回答

Python的strptime方法不支持%z格式化指令,因此无法从数据库中的字符串中获取时区。我想这就是为什么它没有被存储。在

你有两个选择。您已经在另一列中提到了一个存储时区。在

然而,对于这个问题,一般建议的解决方案是不同的。不要在Python或数据库中使用datetime存储时区,而是在从用户接收到所有datetime立即转换为UTC,并且只在内部处理UTC。稍后,当您必须向用户显示结果时,请将其转换为正确的时区。在

这就把实际时间和你不能依赖的东西区分开来。如果你的程序的用户从奥克兰搬到日本,或者新西兰政府改变了时区怎么办?在

有一篇由阿明·罗纳彻写的很好的博客文章,题目是““Eppur si muove!”* – Dealing with Timezones in Python”。它基本上是这样说的:

  1. 在内部总是使用偏移量NaiveDateTime对象并考虑 他们是UTC。在
  2. 与用户交互时,在本地和本地之间进行转换 时间。在

相关问题 更多 >