PostgreSQL timestamp踩坑記錄與填坑指南
項(xiàng)目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()
})
不同時(shí)區(qū)to_timestamp查詢結(jié)果
測試輸入數(shù)據(jù)為1514736000(UTC時(shí)間2017-12-31 16:00:00,北京時(shí)間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官方文檔對(duì)timestamp的一個(gè)描述
詳見: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進(jìn)行時(shí)間轉(zhuǎn)換且DB時(shí)區(qū)非UTC時(shí),寫入**timestamp without time zone**類型的COLUMN則會(huì)與預(yù)期結(jié)果不符。
不同Timezone/columnType查詢結(jié)果
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ù)以上結(jié)果可判定:
使用pg查詢**timestamp without time zone**類型的COLUMN時(shí),會(huì)將數(shù)據(jù)庫存儲(chǔ)的時(shí)間當(dāng)做北京時(shí)間而非UTC時(shí)間,與數(shù)據(jù)庫時(shí)區(qū)沒有關(guān)系。
總結(jié)
網(wǎng)上類似問題的解決辦法是將DB時(shí)區(qū)改為UTC+08。
原理:寫入DB的時(shí)間實(shí)際為北京時(shí)間,pg庫恰好是當(dāng)做北京時(shí)間讀取,所以時(shí)間戳就不會(huì)出問題了。
假如應(yīng)用部署在不同的地域,使用timestamp without time zone存儲(chǔ)timestamp這樣的設(shè)計(jì)簡直是災(zāi)難。
不要用timestamp without time zone存儲(chǔ)timestamp!
不要用timestamp without time zone存儲(chǔ)timestamp!
不要用timestamp without time zone存儲(chǔ)timestamp!
補(bǔ)充:pg查詢時(shí)間間隔(timestamp類型)
create_date timestamp(6) without time zone

1.從2015-10-12到2015-10-13 之間的4點(diǎn)到9點(diǎn)的數(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;
結(jié)果:

2.2015-10-12五點(diǎn)的數(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')
結(jié)果:

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
在PostgreSQL中實(shí)現(xiàn)跨數(shù)據(jù)庫的關(guān)聯(lián)查詢
在 PostgreSQL 中,通常情況下的關(guān)聯(lián)查詢是在同一個(gè)數(shù)據(jù)庫的不同表之間進(jìn)行的,然而,在某些復(fù)雜的應(yīng)用場景中,可能需要實(shí)現(xiàn)跨數(shù)據(jù)庫的關(guān)聯(lián)查詢,本文將詳細(xì)探討如何在 PostgreSQL 中實(shí)現(xiàn)這一需求,并通過示例代碼進(jìn)行說明,需要的朋友可以參考下2024-08-08
postgresql 中的COALESCE()函數(shù)使用小技巧
這篇文章主要介紹了postgresql 中的COALESCE()函數(shù)使用小技巧,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
PostgreSQL時(shí)間線(timeline)和History File的用法
這篇文章主要介紹了PostgreSQL時(shí)間線(timeline)和History File的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Postgresql數(shù)據(jù)庫之創(chuàng)建和修改序列的操作
這篇文章主要介紹了Postgresql數(shù)據(jù)庫之創(chuàng)建和修改序列的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Postgresql的pl/pgql使用操作--將多條執(zhí)行語句作為一個(gè)事務(wù)
這篇文章主要介紹了Postgresql的pl/pgql使用操作--將多條執(zhí)行語句作為一個(gè)事務(wù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01
關(guān)于PostgreSql數(shù)據(jù)庫與mysql數(shù)據(jù)庫的不同點(diǎn)以及注意事項(xiàng)
PostgreSQL和MySQL是兩種流行的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),它們都可以用來存儲(chǔ)和管理數(shù)據(jù),但是它們?cè)谀承┓矫嬗兴煌?下面這篇文章主要給大家介紹了關(guān)于PostgreSql數(shù)據(jù)庫與mysql數(shù)據(jù)庫的不同點(diǎn)以及注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2023-05-05
關(guān)于PostgreSQL截取某個(gè)字段中的部分內(nèi)容進(jìn)行排序的問題
這篇文章主要介紹了PostgreSQL截取某個(gè)字段中的部分內(nèi)容進(jìn)行排序,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
PostgreSQL數(shù)據(jù)庫遷移部署實(shí)戰(zhàn)教程
這篇文章主要介紹了PostgreSQL數(shù)據(jù)庫遷移部署實(shí)戰(zhàn)教程,由于項(xiàng)目本身就是基于PostgreSQL數(shù)據(jù)庫構(gòu)建的,因此數(shù)據(jù)庫遷移將變得十分便捷,接下來,我將簡要介紹我們的遷移步驟,需要的朋友可以參考下2023-07-07

