我在欧洲/柏林时区(+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时间是前一天的stil,今天似乎使用utc来计算其余时间。
如果我们在欧洲/柏林有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
这是正确的,但非常难看。
此命令是否有更清晰的变体?
答案 0 :(得分:4)
使用timestamptz
。最后的tz
表示with time zone
:
SELECT TIMESTAMPTZ 'today' AT TIME ZONE 'Europe/Berlin'
或者如果你更喜欢它:
SELECT TIMESTAMP with time zone 'today' AT TIME ZONE 'Europe/Berlin'
答案 1 :(得分:1)
将其包裹在一个函数中:
create function midnight() returns timestamptz as $$
select date_trunc('day', now() AT TIME ZONE 'Europe/Berlin') AT TIME ZONE 'Europe/Berlin';
$$ language sql;
答案 2 :(得分:1)
基于Erwin's answer to a related question,这是我找出方法的最简单,最快的方法:
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倍。基于5次运行的最佳运行时间,运行时间为.017ms vs.0.006ms。