2014-10-29 76 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