我正在做一些数据导入,包括时区转换。我导入的数据位于 America/New_York 时区,我必须将其导入为 UTC 时间戳。
我尝试了一些在互联网上找到的例子,例如:
to_timestamp(tar.read_at_date || ' ' || tar.read_at_hour, 'MM/DD/YYYY HH24:MI')::timestamp without time zone at time zone 'America/New_York' at time zone 'utc'
这似乎对大多数数据都有效,但是,我注意到在特定时间有一些奇怪的转换,比如 Postgres 对 UTC 时区应用夏令时(???)。
要快速说明行为,请查看下面的示例和结果:
select ('2023-03-25 22:00:00'::timestamp at time zone 'America/New_York' at time zone 'utc');
result: 2023-03-26 03:00:00.000
select ('2023-03-25 23:00:00'::timestamp at time zone 'America/New_York' at time zone 'utc');
result: 2023-03-26 03:00:00.000
我正在运行这些查询:
PostgreSQL [15.5
PostgreSQL 15.5 on aarch64-unknown-linux-gnu, compiled by gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-6), 64-bit]
另外,值得一提的是,2023 年纽约的夏令时从 3 月 12 日星期日凌晨 2:00 开始。有趣的是,2023 年 3 月 26 日凌晨 2 点是欧洲时钟前进的时间。
有什么合理的解释为什么会发生这种情况吗?
函数
to_timestamp()
返回。text
timestamptz
这并不是IMMUTABLE
因为它取决于当前的timezone
设置。输入表达式
tar.read_at_date || ' ' || tar.read_at_hour
似乎没有附加时区偏移量。告诉 Postgres 你的时间戳位于America/New_York
时区的正确方法是进行timezone
相应的设置(对于当前会话):这是不明确的:
Postgres 时间戳类型根本不“位于”任何时区。看:
数据类型
timestamp
(timestamp without time zone
) 没有时区的概念。需要将其设置在给定的时区中才能作为通用时间有意义。数据类型
timestamptz
(timestamp with time zone
) 在内部存储为 UTC。其文本表示形式根据timezone
当前会话的设置进行格式化。但总是在同一个时间点。对于我(使用timezone = 'Europe/Vienna'
),时间戳当前显示为“+02”偏移量(这要归功于完全无用的“夏令时”)。所以:.. 显示为“2023-04-26 01:00:00+02”。完全相同的值,只是针对不同的时区设置了格式。