在写入和读取带有datetime列的行时获得不同的时区



为什么在写入和读取带有datetime列的行时会得到不同的时区

我有下一张表Tests:

class Test(Base):
__tablename__ = 'tests'
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True)
test_datetime = Column(DateTime(timezone=True), nullable=False, default=datetime.utcnow())
def __init__(self, test_datetime):
self.test_datetime = test_datetime
def __repr__(self):
return f'<Test(id={self.id}, test_datetime={self.test_datetime})'

我决定将utc中的感知日期时间存储在数据库和测试表中。我正在执行向表中添加新行的操作。测试对象具有感知日期时间。

session.add(Test(datetime.utcnow().replace(tzinfo=pytz.UTC)))
session.commit()
session.close()

psql选择命令输出:

database_name=# select * from tests;                                                                                                                      id                  |        test_datetime
--------------------------------------+-----------------------------
751bcef0-2ef4-4c0f-960c-a40ca2b8ec94 | 2021-04-12 14:46:30.8957+03
(1 row)
database_name=# SHOW timezone ;
TimeZone
---------------
Europe/Moscow
(1 row)
database_name=# d tests
Table "public.tests"
Column     |           Type           | Collation | Nullable | Default
---------------+--------------------------+-----------+----------+---------
id            | uuid                     |           | not null |
test_datetime | timestamp with time zone |           | not null |
Indexes:
"tests_pkey" PRIMARY KEY, btree (id)

我们看到datatime列被错误地写入数据库(时区偏移量+3小时到位置+0(。

正如预期的那样,从数据库中读取数据,我得到了一个不同的时区(+3h(

query = session.query(Test)
for test in query.order_by(Test.test_datetime.asc()).all():
print(test.test_datetime, test.test_datetime.tzinfo)

Python输出:

2021-04-12 14:46:30.895700+03:00 psycopg2.tz.FixedOffsetTimezone(offset=180, name=None)

我的数据库有一个时区:";欧洲/莫斯科";。有一种假设:在写入数据库时,可能会将日期时间保存为幼稚。test_datetime列中的所有对象都从数据库中获取时区(偏移量(。但我不确定它是否像那样工作。

PostgreSQL将timestamp with time zone值存储为UTC,默认情况下将其显示在本地时区。所以,如果我通过psql插入一个UTC值…

mydb=# insert into tests (id, test_datetime) values (1, '2021-04-12 11:46:30.8957+00');
INSERT 0 1

…然后取回…

mydb=# select * from tests;
id |        test_datetime        
----+-----------------------------
1 | 2021-04-12 05:46:30.8957-06
(1 row)

…它显示在我的本地时区(当前为UTC-6(。psycopg2还返回本地时区中的值

with engine.begin() as conn:
result = conn.execute(
sa.text("SELECT test_datetime FROM tests WHERE id=1")
).scalar()
print(type(result))  # <class 'datetime.datetime'>
print(result)  # 2021-04-12 05:46:30.895700-06:00

如果您希望时区感知datetime值以UTC为单位,则只需将其转换为

result_utc = result.astimezone(timezone.utc)
print(result_utc)  # 2021-04-12 11:46:30.895700+00:00

最新更新