PostgreSQL timestamp踩坑記錄與填坑指南
項目Timezone情況
NodeJS:UTC+08
PostgreSQL:UTC+00
timestampTest.js const { Client } = require('pg') const client = new Client() client.connect() let sql = `` client.query(sql, (err, res) => { console.log(err ? err.stack : res.rows[0].datetime) client.end() })
不同時區(qū)to_timestamp查詢結果
測試輸入數(shù)據(jù)為1514736000(UTC時間2017-12-31 16:00:00,北京時間2018-01-01 00:00:00)
1、timezone=UTC
BEGIN; SET TIME ZONE 'UTC'; SELECT to_timestamp(1514736000) as datetime; END;
直接查詢:2017-12-31 16:00:00+00YES
pg查詢:2017-12-31T16:00:00.000ZYES
2、timezone=PRC
BEGIN; SET TIME ZONE 'PRC'; SELECT to_timestamp(1514736000) as datetime; END;
直接查詢:2018-01-01 00:00:00+08NO
pg查詢:2017-12-31T16:00:00.000ZYES
PostgreSQL官方文檔對timestamp的一個描述
詳見:8.5.1.3. Time Stamps
In a literal that has been determined to be timestamp without time zone, PostgreSQL will silently ignore any time zone indication. That is, the resulting value is derived from the date/time fields in the input value, and is not adjusted for time zone.
坑
使用to_timestamp進行時間轉換且DB時區(qū)非UTC時,寫入**timestamp without time zone**類型的COLUMN則會與預期結果不符。
不同Timezone/columnType查詢結果
1、timezone=UTC,timestamp with timezone
BEGIN; SET TIME ZONE 'UTC'; SELECT TIMESTAMP WITH TIME ZONE '2017-12-31T16:00:00+00' as datetime; END;
直接查詢:2017-12-31 16:00:00+00YES
pg查詢:2017-12-31T16:00:00.000ZYES
2、timezone=UTC,timestamp without timezone
BEGIN; SET TIME ZONE 'UTC'; SELECT TIMESTAMP '2017-12-31T16:00:00+00' as datetime; END;
直接查詢:2017-12-31 16:00:00YES
pg查詢:2017-12-31T08:00:00.000ZNO
3、timezone=PRC,timestamp with timezone
BEGIN; SET TIME ZONE 'PRC'; SELECT TIMESTAMP WITH TIME ZONE '2017-12-31T16:00:00+00' as datetime; END;
直接查詢:2018-01-01 00:00:00+08YES
pg查詢:2017-12-31T16:00:00.000ZYES
4、timezone=PRC,timestamp without timezone
BEGIN; SET TIME ZONE 'PRC'; SELECT TIMESTAMP '2017-12-31T16:00:00+00' as datetime; END;
直接查詢:2017-12-31 16:00:00YES
pg查詢:2017-12-31T08:00:00.000ZNO
據(jù)以上結果可判定:
使用pg查詢**timestamp without time zone**類型的COLUMN時,會將數(shù)據(jù)庫存儲的時間當做北京時間而非UTC時間,與數(shù)據(jù)庫時區(qū)沒有關系。
總結
網(wǎng)上類似問題的解決辦法是將DB時區(qū)改為UTC+08。
原理:寫入DB的時間實際為北京時間,pg庫恰好是當做北京時間讀取,所以時間戳就不會出問題了。
假如應用部署在不同的地域,使用timestamp without time zone存儲timestamp這樣的設計簡直是災難。
不要用timestamp without time zone存儲timestamp!
不要用timestamp without time zone存儲timestamp!
不要用timestamp without time zone存儲timestamp!
補充:pg查詢時間間隔(timestamp類型)
create_date timestamp(6) without time zone
1.從2015-10-12到2015-10-13 之間的4點到9點的數(shù)據(jù)
select * from schedule where create_date between to_date('2015-10-12','yyyy-MM-dd') and to_date('2015-10-13','yyyy-MM-dd') and EXTRACT(hour from create_date) between 4 and 9;
結果:
2.2015-10-12五點的數(shù)據(jù)
select * from schedule where hospital_id='syzyyadmin' and date_trunc('hour',create_date)=to_timestamp('2015-10-12 05','YYYY-MM-DD HH24')
結果:
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。如有錯誤或未考慮完全的地方,望不吝賜教。
相關文章
PostgreSQL使用MySQL作為外部表(mysql_fdw)
PostgreSQL 提供了一種訪問和操作外部數(shù)據(jù)源的機制,稱為外部數(shù)據(jù)包裝器,本文主要給大家介紹了PostgreSQL使用MySQL作為外部表的方法,感興趣的朋友跟隨小編一起看看吧2022-11-11詳解PostgreSQL?14.4安裝使用及一些安裝的異常問題
這篇文章主要介紹了PostgreSQL?14.4的安裝以及使用以及一些安裝的異常,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07PostgreSQL教程(三):表的繼承和分區(qū)表詳解
這篇文章主要介紹了PostgreSQL教程(三):表的繼承和分區(qū)表詳解,本文講解了多表繼承、 繼承和權限、什么是分區(qū)表、分區(qū)表實現(xiàn)、分區(qū)和約束排除等內容,需要的朋友可以參考下2015-05-05PostgreSQL實現(xiàn)一個通用標簽系統(tǒng)
這篇文章主要給大家介紹了關于利用PostgreSQL實現(xiàn)一個通用標簽系統(tǒng)的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-01-01PostgreSQL中實現(xiàn)數(shù)據(jù)實時監(jiān)控和預警的步驟詳解
在 PostgreSQL 中實現(xiàn)數(shù)據(jù)的實時監(jiān)控和預警是確保數(shù)據(jù)庫性能和數(shù)據(jù)完整性的關鍵任務,以下將詳細討論如何實現(xiàn)此目標,并提供相應的解決方案和具體示例,需要的朋友可以參考下2024-07-07常用?PostgreSQL?預防數(shù)據(jù)丟失解決方案
這篇文章主要介紹了常用?PostgreSQL?預防數(shù)據(jù)丟失方案,本篇主要介紹關于?DDL?和?DML?操作,如何預防數(shù)據(jù)丟失的方案,需要的朋友可以參考下2022-01-01