使用日期时间列写入和读取行时获取不同的时区?
Get different timezones when writing and reading row with datetime column?
为什么我在写入和读取带有日期时间列的行时得到不同的时区?
我有下一个tableTests
:
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 格式存储感知日期时间 table。
我正在向 table 添加一个新行。测试对象具有感知日期时间。
session.add(Test(datetime.utcnow().replace(tzinfo=pytz.UTC)))
session.commit()
session.close()
psql select 命令输出:
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)
我们看到数据时间列被错误地写入数据库(时区偏移 +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)
我的数据库有一个时区:“Europe/Moscow”。
有一个假设:有可能在写入数据库时,将日期时间保存为 naive。 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 也 returns 本地时区的值
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
为什么我在写入和读取带有日期时间列的行时得到不同的时区?
我有下一个tableTests
:
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 格式存储感知日期时间 table。 我正在向 table 添加一个新行。测试对象具有感知日期时间。
session.add(Test(datetime.utcnow().replace(tzinfo=pytz.UTC)))
session.commit()
session.close()
psql select 命令输出:
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)
我们看到数据时间列被错误地写入数据库(时区偏移 +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)
我的数据库有一个时区:“Europe/Moscow”。 有一个假设:有可能在写入数据库时,将日期时间保存为 naive。 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 也 returns 本地时区的值
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