是否有一种简单而干净的方式将“DATE”转换为UTC日期的那个日期的“TIMESTAMP AT TIME ZONE”?

时间:2012-08-23 13:12:05

标签: sql postgresql date timezone

这应该很简单,但我遇到了一些令人尴尬的麻烦。

在PostgreSQL 9.1中,我需要在数据库中存储一个存储为DATE的字段,就好像它是TIMESTAMPTZ表示该日期的午夜UTC一样。我希望以干净和可读的方式做到这一点,有人可以来,看看,并了解正在发生的事情。

到目前为止,我发现这样做的唯一方法都非常难看。一个人将其转换为TIMESTAMP WITHOUT TIME ZONE,然后通过将其解释为UTC来创建TIMESTAMP WITH TIME ZONE

SELECT CAST(DATE '2012-01-01' AS TIMESTAMP WITHOUT TIME ZONE) AT TIME ZONE 'utc'

另一种方式更糟:

('2012-01-01'::date)::timestamptz - (current_timestamp AT TIME ZONE 'UTC' - current_timestamp)

因为它将日期转换为当地时间午夜的时间戳,然后减去时区偏移量。我无法找到任何方法将该偏移作为一个间隔本地(这看起来很疯狂)所以我通过将本地时间的current_timestamp与UTC中的current_timestamp进行比较来获得它。

我可以解决的唯一方法是使用extract获取日期部分并从中组合新的timestamptz。我甚至不会展示那个,它太丑了。

这两种方法都会感到各种奇怪和错误。是否有任何理智的方式 - 标准或无 - 以可读且易于理解的方式从当天午夜UTC的DATE转换为timestamptz

我正在寻找类似(虚构,不起作用)的东西

'2012-01-01'::date AS TIMESTAMPTZ IN TIME ZONE '00:00';

to_timestamp('2012-01-01'::date, '00:00'::time, 'UTC');

请指出我错过的愚蠢明显的事情。

请注意,我正在测试以确保日期在内部真正正确,而不仅仅是显示日期,其中extract(epoch from $1) $1是转换日期。

2 个答案:

答案 0 :(得分:4)

你的第一种方法是正确的。这不是那么难看,是吗?在简化的Postgres语法中:

SELECT '2012-1-1'::date::timestamp AT TIME ZONE 'UTC';

应用于变量或列,它看起来更优雅:

SELECT mydate::timestamp AT TIME ZONE 'UTC';

如果您要手动输入日期,可以快捷方式:

SELECT '2012-1-1 0:0'::timestamp AT TIME ZONE 'UTC'

结果将始终显示根据客户端的本地时区(即具有相应的偏移量),但这对没有影响。

答案 1 :(得分:2)

注意:我对PSQL知之甚少,但我对日期/时间问题有一些经验。

你的第一种方式对我来说是正确的。您实际上是从“本地日期”到“本地日期/时间”到“特定时区的日期/时间”。这些都是合理的步骤,我希望在正常的日期/时间API中看到这些步骤。

据我所知,这种方法从未引入系统默认时区,这是一件非常好的事情。它一次执行一个逻辑步骤,假设投射是明智的事情。

您无需担心目标时区中的本地日期/时间不明确或缺失,因为UTC没有任何DST转换。

基本上,它看起来很好。如果它能够正常工作并且表现得很好,我会坚持下去。