通过使用PostgreSQL Python模块psycopg2,我想找到一些结束时间落在某个时间戳之前的行。我尝试使用带有cursor.execute(…)
的SQL查询的… where end_time < %s
执行此操作,其中%s替换为带有时区的datetime.datetime
对象。 psycopg2生成的SQL是:
select * from my_table where end_time < '2014-05-01T13:00:00+00:00'::timestamptz;
返回如下行:
id | start_time | end_time
331 | 2014-05-01 14:55:00 | 2014-05-01 15:05:00
结束时间不早于2014-05-01 at 13:00 UTC,与我的预期相反。
在psycopg2中执行所需时间选择的正确方法是什么?
答案 0 :(得分:2)
好的,在表中使用PostgreSQL时间戳和时区解决了这个问题。
以下是问题所在的详细信息:
我将时区感知时间戳放在不支持时区的列中。我假设timestamp without time zone
列包含 UTC 时间(例如timestamp with time zone
),但它实际上包含本地中的时间戳时间,如documentation:
没有时区的时间戳和时间戳之间的转换 时区通常假设时间戳没有时区值 应当作为当地时间的时区采取或给出。不同的时区 可以使用AT TIME ZONE指定转换。
因此,在中国时,00:00 UTC将08:00
存储在timestamp without time zone
列中。
执行比较时,如#34;时间戳,不带时区&#34; &LT; &#34; timestamp with time zone&#34;,我无法在文档中找到PostgreSQL的功能。然而,在该问题中观察到的结果与首先以相同方式移除时区的想法一致,并且比较了没有时区的时间戳。我不应该对结果感到惊讶:迟到的时间&#34; 15:00&#34;确实早于而不是13:00 UTC,在中国(UTC + 8)。关键是要知道显示(和存储)时间是在当地时区。
我从中得到的道德是:有时区和无时区的时间戳之间的转换可以更好地处理显式 。
答案 1 :(得分:0)
指定应显示时间的时区。如果start_time
和end_time
是时间戳没有时区,那么您还需要告诉postgresql他们应该在哪个时区
select
id,
start_time at time zone 'UTC' at time zone 'UTC',
end_time at time zone 'UTC' at time zone 'UTC'
from my_table
where end_time at time zone 'UTC' < %s