4

我在欧洲/柏林时区 (+02),Postgresql 在 UTC (+00) 运行。我需要在最新的本地午夜日期(我的时区当天的开始日期)获取带有时区的时间戳。

因此,如果我们有 2013-03-03 14:00:00+02,我的最终结果将是这样的

2013-03-03 22:00:00+00
2013-03-04 00:00:00+02 // the same

我试图得到这个日期

SELECT TIMESTAMP 'today' AT TIME ZONE 'Europe/Berlin'

不幸的是,这会在 00:00 和 02:00 期间产生错误的日​​期(前一天午夜),因为 UTC 时间仍然是前一天,而今天似乎使用 utc 来计算其余时间。

如果我们在 Europe/Berlin 有 2013-03-03 00:05 这将返回

2013-05-01 22:00:00+00

如果我想获得正确的日期,我需要使用

SELECT date_trunc('day', now() AT TIME ZONE 'Europe/Berlin') AT TIME ZONE 'Europe/Berlin';
2013-05-02 22:00:00+00

这是正确的,但很丑陋。

这个命令有更简洁的变体吗?

4

3 回答 3

5

使用timestamptz. 结尾的tz意思with time zone

SELECT TIMESTAMPTZ 'today' AT TIME ZONE 'Europe/Berlin'

或者,如果您更喜欢它:

SELECT TIMESTAMP with time zone 'today' AT TIME ZONE 'Europe/Berlin'
于 2013-05-03T11:15:27.220 回答
2

将其包装在一个函数中:

create function midnight() returns timestamptz as $$
  select date_trunc('day', now() AT TIME ZONE 'Europe/Berlin') AT TIME ZONE 'Europe/Berlin';
$$ language sql;
于 2013-05-03T09:37:08.020 回答
1

根据Erwin 对相关问题的回答,这是我想出的最简单和最快的方法:

SELECT timezone('Europe/Berlin', now()::date::timestamp) AS local_midnight_in_utc;

关键是转换为时间戳,它从日期中删除时区。

您可以使用以下命令测试您的采样时间“2013-03-03 00:05”:

SELECT timezone('Europe/Berlin', '2013-03-03 00:05'::date::timestamp) AS midnight;

它返回

2013-03-02 23:00:00+00

根据解释分析,这大约是 datetrunc 版本的 3 倍。0.017 毫秒与 0.006 毫秒的运行时间基于 5 次运行中的最佳值。

于 2020-05-06T07:50:38.437 回答