如何使用psycopg2比较日期(PostgreSQL)?

0 投票
2 回答
4351 浏览
提问于 2025-04-18 05:24

我想用PostgreSQL的Python模块psycopg2来查找一些数据行,这些行的结束时间在某个时间戳之前。我尝试通过执行一个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年5月1日13:00 UTC,这和我预期的结果不一样。

那么,在psycopg2中,正确的时间选择方式应该是什么呢?

2 个回答

0

指定时间应该以哪个时区来显示。如果start_timeend_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
2

好的,使用带时区的PostgreSQL时间戳解决了问题。

下面是问题的详细情况:

  • 我把带时区的时间戳放在了不带时区的列里。我以为timestamp without time zone列会存储UTC时间(就像timestamp with time zone一样),但实际上它存的是本地时间的时间戳,正如文档中所描述的:

    在没有时区的时间戳和带时区的时间戳之间进行转换时,通常假设没有时区的时间戳值应该被视为本地时间。如果需要转换,可以使用AT TIME ZONE指定不同的时区。

    因此,在中国,00:00 UTC会被存储为08:00timestamp without time zone这一列中。

  • 当进行比较时,比如“没有时区的时间戳”<“带时区的时间戳”,我在文档中找不到PostgreSQL是怎么处理的。不过,问题中观察到的情况和这样的想法是一致的:首先去掉时区,然后比较没有时区的时间戳。我不应该对结果感到惊讶:在中国,晚上的“15:00”确实是比13:00 UTC要的(中国是UTC+8)。关键是要知道显示(和存储)的时间是本地时区的。

我从中得到的教训是:在带时区和不带时区的时间戳之间的转换最好是明确处理

撰写回答