2016-12-27 17 views
0

我確定標題可能會令人困惑。無法找到一種方法來在標題中很好地說出這一點,而不會使其長度爲非常長無論夏令時如何,只在UTC 2:00檢索時間戳(帶時區)行的SQL查詢

在短期

我有存檔外部API端點每15分鐘一個PSQL數據庫表。該表具有以下的列:

  • ID(串行)
  • 比賽(jsonb)
  • snapshot_time(時間戳和時區不爲空默認NOW())

我需要一個SQL只能在以下約束下獲取行的查詢:

  • 一天必須星期六(6)
  • 時間戳必須在'... T02:00:00Z'ISO8601
  • 在指定的開始和結束日期之間。

我現在有

SELECT id,snapshot_time,match->'kills' FROM match_archive 
WHERE extract(dow from snapshot_time)=6 
AND snapshot_time >= '2016-12-01' 
AND date_part('hour', snapshot_time)=2 
AND date_part('minute', snapshot_time)=00; 

(開始&結束時間,目前很難在例如編碼)

的問題

這將返回正確的行,但問題是自snapshot_time列以來的結果行是因爲我住在東部標準時間,所以timestamp with time zone型實際上是5個小時。

它返回一個例子行

id |   snapshot_time   |     ?column? 
--------+-------------------------------+-------------------------------------------- 
120941 | 2016-12-03 02:00:03.32946-05 | {"red": 3389, "blue": 1962, "green": 2911} 

正如你所看到的,snapshot_time確實是2:00,但它在美國東部時間。

我想,「嘿,我可以讓它的小時:21,星期幾:5(星期五)」,這樣就行得通了,但突然間由於夏令時將在一個小時後關閉。

其他的事情將使用timestamp without time zone來存儲信息,但會發生什麼,然後是它會採取2016-12-03T17:44:21-05,只是砍掉-05並把它作爲2016-12-03T17:44:21Z插入新行到數據庫時。

那麼,有沒有什麼好方法可以讓SQL查詢符合上面列出的要求而不必擔心夏令時?謝謝。

+0

雖然我意識到您可能沒有這個選項,但理解最佳做法是始終將UTC中的日期時間數據存儲在首位。如果這樣做了,這個問題就不會出現。即使是現在,如果我有選擇,我會認真研究將數據庫中的所有現有本地時區日期時間數據(以及從其驅動的代碼)轉換爲UTC。 –

+0

@CharlesBretana存儲UTC時區甚至不是PostgreSQL中的選擇。這就是它們的存儲方式。 –

+0

我沒說店時區,我說在UTC存儲日期倍。然而,我承認我不熟悉PostgreSQL。你是說你無法控制你存儲在PostGreSQL表的日期時間列中的值嗎?客戶端軟件無法存儲UTC值而不是本地時間值? –

回答

2

這將返回正確的行,但問題是自snapshot_time列以來的結果行是時區類型的時間戳實際上是5個小時,因爲我住在東部標準時間。

時間戳總是存儲在PostgreSQL的UTC,per the docs

對於帶有時區的時間標記,內部存儲的數值總是UTC(全球統一時間,習慣上稱爲格林威治標準時間(GMT)) 。使用該時區的適當偏移量將具有指定明確時區的輸入值轉換爲UTC。如果沒有時間段被輸入字符串表示,那麼它被認爲是在由該系統的時區參數所表示的時間帶,並使用被轉換爲UTC的時區區域中的偏移量。

當與時區值的時間戳輸出,它總是從UTC轉換成當前時區區域,並且如在該區域的本地時間顯示。要查看另一個時區的時間,可以更改時區,要麼使用AT TIME ZONE構造(見Section 9.9.3)。

0

回答我的情況下,任何人的問題遇到在谷歌這個問題。

繼埃文·卡羅爾的答案,下面的SQL固定我的問題:

SELECT id,snapshot_time,match->'kills' FROM match_archive 
WHERE extract(dow from snapshot_time AT TIME ZONE 'UTC')=5 
AND snapshot_time >= '2016-12-01' 
AND date_part('hour', snapshot_time AT TIME ZONE 'UTC')=2 
AND date_part('minute', snapshot_time AT TIME ZONE 'UTC')=00; 

可能的微小date_part數沒有必要,但要保持一致。

+0

或者,如果您希望UTC的時間,只需將客戶端,數據庫或操作系統中的本地時區設置爲UTC即可。 –