2010-12-11 203 views
0

我需要對我的數據庫執行一些日期時間操作,這需要所有created時間戳具有相同的年份。我試圖與此查詢:PostgreSQL中的時間戳操作 - 帶小時/時區的問題

select created,cast (created - 
    to_timestamp(''||date_part('year', created), 'YYYY') + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table where created is not null limit 10; 

...但結果是隻能部分滿足:

 created  |  timestamp  
---------------------+--------------------- 
2010-08-29 12:44:05 | 2010-08-29 11:44:05 
2007-06-21 13:49:22 | 2010-06-21 12:49:22 
2007-06-21 15:02:33 | 2010-06-21 14:02:33 
2007-06-21 15:05:26 | 2010-06-21 14:05:26 
1999-09-30 13:00:00 | 2010-09-30 12:00:00 
1997-06-07 13:00:00 | 2010-06-07 12:00:00 
2010-06-15 20:51:01 | 2010-06-15 19:51:01 
2006-08-26 15:33:02 | 2010-08-26 14:33:02 
2009-12-15 11:07:06 | 2010-12-15 11:07:06 
1997-06-28 13:00:00 | 2010-06-28 12:00:00 
(10 rows) 

正如你所看到的,所有的時間戳是-1小時比較原始created值。更奇怪的是,最後一個(2010-12-15 11:07:06)之前沒有。

created列是timestamp without time zone類型。

任何想法我做錯了什麼?

回答

1

您的SQL的問題是它不會將日期轉換爲另一年的日期。它計算已創建的和2010-01-01的增量值並將其轉換爲日期。所以你實際上並沒有刪除年份,而是計算了多久之前。

下面是解決問題的另一種方法。它只會取代一年,其餘日期不變。

SELECT TO_TIMESTAMP('2010-' || CAST(EXTRACT(MONTH FROM created) AS VARCHAR) || '-' || CAST(EXTRACT(DAY FROM created) AS VARCHAR) || ' ' || CAST(EXTRACT(HOUR FROM created) AS VARCHAR) ||':'||CAST(EXTRACT(MINUTE FROM created) AS VARCHAR) ||':'|| CAST(EXTRACT(SECONDS FROM created) AS VARCHAR), 'YYYY-MM-dd HH24:MI:SS') AS timestamp FROM table; 

你也可以用子串來做到這一點。 TO_TIMESTAMP()會將2010-02-29投影到2010-03-01,因此可以安全使用。

1

這是中提到的子解決方案JMZ:

 
select to_timestamp('2010'||substring(to_char(created, 'yyyy-mm-dd hh24:mi:ss.ms'), 5), 'yyyy-mm-dd hh24:mi:ss.ms') 
0

謝謝你們,無論JMZ和a_horse_with_no_name解決方案,做工精細。

我也修復了我的解決方案。問題出在to_timestamp返回timestamp with time zone和我預計timestamp without time zone。這足以添加一個類型匹配:

select created,cast (created-to_timestamp(''|| 
    date_part('year', created), 'YYYY')::timestamp without time zone + 
    timestamp '2010-01-01' as timestamp without time zone) 
    from table;