首页 > 解决方案 > fetchall 方法将 Postgresql timestamptz 字段转换为不同的时区

问题描述

第一个问题在这里,所以让我知道是否需要更多信息。我正在使用 Pythonpsycopg2-binary==2.7.7包试图将 PostgreSQL 9.6.11 timestamptz 字段从数据库中提取出来。

话虽如此,“psycopg2”包似乎将时间戳记日期时间强制到与数据库中存在的不同时区。

例如,如果在 PostgreSQL 客户端中运行,以下查询将返回正确的偏移量:

SQL

SELECT row_to_json(t)
FROM (
    SELECT '2019-01-24T08:24:00-05:00'::timestamptz AS tz 
)t;

结果

{"tz":"2019-01-24 08:24:00-05"}

但是,如果我通过该方法运行相同的查询psycopg2.cursor.fetchall,我得到的偏移量与预期/返回的不同:

import time
import psycopg2
import logging

logger = logging.getLogger()


def getRows(query, printRows=False, **kwargs):
    try:
        cs = "dbname={dbname} user={dbuser} password={dbpass} host={server} port={port}".format(
            **kwargs)
        con = psycopg2.connect(cs)
        con.set_session(readonly=True, autocommit=True)
    except Exception:
        logger.exception("-->>>>Something went wrong connecting to db")
        return None

    end = None

    try:
        start = time.time()
        cur = con.cursor()
        cur.execute(query)

        rows = cur.fetchall()
        if printRows:
            for i in rows:
                print(i)

        cur.close()
        con.commit()
        con.close()
        end = time.time()
        logger.info(
            "-->>>>Query took {} seconds...".format(round(end - start, 2)))
        return rows
    except Exception:
        end = time.time()
        cur.close()
        con.commit()
        con.close()
        logger.exception("-->>>>Something went wrong with the query...")
        logger.info(
            "-->>>>Query took {} seconds...".format(round(end - start, 2)))


if __name__ == '__main__':
    test = getRows("""SELECT row_to_json(t) AS "result" 
                      FROM(
                      SELECT '2019-01-24T08:24:00-05:00'::timestamptz AS tz
                      )t;
                   """, printRows=True, **DBSECRETS)
    print(test[0][0]) 

结果

{'tz': '2019-01-24T05:24:00-08:00'}

如上所示,-5PostgreSQL 的 EST 时区(偏移量)正在-08:00通过psycopg2包转换为偏移量。

我检查了psycopg2文档,但找不到任何确凿的例子来解决这个问题。具体来说,我在这里检查过:

http://initd.org/psycopg/docs/cursor.html#cursor.tzinfo_factory

标签: python-3.xpsycopg2postgresql-9.6

解决方案


事实证明,SQL 客户端 Dbeaver 将时间戳强制转换为本地操作系统时区,在本例中为 EST。

如何更改 DBeaver 时区/如何阻止 DBeaver 转换日期和时间

但是,PostgreSQL 服务器具有太平洋时间或 PST 的本地时区。因此,psycopg2包根据服务器正确解释了时间戳,即 PST。


推荐阅读