2016-04-11 78 views
4

关于时区从夏令时到非夏令时变化的棘手问题,我很难过。postgres:生成关于时区的一系列时间戳

我试图生成一系列时间戳,相隔6小时。稍后在数据集中每天在00,06,12,18小时与具有相应时间戳的数据结合。

这通常工作正常使用:

generate_series(extract(epoch from start_ts)::integer, extract(epoch from end_ts)::integer, 21600)

其中start_ts是在第一次约会00小时,并end_ts是排他性的最后一天00小时。

但是,如果时区偏移量从+11到+10在整个系列的一半时间内变化,它将不再匹配任何记录,因为系列元素变为1小时关闭。

有没有人有建议如何产生一系列'纪元整数'或时间戳,将匹配00,06,12,18小时时间戳,同时尊重时区的偏移?

回答

2

这(使用PostgreSQL 9.5+),从今天开始,10天产生的呢:

select (current_date::timestamp + ((a-1)||' days')::interval)::timestamptz 
from generate_series(1, 10, .25) a 

测试它整整一年:

select *, date_part('hour', d::timestamp), d::timestamp 
from (
    select (current_date::timestamp + ((a-1)||' days')::interval)::timestamptz AS d 
    from generate_series(1, 365, .25) a 
) x 
where date_part('hour', d) not in (0, 6, 12, 18) 

编辑:下面的版本适用于9.5以上版本的PostgreSQL:

select (current_date::timestamp + (((a-1)/4.0)||' days')::interval)::timestamptz 
from generate_series(1, 4* 10 ) a -- 10 days 
+0

增加了一个修正和测试 –

+1

我喜欢它!好像我们使用的是9.4,而不是9.5,它向generate_series引入了'数字'参数类型,在此之前只允许int/bigint。我会看看我们是否可以升级。谢谢!然而,我确实设法以更冗长的方式解决它;生成2个序列 - 1前进1后退,然后验证每个结果。我将以解决方案的形式发布,因为它在时区z'有其他一些好处'to_timestamp(val)。 – pstanton

0

@ Ziggy的回答非常好,请使用它。但这里是我如何解决它在我的应用程序不能使用generate_series小数(V9.4):

_min timestamp with time zone, -- the first timestamp in the series 
_max timestamp with time zone, -- the last timestamp in the series 
_inc integer, -- the increment in seconds, eg 21600 (6hr) 
_tz text 
  1. 从创建使用TZ的_MAX偏移的_MAX下一个系列,
  2. 创建从使用TZ的_min偏移的_min了一系列,
  3. 将结果合并
  4. 验证每个结果是通过在结果的TZ的_inc整除,丢弃如果不是

查询:

select t1 from (
    select ser, 
     to_timestamp(ser) t1, 
     extract(epoch from 
       to_timestamp(ser) at time zone _tz 
        - date_trunc('day', to_timestamp(ser) at time zone _tz) 
      )::integer % _inc = 0 is_good 
    from (
     select 'ser1' s, generate_series(extract(epoch from _min)::integer, extract(epoch from _max)::integer, _inc) ser 
     union all 
     select 'ser2' s, generate_series(extract(epoch from _max)::integer, extract(epoch from _min)::integer, _inc * -1) ser 
    ) x 
    group by ser, _tz, _inc 
    order by ser asc 
) x 
where is_good 
; 
相关问题