在 'COPY .. TO ..' 期间将给定时区的时间戳转换为本地时间

Transform timestamp to local time for a given timezone during 'COPY .. TO ..'

我在 PostgreSQL 数据库中有一个日志 table,其中一个 event 列类型为 timestamp without time zone

现在我有一个 bash 脚本,它从日志数据库创建一个 CSV 文件:

...
psql .. -c "COPY (SELECT event, ... FROM logtable order by event desc) TO STDOUT WITH CSV" logdb > log.csv
...

这是在托管数据库的云服务器上执行的,因此,log.csv 中的时间戳字符串是服务器时区的本地时间。

不过,我喜欢用时间戳字符串来表示我所在时区的时间。所以我应该能够让 psql 将时间戳 -> 字符串转换为给定的时区。我怎样才能做到这一点?

首先,在处理多个时区时,您应该使用 timestamptz 而不是 timestamp。会完全避免这个问题。

详情:

  • Ignoring timezones altogether in Rails and PostgreSQL

可以@NuLo suggests一样使用AT TIME ZONE构造,它可能甚至可以工作,但不完全是如上所述。

AT TIME ZONE 将类型 timestamp (timestamp without time zone) 转换为 timestamptz (timestamp with time zone),反之亦然。 timestamptz值的文本表示取决于时区的当前设置在您 运行 命令所在的会话中。这两个 timestamptz 100% 相同(表示同一时间点):

'2015-09-02 15:55:00+02'::timestamptz
'2015-09-02 14:55:00+01'::timestamptz

但是文本表示是而不是。显示适用于不同的时区。如果您将此字符串文字输入 timestamp 类型,则时区部分只是 被忽略 并且您最终得到 different 值。因此,如果您 运行 在会话中使用与原始 timestamp 值相同时区设置的 COPY 语句,建议的操作 会发生 上班。

然而,干净的方法是通过应用 AT TIME ZONE 两次[=74 来生成正确的 timestamp 值=]:

SELECT <b>event AT TIME ZONE 'my_target_tz' AT TIME ZONE 'my_source_tz'</b>, ...
FROM   logtable
ORDER  BY event desc;

'my_target_tz'是"your own time zone"和'my_source_tz'示例中云服务器的时区。为确保遵守 DST,请使用 时区名称 ,而不是时区缩写。 The documentation:

A time zone abbreviation, for example PST. Such a specification merely defines a particular offset from UTC, in contrast to full time zone names which can imply a set of daylight savings transition-date rules as well.

相关:

  • Accounting for DST in Postgres, when selecting scheduled items
  • Time zone names with identical properties yield different result when applied to timestamp

或者,更好的是,到处使用 timestamptz,它会自动正常工作。