我正在尝试在Postgres中创建一个表,用于存储在接下来的几年中每天每小时发生一次的事件。所以我使用以下表达式填充了一个coloumn:
INSERT INTO tablename(time)
SELECT CAST('2013-01-01' AS DATE) + (n || ' hour')::INTERVAL
FROM generate_series(0, 100000) n;
作为此列的数据类型,我选择带时区的时间戳,并希望以这种方式自动考虑夏令时。 (顺便说一句,我的默认时区是CET,所以当DST适用时它是UTC + 1或UTC + 2)。作为上述查询的结果,我得到了这个:
UTC的偏移变化,我预计3月31日02:00被遗漏,因为这一天只有23个小时,但我不知道为什么03:00有两次,而10月27日02:00只有一次而不是两次,因为这一天有25个小时。我想要实现的是,在3月2日的特定日期的所有年份都不会跳过(我宁愿放入' na'或相应值的东西)并且在10月的特定日期(但不是3月份),有两个3' oclock的条目,因此我将获得以下形式的列(其中1表示从00:00-1开始的小时) :00,2:1:00-2:00等):
有人知道如何去做吗?我做的事基本上是错的吗?这只是格式问题吗?我必须写一个函数吗?任何帮助,将不胜感激。谢谢。
答案 0 :(得分:0)
Postgres中的日期和时间以UTC格式存储,并根据时区配置指定的区域转换为本地时间。
这意味着您只需要解决表示问题。尝试使用AT TIME ZONE 'UTC+2'
将UTC时间转换为您的时区并查看结果。这是查询:
SELECT (CAST('2013-03-30' AS DATE) + (n || ' hour')::INTERVAL) AT TIME ZONE 'UTC+2'
FROM generate_series(0, 1000) n;
答案 1 :(得分:0)
无论时区设置如何,时间戳始终存储为UTC。 From the manual
对于带时区的时间戳,内部存储的值始终为UTC(通用协调时间,传统上称为格林威治标准时间,GMT)。具有指定显式时区的输入值将使用该时区的适当偏移量转换为UTC。如果输入字符串中没有声明时区,则假定它位于系统的TimeZone参数指示的时区中,并使用时区的偏移量转换为UTC。
set time zone 'CET';
drop table if exists events;
create table events (
tstz timestamp with time zone
);
insert into events (tstz)
select generate_series('2013-01-01', '2013-10-28', interval '1 hour') s(tstz)
;
请注意使用generate_series
函数。
select
tstz at time zone 'UTC' as "UTC",
tstz at time zone 'CET' as "CET",
tstz at time zone 'CEST' as "CEST",
tstz as "LOCAL"
from events
where date_trunc('day', tstz) in ('2013-03-31', '2013-10-27')
order by tstz
;
UTC | CET | CEST | LOCAL
---------------------+---------------------+---------------------+------------------------
2013-03-30 23:00:00 | 2013-03-31 00:00:00 | 2013-03-31 01:00:00 | 2013-03-31 00:00:00+01
2013-03-31 00:00:00 | 2013-03-31 01:00:00 | 2013-03-31 02:00:00 | 2013-03-31 01:00:00+01
2013-03-31 01:00:00 | 2013-03-31 02:00:00 | 2013-03-31 03:00:00 | 2013-03-31 03:00:00+02
2013-03-31 02:00:00 | 2013-03-31 03:00:00 | 2013-03-31 04:00:00 | 2013-03-31 04:00:00+02
2013-03-31 03:00:00 | 2013-03-31 04:00:00 | 2013-03-31 05:00:00 | 2013-03-31 05:00:00+02
...
2013-10-26 22:00:00 | 2013-10-26 23:00:00 | 2013-10-27 00:00:00 | 2013-10-27 00:00:00+02
2013-10-26 23:00:00 | 2013-10-27 00:00:00 | 2013-10-27 01:00:00 | 2013-10-27 01:00:00+02
2013-10-27 00:00:00 | 2013-10-27 01:00:00 | 2013-10-27 02:00:00 | 2013-10-27 02:00:00+02
2013-10-27 01:00:00 | 2013-10-27 02:00:00 | 2013-10-27 03:00:00 | 2013-10-27 02:00:00+01
2013-10-27 02:00:00 | 2013-10-27 03:00:00 | 2013-10-27 04:00:00 | 2013-10-27 03:00:00+01
2013-10-27 03:00:00 | 2013-10-27 04:00:00 | 2013-10-27 05:00:00 | 2013-10-27 04:00:00+01
2013-10-27 04:00:00 | 2013-10-27 05:00:00 | 2013-10-27 06:00:00 | 2013-10-27 05:00:00+01
如果timestamp with timestamp
列是selectec而未使用上面LOCAL
列中的at time zone
,那么它将在服务器时区输出在该时间戳 。这就是为什么缺少和重复的小时数。
我认为您想要的输出是错误的。但是使用 query fu
可以实现我无法重现您的实际输出。什么是服务器时区?
show time zone;
TimeZone
----------
CET