2014-10-29 34 views
2

我試圖想出一個查詢,它將正確計算夏令時有25個小時。我的表有一個timestampz類型的列,名爲hourly_timestamp。不正確的答案我到目前爲止是這樣的:PostgreSQL:計算夏令時當天的小時數

select EXTRACT(epoch FROM tomorrow-today)/3600 
from(
    select date_trunc('day', timezone('America/New_York', hourly_timestamp) as today , 
     date_trunc('day', timezone('America/New_York', hourly_timestamp))) 
                 + '1 day'::interval as tomorrow 
    )t; 

在此查詢在夏令時執行,我仍然只能獲取24時間重新寫回,而不是25.任何想法如何正確地做到這一點?

回答

0

你首先要做的萃取時期,然後計算:

WITH test AS (
    SELECT '2014-10-26'::timestamptz at time zone 'America/New_York' AS today, 
     '2014-10-27'::timestamptz at time zone 'America/New_York' AS tomorrow 
) 
SELECT 
    extract(epoch from tomorrow) - extract(epoch from today)  AS seconds, -- 90000 
    (extract(epoch from tomorrow) - extract(epoch from today))/3600 AS hours -- 25 
FROM test; 
1

的小時數與時鐘而變化。

with hours as (
    select (timestamp with time zone '2014-11-01 00:00:00 America/New_York' + (n || ' hour')::interval) as hourly_timestamp 
    from generate_series(0, 72) n 
) 
select hourly_timestamp 
    , hourly_timestamp + interval '1' day as one_day_later 
    , hourly_timestamp + interval '1' day - hourly_timestamp as elapsed_time 
from hours; 
 
hourly_timestamp   one_day_later   elapsed_time 
-- 
[snip] 
2014-11-01 22:00:00-04 2014-11-02 22:00:00-05 1 day 01:00:00 
2014-11-01 23:00:00-04 2014-11-02 23:00:00-05 1 day 01:00:00 
2014-11-02 00:00:00-04 2014-11-03 00:00:00-05 1 day 01:00:00 
2014-11-02 01:00:00-04 2014-11-03 01:00:00-05 1 day 01:00:00 
2014-11-02 01:00:00-05 2014-11-03 01:00:00-05 1 day 
2014-11-02 02:00:00-05 2014-11-03 02:00:00-05 1 day 
2014-11-02 03:00:00-05 2014-11-03 03:00:00-05 1 day 
2014-11-02 04:00:00-05 2014-11-03 04:00:00-05 1 day 
[snip] 

需要注意的是01:00的重複,但有不同的偏移。夏令時在02:00結束,時鐘倒退並在01:00和02:00之間重複小時,但由於夏令時已結束,UTC和America/New_York時區之間現在有五個小時。

這個類似的查詢顯示日期,而不是時間戳。

with dates as (
    select (timestamp with time zone '2014-11-01 00:00:00 America/New_York' + (n || ' day')::interval) as daily_timestamp 
    from generate_series(0, 2) n 
) 
select daily_timestamp::date 
    , (daily_timestamp + interval '1' day)::date as one_day_later 
    , daily_timestamp + interval '1' day - daily_timestamp as elapsed_time 
from dates; 
 
daily_timestamp one_day_later elapsed_time 
-- 
2014-11-01  2014-11-02  1 day 
2014-11-02  2014-11-03  1 day 01:00:00 
2014-11-03  2014-11-04  1 day 

你去哪兒了?通過計算之後的經過時間,可以截短時間信息。 (日期沒有與它們關聯的時區。)如果我接受第二個查詢並將「daily_timestamp」轉換爲公用表表達式中的日期,我也會獲得24小時。

with dates as (
    select (timestamp with time zone '2014-11-01 00:00:00 America/New_York' + (n || ' day')::interval)::date as daily_timestamp 
    from generate_series(0, 2) n 
) 
select daily_timestamp::date 
    , (daily_timestamp + interval '1' day)::date as one_day_later 
    , daily_timestamp + interval '1' day - daily_timestamp as elapsed_time 
from dates; 
 
daily_timestamp one_day_later elapsed_time 
-- 
2014-11-01  2014-11-02  1 day 
2014-11-02  2014-11-03  1 day 
2014-11-03  2014-11-04  1 day