embulk-input-postgresqlでTimestampが9時間巻き戻ってしまったとき

embulk-input-postgresql v0.13.0で、Timestamp without Timezoneなカラムの値が9時間巻き戻るケースを発見した。

PostgreSQLサーバのTZがUTC、実行ホストがJSTの場合に巻き戻る模様。

実験

サーバのTZがUTCの場合

admin=# show timezone;
 TimeZone
----------
 Etc/UTC
(1 row)

mydatabase=# select * from mytable;
 id |  name  |         updated_at
----+--------+----------------------------
  1 | myname | 2022-07-30 17:23:28.698386
(1 row)

liquidファイルは以下のようなものを用意しておく

in:
  type: postgresql
  host: 127.0.0.1
  user: admin
  password: admin 
  database: mydatabase
  table: mytable
結果
$ embulk preview test.yml.liquid

# プレビュー
+---------+-------------+--------------------------------+
| id:long | name:string |           updated_at:timestamp |
+---------+-------------+--------------------------------+
|       1 |      myname | 2022-07-30 08:23:28.698386 UTC |
+---------+-------------+--------------------------------+

サーバのTZがAsia/Tokyoの場合

mydatabase=# show timezone;
  TimeZone
------------
 Asia/Tokyo
(1 row)

mydatabase=# select * from mytable;
 id |  name  |        updated_at
----+--------+---------------------------
  1 | myname | 2022-07-31 01:50:28.73504
(1 row)
結果
$ embulk preview test.yml.liquid

# プレビュー
+---------+-------------+--------------------------------+
| id:long | name:string |           updated_at:timestamp |
+---------+-------------+--------------------------------+
|       1 |      myname | 2022-07-30 16:50:28.735040 UTC |
+---------+-------------+--------------------------------+

対処法1

サーバのTZがUTCの場合はTZ=UTCでembulk previewを実行する

PostgreSQLと実行ホストのTZを共にUTCで揃えると巻き戻らない。

$ TZ=UTC embulk preview test.liquid.yml

# プレビュー
+---------+-------------+--------------------------------+
| id:long | name:string |           updated_at:timestamp |
+---------+-------------+--------------------------------+
|       1 |      myname | 2022-07-30 17:23:28.698386 UTC |
+---------+-------------+--------------------------------+

対処法2

サーバのTZがJSTの場合はdefault_column_options でフォーマットすることで対応する

in:
  type: postgresql
  host: 127.0.0.1
  user: admin
  password: admin 
  database: mydatabase
  table: mytable
  default_column_options:
    TIMESTAMP: { type: string, timestamp_format: "%Y/%m/%d %H:%M:%S", timezone: "+0900"}

結果

# プレビュー
+---------+-------------+---------------------+
| id:long | name:string |   updated_at:string |
+---------+-------------+---------------------+
|       1 |      myname | 2022/07/31 01:50:28 |
+---------+-------------+---------------------+

参考

こちらのツイートのツリーを参考にさせていただきました。

https://twitter.com/hiroysato/status/1281043865667944448

default_column_options については以下に記載あり。

embulk-input-jdbc/embulk-input-postgresql at master · embulk/embulk-input-jdbc · GitHub