搭建兩個虛擬環境,操作系統均是cents7。
環境A:
使用timedatectl命令查看時區為 Time zone: Asia/Shanghai (CST, +0800)。
本地數據庫時區(show timezone命令)為PRC,等價於cst。
環境B:
時區為America/New_York (EST, -0500),本地數據庫時區為US/Eastern,等價於EST。
1. 先針對timestamp with time zone和timestamp without time zone兩個配置進行測試。
在環境A的數據庫建立數據表並寫入數據:
CREAT TABLE test_timestamp( ttz timestamp with time zone, twtz timestamp without time zone );
INSERT INTO test_timestamp VALUES (now(),now());
查看數據:
postgres=# table test_timestamp; ttz | twtz -------------------------------+---------------------------- 2019-02-15 11:28:26.994804+08 | 2019-02-15 11:28:26.994804 (1 row)
在環境B中,使用python查看:
>>> data = pd.read_sql(''' select * from test_timestamp ''', conn) >>> data ttz twtz 0 2019-02-15 03:28:26.994804+00:00 2019-02-15 11:28:26.994804 >>>
會發現ttz字段自動轉換成了UTC時間,而twtz字段原封不動的輸出。
再測試環境B寫入數據:
本地時間為:$ date Thu Feb 14 22:33:42 EST 2019 執行cur.execute(''' insert into test_timestamp values('2019-02-14 22:33:42','2019-02-14 22:33:42') ''')
在A的數據庫中查看:
postgres=# table test_timestamp; ttz | twtz -------------------------------+---------------------------- 2019-02-15 11:28:26.994804+08 | 2019-02-15 11:28:26.994804 2019-02-14 22:33:42+08 | 2019-02-14 22:33:42 (2 rows)
發現ttz字段日期值加上了環境A的時區,出現了偏差。因為插入語句用的是字符串類型,是的數據庫默認為本地時區。
寫入數據時如果調用sql函數:
cur.execute(''' insert into test_timestamp values(now(),now()) ''')
在環境A中:
postgres=# table test_timestamp; ttz | twtz -------------------------------+---------------------------- 2019-02-15 11:28:26.994804+08 | 2019-02-15 11:28:26.994804 2019-02-14 22:33:42+08 | 2019-02-14 22:33:42 2019-02-15 11:41:13.080922+08 | 2019-02-15 11:41:13.080922 (3 rows)
插入的也是環境A的本地時間。也就是說,最后都是以數據庫的環境來執行。
結論:
A. 同一時區內,沒有差別。跨時區時,如果只是跨時區讀(寫操作由一個特定時區完成),可以看成是無差別,都需要轉換一下,設置成with time zone可能會好一些,因為在讀取的時候有些工具或語言(比如java)會自動轉成當地時區的時間。如果是跨時區寫,那么就要設置成without time zone,要不然數據庫記錄的時間會有錯誤,因為寫的時候傳的是字符串,數據庫會加上本地時區。
B. 不同數據庫時間類型的名稱不一樣,postgres里面沒有datetime類型,用timestamp表示datetime;在mysql里有datetime類型,也有timestamp類型(含義和postgres里面不一樣)。表示的范圍大小、是不是帶有時區信息也要查看具體數據庫的手冊。
C. postgres日期類型一般都是“YYYY-MM-DD HH:mm:ss”格式,不接受一般理解上的數字類型的時間戳(int型數值)的輸入。時間類型(比如updatetime和tradedate等)的設置不一定得是數值格式,也可以是日期格式,只是需要注意好時區問題。