PostgreSQL - 如何在不同的时区渲染日期?

时间:2012-05-29 10:54:15

标签: postgresql datetime timezone

我的服务器在中部时间。我想使用东部时间渲染时间戳。

例如,我想将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')

2 个答案:

答案 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知道:

在解释输入时,Postgres使用有关提供的时区的信息。 在呈现时间戳值时,Postgres使用当前 timezone设置,但时区偏移缩写名称< / em>仅用于在输入上计算正确的。它们未保存。稍后提取该信息不可能。有关此related answer的详细信息:

您的“正确”示例 几乎 正确。 TZ的{​​{1}}返回'CDT'表示中央时间夏令时和其他'CST'时间戳的时间戳。东部时间(to_char() / EST)在同一本地时间切换夏令时 - 我引用维基百科:

  

时间在当地时间凌晨2:00调整。

这两个时区每年两小时内不同步。当然,这绝不会影响EDT15:00的时间戳,只会影响16:00

一个完全正确的解决方案 - 就像@Daniel已发布的那样,略微简化:

02:00
  

SET LOCAL的效果仅持续到当前交易结束。

The manual about SET LOCAL.