簡體   English   中英

postgresql JDBC驅動程序使用客戶端時區

[英]postgresql JDBC driver uses client time zone

我正在使用postgresql-42.2.2.jar jdbc驅動程序和postgresql 9.6服務器。

如何配置連接以使用服務器時區而不是客戶端時區?

查詢:

select id, TO_TIMESTAMP(tbl.ended_time / 1000)
FROM tbl
where TO_TIMESTAMP(tbl.ended_time / 1000) >= now()::date + interval '1m'

使用pgadmin運行查詢我得到以下結果(正確)

"2185"  "2018-06-22 00:02:02-05"
"2186"  "2018-06-22 00:03:01-05"
"2187"  "2018-06-22 00:13:02-05"

但是使用JDBC驅動程序運行相同的查詢,結果是:

2169 2018-06-22 07:13:01.0
2181 2018-06-22 08:33:02.0
2180 2018-06-22 08:23:01.0
2185 2018-06-22 09:02:02.0
2186 2018-06-22 09:03:01.0
2187 2018-06-22 09:13:02.0

如果沒有使用pgadmin運行的查詢,結果將是:

"2169"  "2018-06-21 22:13:01-05"
"2181"  "2018-06-21 23:33:02-05"
"2180"  "2018-06-21 23:23:01-05"
"2185"  "2018-06-22 00:02:02-05"
"2186"  "2018-06-22 00:03:01-05"
"2187"  "2018-06-22 00:13:02-05"

這是代碼:

static String URL = "jdbc:postgresql://some_ip:7000/db";
static String USERNAME = "test";
static String PASSWORD = "test";
static String JDBC_DRIVER = "org.postgresql.Driver";

public static void main(String[] args) {
    String query = "select id, TO_TIMESTAMP(tbl.ended_time / 1000) FROM tbl where TO_TIMESTAMP(tbl.ended_time / 1000) >= now()::date + interval '1m'";
    Connection conn = null;

    try {
        Class.forName(JDBC_DRIVER);
        conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        Statement st = conn.createStatement();          
        ResultSet rs = st.executeQuery(query);
        while (rs.next()) {             
            System.out.println(rs.getObject(1) + "--" + rs.getObject(2));
        }
        rs.close();
        st.close();
        conn.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 

}

正如解釋這里的JDBC驅動程序使用本地時區而不是服務器時區。

不幸的是,沒有簡單的方法可以更改該行為或查詢服務器的時區。

另請注意,使用OffsetDateTime檢索數據並沒有太大幫助:

rs.getObject(2, OffsetDateTime.class)

因為不幸的是,驅動程序返回了所有偏移量為0的 OffsetDateTime ,所以時區信息丟失了。

因此,最好的選擇似乎是對數據庫的時區進行硬編碼並使用Java計算時限,或者將時區分別存儲在數據庫中並進行查詢。

TL; DR:與JDBC驅動程序無關。 SQL有缺陷。

比較timestamp WITH time zone timestamp withOUT time zone timestamp WITH time zone timestamp withOUT time zone timestamp WITH time zone您會有什么期望? 您的SQL完全是錯誤的,因此會產生奇怪的結果。

您對now()::date有何期待? 注意:PostgreSQL文檔沒有說明now()將產生哪個時區。 它僅指定“時區將存在”,但是它甚至可以從一個PG版本更改為另一個PG版本。 因此,您基本上是在要求“隨機值”。

請闡明您要實現的目標,然后編寫適當的SQL。 例如,如果要獲取帶有時間戳的記錄“歐洲/柏林時區的當前日期的00:00:00之后”,則可以使用類似

where TO_TIMESTAMP(tbl.ended_time / 1000) >= ((now() at time zone 'Europe/Berlin')::date + interval '4m')::timestamp at time zone 'Europe/Berlin'

關鍵是沒有“一天的開始”,除非您指定要表示的時區。 pgjdbc填充使用默認時區的會話( TimeZone.getDefault()因此被隱式轉換使用,但是我強烈對比,從建議你withwithout時區同類SQL數據類型的,不管你用什么來執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM