我的服务器在中部时间。我想使用东部时间渲染时间戳。
例如,我想将2012-05-29 15:00:00
呈现为2012-05-29 16:00:00 EDT
。
我怎样才能实现它?
to_char('2012-05-29 15:00:00'::timestamptz at time zone 'EST5EDT', 'YYYY-MM-DD HH24:MI:SS TZ')
提供2012-05-29 16:00:00
(无区域)。
to_char('2012-05-29 15:00:00'::timestamp at time zone 'EST5EDT', 'YYYY-MM-DD HH24:MI:SS TZ')
提供2012-05-29 14:00:00 CDT
(错误)。
这个有用,但它太复杂了必须有一个更简单的方法:replace(replace(to_char(('2012-05-29 15:00:00'::timestamptz at time zone 'EST5EDT')::timestamptz, 'YYYY-MM-DD HH24:MI:SS TZ'), 'CST', 'EST'), 'CDT', 'EDT')
答案 0 :(得分:34)
关键是在交易期间将本地时区切换到所需的显示时区:
begin;
set local timezone to 'EST5EDT';
select to_char('2012-05-29 15:00:00'::timestamp at time zone 'CDT',
'YYYY-MM-DD HH24:MI:SS TZ');
end;
结果是:
2012-05-29 16:00:00美国东部时间
请注意,对于set [local] timezone
,需要使用全时区域名称而不是缩写(例如,CST不起作用)。在pg_timezone_names
视图中查找有效选项。
要在类似于to_char()调用的上下文中使用该方法,我相信这个函数可以完成这项任务:
CREATE FUNCTION display_in_other_tz(
in_t timestamptz,
in_tzname text,
in_fmt text) RETURNS text
AS $$
DECLARE
v text;
save_tz text;
BEGIN
SHOW timezone into save_tz;
EXECUTE 'SET local timezone to ' || quote_literal(in_tzname);
SELECT to_char(in_t, in_fmt) INTO v;
EXECUTE 'SET local timezone to ' || quote_literal(save_tz);
RETURN v;
END;
$$ language plpgsql;
答案 1 :(得分:3)
事实上,PG知道这一切 - to_char(x,'TZ')区分CST CDT正确,并且在时区EST5EDT也尊重DST。
在处理时间戳时,Postgres知道:
timezone
。timestamp
和timestamptz
的'1970-1-1 0:0 UTC'相同的秒数。 (或者,确切地说:UT1。)在解释输入时,Postgres使用有关提供的时区的信息。
在呈现时间戳值时,Postgres使用当前 timezone
设置,但时区偏移,缩写或名称< / em>仅用于在输入上计算正确的值。它们未保存。稍后提取该信息不可能。有关此related answer的详细信息:
您的“正确”示例 几乎 正确。 TZ
的{{1}}返回'CDT'表示中央时间夏令时和其他'CST'时间戳的时间戳。东部时间(to_char()
/ EST
)在同一本地时间切换夏令时 - 我引用维基百科:
时间在当地时间凌晨2:00调整。
这两个时区每年两小时内不同步。当然,这绝不会影响EDT
或15:00
的时间戳,只会影响16:00
。
一个完全正确的解决方案 - 就像@Daniel已发布的那样,略微简化:
02:00
SET LOCAL的效果仅持续到当前交易结束。