postgres的时间转换
天下苦postgres時(shí)間轉(zhuǎn)換久已!
最近在操作數(shù)據(jù)庫(kù)時(shí),遇到頻繁的時(shí)間操作,每次弄完了就忘了,今天痛定思痛,下定決心(終于自己也受不了自己的lazy了)對(duì)postgres的時(shí)間操作進(jìn)行一下總結(jié)。本文竟可能詳盡的記錄postgres中涉及到date、timestamp以及和字符串之間的轉(zhuǎn)換進(jìn)行說(shuō)明。
1.utc對(duì)timestamp的轉(zhuǎn)換
在postgres中沒(méi)有utc這個(gè)概念,為什么?這個(gè)問(wèn)題沒(méi)有深入的調(diào)研,沒(méi)有什么我們不關(guān)心,但是與之對(duì)應(yīng)的有一個(gè)概念——epoch,其意思為新紀(jì)元,新時(shí)代,怎么定義的新呢,計(jì)算機(jī)上面就是指1970-01-01 00:00:00之后的時(shí)間,有人會(huì)說(shuō)這不就是utc嗎,好吧,我承認(rèn)買(mǎi)了個(gè)關(guān)子,但是有助于記憶。
postgres中的時(shí)間可以精確到小數(shù)點(diǎn)后五位,也就是10微秒的單位,已經(jīng)很小了,我們先來(lái)感受一下在pg中獲取epoch:
--把時(shí)間戳轉(zhuǎn)成epoch值 postgres=# select extract(epoch from now()); date_part --- 1533803404.49598 (1 row)上面是將當(dāng)前時(shí)間戳轉(zhuǎn)化為epoch,轉(zhuǎn)換的過(guò)程中主要用到extract函數(shù),
--將具體時(shí)間戳轉(zhuǎn)換為utc select extract(epoch from timestamp without time zone '1970-01-01 01:00:00');date_part -----------3600 (1 row) --根據(jù)具體時(shí)間進(jìn)行計(jì)算,一個(gè)小時(shí)的utc select extract(epoch from interval '+1 hours');date_part -----------3600 (1 row) --同上 select extract(epoch from interval '-1 hours');date_part ------------3600 (1 row)下面是將epoch值也就是utc值,轉(zhuǎn)換為時(shí)間戳,如下:
--把epoch 值轉(zhuǎn)換回時(shí)間戳 postgres=# SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 1447898857.74524 * INTERVAL '1 second'; ?column? --- 2015-11-19 10:07:37.74524+08其他都很好理解,這里有一點(diǎn)需要注意,就是with time zone,字面意思很好理解,就是帶時(shí)區(qū),如果不帶時(shí)區(qū)怎么表示?對(duì)了就是without time zone,我們將上面語(yǔ)句進(jìn)行不帶時(shí)區(qū)的運(yùn)行,如下:
SELECT TIMESTAMP WITHout TIME ZONE 'epoch' + 1447898857 * INTERVAL '1 second'; --- 2015-11-19 02:07:37整整相差了8個(gè)小時(shí),不賣(mài)關(guān)子,其主要區(qū)別如下:
沒(méi)有時(shí)區(qū)代表的是絕對(duì)時(shí)間,absolute timestamp,即 UTC (UTC+0) 時(shí)間。
帶著時(shí)區(qū)的代表相對(duì)時(shí)間,relative timestamp,即當(dāng)?shù)貢r(shí)間,如北京的當(dāng)?shù)貢r(shí)間是 UTC+8 的時(shí)間。
使用的一個(gè)最佳實(shí)踐是時(shí)間類型都設(shè)為 timestamp with time zone 類型,只有在根據(jù) timestamp 進(jìn)行 partition 時(shí)才使用 timestamp without time zone 類型,因?yàn)?partition 必須使用 immutable 數(shù)據(jù) (即在任何情況下數(shù)據(jù)取出來(lái)都一樣),而 timestamp with time zone 的數(shù)據(jù)值與 postgres 配置的 timezone 有關(guān)。
這兩種數(shù)據(jù)類型的區(qū)別是:
- 以當(dāng)?shù)貢r(shí)間存儲(chǔ)數(shù)據(jù)到 timestamp with time zone 類型的字段時(shí),postgres 底層會(huì)以 UTC 時(shí)間存儲(chǔ),展示數(shù)據(jù)時(shí)會(huì)根據(jù) postgres 設(shè)置的 timezone 顯示為當(dāng)時(shí)時(shí)間。
- 以當(dāng)?shù)貢r(shí)間存儲(chǔ)數(shù)據(jù)到 timestamp without time zone 類型的字段時(shí),postgres 底層以輸入的數(shù)據(jù)進(jìn)行存儲(chǔ),展示時(shí)會(huì)原樣展示,與 postgres 設(shè)置的時(shí)區(qū)無(wú)關(guān)。
查看當(dāng)前時(shí)間戳
下面這是查看當(dāng)前時(shí)間戳的幾種方式,如下:
--查看當(dāng)前的時(shí)間戳,還有函數(shù)now()postgres=# select clock_timestamp(),current_timestamp,localtimestamp;clock_timestamp | now | timestamp -------------------------------+-------------------------------+----------------------------2016-02-02 17:54:15.547194+08 | 2016-02-02 17:54:15.546956+08 | 2016-02-02 17:54:15.546956clock_timestamp和current_timestamp都有時(shí)區(qū)信息,而localtimestamp沒(méi)有時(shí)區(qū)信息
時(shí)間戳加減
--時(shí)間加減 postgres=# select date '2016-02-02 10:00:00'+ interval '10 minutes'; ?column? ---2016-02-02 00:10:00時(shí)間戳格式轉(zhuǎn)化
將時(shí)間戳根據(jù)具體格式轉(zhuǎn)換為字符串:
SELECT to_char((TIMESTAMP WITH TIME ZONE'epoch' + 1447898857 * INTERVAL '1 second' ),'yyyy-MM');2015-11時(shí)間段內(nèi)的隨機(jī)時(shí)間
--直接用sql生成隨機(jī)日期時(shí)間select '2015-5-1'::date + trunc(random()*100)::integer +' 00:22:22'::time + (trunc(random()*3600*24)||' second')::interval;random()生成一個(gè)0到1的隨機(jī)數(shù),trunc()對(duì)生成隨機(jī)數(shù)進(jìn)行截取,剩下的參考時(shí)間戳加減過(guò)程的相關(guān)做法。
--創(chuàng)建隨機(jī)日期時(shí)間函數(shù) CREATE OR REPLACE FUNCTION rand_date_time(start_date date, end_date date) RETURNS TIMESTAMP AS BODY DECLARE interval_days integer; random_seconds integer; random_dates integer; random_date date; random_time time; BEGIN interval_days := end_date - start_date; random_dates:= trunc(random()*interval_days);random_date := start_date + random_dates; random_seconds:= trunc(random()*3600*24); random_time:=' 00:00:00'::time+(random_seconds || ' second')::INTERVAL;RETURN random_date +random_time; END; BODY LANGUAGE plpgsql; --生成指定時(shí)間內(nèi)的隨機(jī)時(shí)間 SELECT rand_date_time('2000-01-01', '2013-12-31');不同時(shí)區(qū)日期轉(zhuǎn)化
--不同時(shí)區(qū)之間的轉(zhuǎn)換,pst美國(guó)太平洋標(biāo)準(zhǔn)時(shí)間postgres=# select '2016-02-03 09:07:30.816885+08' at time zone 'pst'; timezone ---2016-02-02 17:07:30.816885 (1 row) --cct中國(guó)沿海時(shí)間 postgres=# select '2016-02-03 09:07:30.816885+08' at time zone 'cct'; timezone ---2016-02-03 09:07:30.816885 (1 row) --將西五區(qū)轉(zhuǎn)到東八區(qū) postgres=# SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'cct';timezone ---2001-02-17 09:38:40系統(tǒng)時(shí)區(qū)查看
--查看系統(tǒng)支持的時(shí)區(qū)select * from pg_timezone_names ;系統(tǒng)時(shí)區(qū)設(shè)置
--時(shí)區(qū)設(shè)置參數(shù) timezone = 'PRC' --修改時(shí)區(qū)的方法1. 全局參數(shù)postgresql.conftimezone='UTC' 2. 數(shù)據(jù)庫(kù)級(jí)配置alter database dbname set timezone='UTC';pipeline=# select * from pg_db_role_setting ;setdatabase | setrole | setconfig -------------+---------+--------------------------------------14930 | 0 | {TimeZone=UTC}3. 用戶級(jí)配置alter role rolname set timezone='UTC';或者alter role all set timezone='UTC';pipeline=# select * from pg_db_role_setting ;setdatabase | setrole | setconfig -------------+---------+--------------------------------------14930 | 0 | {TimeZone=UTC}0 | 0 | {TimeZone=UTC}執(zhí)行休眠時(shí)間設(shè)置
--休眠1.5秒后執(zhí)行,單位秒 SELECT clock_timestamp(),pg_sleep(1.5),clock_timestamp();--休眠5分鐘,單位interval SELECT clock_timestamp(),pg_sleep_for('5 minutes'),clock_timestamp();--到指定時(shí)間執(zhí)行,注意這些休眠時(shí)間不是完全精確的 SELECT clock_timestamp(),pg_sleep_until('today 10:00'),clock_timestamp();字符串到時(shí)間戳和日期
主要涉及到的函數(shù)為todate和toTimestamp,示例如下:
select to_date('2018-03-12 18:47:35','yyyy-MM-dd hh24:mi:ss') --轉(zhuǎn)化為日期 2018-03-12 --對(duì)日期進(jìn)行比較,輸出booleanselect current_timestamp <= to_date('2018-03-12 18:47:35','yyyy-MM-dd hh24:mi:ss') f select current_timestamp <= to_timestamp('2018-03-12 18:47:35','yyyy-MM-dd hh24:mi:ss') flag; select to_timestamp('2018-03-12 18:47:35','yyyy-MM-dd hh24:mi:ss') --- f 2018-03-12 18:47:35+08從上面比較可以看出,date和timestamp的主要區(qū)別,需要特別說(shuō)明的一點(diǎn)是,在指定日期的格式的時(shí)候,特別注意時(shí)分秒的格式指定問(wèn)題(使用慣了java的格式,用這個(gè)會(huì)有點(diǎn)不習(xí)慣)。
總結(jié)
以上是生活随笔為你收集整理的postgres的时间转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MAC 安装使用 MAMP
- 下一篇: Typora的使用【保姆级教学】