3

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

在 PostgreSQL 9.1 中,我需要解释一个DATE在数据库中存储为 a 的字段,就好像它是TIMESTAMPTZ那个日期的午夜 UTC 一样。我想以一种清晰易读的方式来完成它,以便有人可以出现、查看并理解正在发生的事情。

到目前为止,我发现的唯一方法都非常难看。将其转换为 a然后通过将其解释为 UTC来TIMESTAMP WITHOUT TIME ZONE创建 a :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在当地时间与current_timestampUTC 进行比较来获得它。

我可以解决的唯一其他方法extract是获取日期零件并timestamptz从中组装新零件。我什至不会展示那个,它太丑了。

这两种方法都让人感到各种奇怪和错误。是否有任何理智的方式 - 标准或否 - 以可读且易于理解的方式从该日期的午夜 UTC转换DATE为 a ?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

4

2 回答 2

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'

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

于 2012-08-23T14:41:57.913 回答
2

注意:我对 PSQL 了解不多,但我对日期/时间问题有一些经验。

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

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

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

基本上,它看起来不错。如果它的工作原理和性能都和你需要的一样好,我会坚持下去。

于 2012-08-23T13:23:10.940 回答