2012-01-06 29 views
1

使用時區,這個問題是不清楚最初發布,所以我完全重寫它:指定爲基於前兩個答案的參考時區

以下問題與如何只關注以及存儲了什麼數據,並且在檢索時沒有關於轉換數據的形式或形式。因此,將SELECT轉換爲所需的時區不是一個合適的答案。

將值插入帶時區字段的時間戳時,會將其檢索到(因此可能存儲),並將時間戳轉換爲數據庫插入時的本地時區。

也就是說,插入爲2012-01-01 00:00:00+00:00的時間戳被檢索爲2011-12-31 19:00:00-05,其中插入時數據庫的本地時區爲-05。在數據庫爲-04的夏令時期間插入的時間戳使用-04時區返回。

我想要的是所有時間戳在存儲時使用任意時區(因此所有時間戳都不需要進行任何額外的工作,因爲具有該時區)。也就是說,圍繞地球運行的服務器,所有時間將在+00:00(任意時區),而不是-12:00+12:00

我可以插入帶有時區列的時間戳嗎,以便所有時間戳都相對於任意時區存儲嗎?如果是這樣,怎麼樣?


原來如下。

將值插入到timestamp with time zone字段中時,它將轉換爲服務器的當前時區。

示例:如果我插入一個指定時區-1的值,則檢索它將返回-5(服務器插入時的時區)的時間。

是否可以指定它應該使用任意時區進行存儲?

注意:這個問題不是如何將返回的時間轉換爲另一個時區,這是特定於如何存儲時間。

回答

1

你必須保存時區除了timestamp偏移。

正如@Milen已經解釋過的(並鏈接到manual):一個timestamp只保存一個時間點(作爲抽象值)。時區修改器是不是已保存,它只用於調整timestamp相對於UTC

考慮以下演示:

-- DROP TABLE tbl; 
CREATE TEMP TABLE tbl (id int, myts timestamptz, mytz interval); 

INSERT INTO tbl VALUES 
(1, now()    , EXTRACT (timezone from now()) * interval '1s') 
,(2, '2012-01-01 00:00-05', interval '-5h') 
,(3, '2012-01-01 00:00+04', interval '4h') 
,(4, '2012-11-11 20:30+03', interval '3h'); 

SELECT * 
     ,(myts AT TIME ZONE mytz)::text 
     || CASE WHEN mytz > '0:0' THEN '+' ELSE '' END 
     || to_char(mytz, 'FMHH24:mi') AS timestamp_at_origin 
FROM tbl; 

在本地運行它看到的。請特別注意AT TIME ZONE構造的細節,以及如何從(本地!)timestamp with time zone中提取時區。
now()返回timestamp with time zonetimestamptz簡稱。

EXTRACT (timezone from now()) * interval '1s' 

timestamp_at_origin在原點處顯示帶時區的時間戳。如果我理解你的問題,那麼你就是在尋找。
您可以進一步改進格式。

你可能會對這related question感興趣,它揭示了時區的含糊性和陷阱。

0

你可以做你的選擇與at time zone操作:

select insertTs at time zone 'CST' from table 

查看更多here

1

將值插入timestamp with time zone字段時,實際發生的是時間戳轉換爲UTC。另一個問題是在輸出時轉換成什麼時區。有控制這幾個方面:

當與時區值的時間戳輸出,它始終是 從UTC轉換成當前時區區域,顯示在該區域 本地時間。要查看其他時區的時間,可以使用 更改時區或使用AT TIME ZONE結構(請參閱Section 9.9.3)。

0

我總是以GMT格式存儲時間,以便客戶端可以根據當前的GMT偏移量進行轉換(格林威治標準時間格式在大多數語言中都可用)。

我寫C# - 所以我可以很容易地將所有DateTime對象轉換爲GMT,使用DateTime.ToUniversalTime()作爲我將數據存儲在數據庫中。

我不確定你使用的是什麼語言,或者如何將所有時間都轉換爲格林尼治標準時間,但從邏輯的角度來看 - 在格林尼治標準時間存儲所有時間將允許一個統一的時區,所有其他時區可以很容易地與。

希望這會有所幫助!

Greenwich Mean Time