JetBrains製EditorでPostgreSQLに接続するときのタイムゾーンについて　

# タイムゾーンが設定値と異なる
PostgreSQL側でタイムゾーンをAsia/Tokyoで指定したのに、InteliJのようなJetBrains製のエディターから接続した時にUTCに変わってしまうことがありました。参照するだけであればそこまで問題ではないですが、そこから現在時刻を挿入するようなことがあれば想定と異なるデータになるため問題になります。

このまま使うのが怖かったので調べたところ、InteliJでタイムゾーンを明示的に指定する方法を見つけたので調査結果と解決策についてまとめます。

# 前提知識と準備
## PostgresSQLのタイムゾーン
PostgresSQLのタイムゾーンはpostgresql.confに設定します。

```
timezone = 'Asia/Tokyo'
```

※AWSのRDSではクラウドパラメータという機能を使って設定することができるので別の設定方法があります。

下記のクエリを投げると現在のタイムゾーンを確認できます。

```
show timezone;
```

## クエリでタイムゾーンを変更する方法
クエリでデータベース単位で変更する方法です。検証で使うので先に書いておきます。

```sql
ALTER DATABASE DB_NAME SET timezone TO 'Asia/Tokyo'
```

セッション単位で変更する時(接続を切れば元に戻る)

```sql
SET timezone TO 'Asia/Tokyo'
```

## タイムゾーンがAsia/TokyoなPostgreSQLを立ち上げる

ローカルにPostgreSQLのdockerコンテナを立てます。

```docker
version: "3"
services:
  postgres:
    image: postgres:9.6
    container_name: "postgres_practice"
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=postgres_practice
      - POSTGRES_PASSWORD=postgres_practice
      - POSTGRES_DB=practice
    user: root
```

立ち上げます。

```bash
docker-compose up
```

タイムゾーンを確認するとUTCになっています。

```bash
docker exec -it postgres_practice psql -U postgres_practice -W -d practice -c "show timezone"
Password for user postgres_practice:
 TimeZone
----------
 UTC
(1 row)
```
デフォルトではUTCになっているのでAsia/Tokyoに変更します。

```bash
docker exec -it postgres_practice sed -i 's/UTC/Asia\/Tokyo/g' /var/lib/postgresql/data/postgresql.conf
```

再起動します。

```bash
docker-compose restart
```

これでタイムゾーンがAsia/TokyoなPostgreSQLが立ち上がります。

```bash
docker exec -it postgres_practice psql -U postgres_practice -W -d practice -c "show timezone"                                                                2824ms  月  4/15 02:37:48 2019
Password for user postgres_practice:
  TimeZone
------------
 Asia/Tokyo
(1 row)
```

# JetBrains製のEditorで確認

しっかりAsia/TokyoなPostgresが立ち上がったところで、JetBrains製のエディターで確認してみます。

下記のような設定で接続します。

<img width="733" alt="スクリーンショット 2019-04-15 3.28.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/bffa8e98-bada-9f1a-2214-ef92625afef9.png">

タイムゾーンを確認。

<img width="598" alt="スクリーンショット 2019-04-15 2.46.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/91217dd9-b75c-a12c-c487-fdcba55ec355.png">

なんでやねん。
しっかりUTCで上書きされてました。

データベース単位でタイムゾーン変更クエリを流してみます。

```sql
ALTER DATABASE practice SET timezone TO 'Asia/Tokyo'
SHOW timezone
```

<img width="618" alt="スクリーンショット 2019-04-15 2.50.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/b9866507-2e33-9861-e7f1-ec0a9454d3a2.png">

変化なし。

次はセッション単位で変更してみます。

```sql
SET timezone TO 'Asia/Tokyo';
SHOW timezone
```

<img width="620" alt="スクリーンショット 2019-04-15 2.51.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/560f6974-b378-0d48-703a-3cbf45e94ac2.png">

変わりました。ただしこれは再接続するとまたUTCに戻ります。

つまりセッション単位で何かしらエディター側で設定が上書きされていることがわかります。
でも毎回打つのはいやです。

# linuxのタイムゾーンを変えてみる
コンテナの中のタイムゾーンを変えたら変化があるかもしれないと思って試してみました。

現在値の確認。

```bash
docker exec -it postgres_practice ls -l /etc/localtime                                                                                                                月  4/15 02:56:35 2019
lrwxrwxrwx 1 root root 27 Mar 26 12:00 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC
```

更新。

```bash
docker exec -it postgres_practice ln -sf  /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

確認。

```bash
docker exec -it postgres_practice date
Mon Apr 15 02:57:25 JST 2019
```

PostgreSQLに繋いでエディターで確認。
<img width="605" alt="スクリーンショット 2019-04-15 3.15.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/0cf8d9e9-7bc1-0c97-af84-8b042edb6337.png">

変わらない...

下記コマンドを実施して効果なし。

```
docker exec -it postgres_practice /bin/bash
root:/# echo "Asia/Tokyo" > /etc/timezone
root:/# dpkg-reconfigure -f noninteractive tzdata

Current default time zone: 'Asia/Tokyo'
Local time is now:      Mon Apr 15 03:02:37 JST 2019.
Universal Time is now:  Sun Apr 14 18:02:37 UTC 2019.
```

# 接続時にオプションを指定する

DataGripのFAQにこんな記述がありました。

```
DataGrip shows time in local time zone, I want it to be shown in UTC, what should I do?
Go to Advanced tab of datasource and put -Duser.timezone=UTC into VM options field.
```
https://intellij-support.jetbrains.com/hc/en-us/articles/115000877044-DataGrip-FAQ

local time zoneになってしまうから明示的にオプションでタイムゾーンを指定しろと書いてます。
上記の手順で変わらない理由はよくわかりませんが試してみます。

<img width="732" alt="スクリーンショット 2019-04-15 3.32.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/611c801f-ce25-2b4d-7429-fc81ebab28f9.png">

これで確認してみると変わりました。
<img width="608" alt="スクリーンショット 2019-04-15 3.33.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13766/c22121bc-5d16-1c7a-d33b-64167f1d5445.png">


# まとめ
調査した結果、タイムゾーンを指定するためには

- `SET timezone TO 'Asia/Tokyo'` を実行する
- オプションで指定する

の2パターンあることがわかりました。
エディターで指定することで設定後は意識することなくAsia/Tokyoで接続できるようになるので、この対応をしておくと基本的には安心だと思います。

具体的な原因は分かり次第追記しようと思います。