【Spring Boot】Date型の値が9時間ずれたときに確認・対応したことまとめ

Spring Bootで実装を進めていたところ、Date型の値が想定値-9時間となってしまいました。
その際に確認＆対応したことのまとめです。

## 環境
- OS：Windows10
- IDE：Eclipse2020-03
- Java：11
- MySQL：5.7
- Spring Boot：2.3.2

## 前提事項
- 日本標準時に設定するものとします。

## 確認内容

### 1. DBのタイムゾーンの設定確認
対象の値がDB由来の場合は、まず、DBの設定が正しくできているか確認しましょう。
以下ように、show variablesコマンドを実行します。

```sql:実行コマンド＆結果

> show variables like '%time_zone%';
+------------------+------------+
| Variable_name    | Value      |
+------------------+------------+
| system_time_zone | UTC        |
| time_zone        | Asia/Tokyo |
+------------------+------------+
```
日本標準時の場合は、time_zoneがAsia/Tokyoに設定されているはずです。
（defaultの場合は、system_time_zoneの値が参照されます。）
異なっている場合は設定ファイルmy.cnfの内容を以下のように変更しましょう。

```:/etc/my.cnf
[mysqld]
default-time-zone = 'Asia/Tokyo'
```

設定が完了したら、以下のコマンドを実行して、日本標準時で現在時刻が取得できることを確認します。

```sql:現在時刻確認コマンド
select now();
```


### 2. アプリケーションサーバーのタイムゾーンの設定確認
対象の値がDB由来でない場合、もしくは、DBの設定に問題がなかった場合はアプリケーションサーバーのタイムゾーンを確認しましょう。
一番手っ取り早い方法は例えば以下のようなコードを追記し、コンソールにサーバーの現在時刻を出力させる方法です。

```java:現在時刻出力コード
System.out.println("現在の時刻は" + new Date() + "です。");
```

上記によって、想定の結果が得られない場合は、環境変数への設定を行います。

#### (1) Eclipseを使ってプロジェクト起動する場合
以下の手順でサーバーのタイムゾーンを設定します。

① Eclipseのメニューバーにて、「実行」（①） > 「実行構成」（②）を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356958/5a8f7a70-382e-8cfe-eace-dbfe66a18774.png)

② Spring Boot アプリケーションの対象のアプリを選択し（①）、引数タブにて（②）VM引数欄に「-Duser.timezone=JST」と記載し（③）、「適用」を押下（④）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356958/5ff6fb11-abf7-7b2d-8dd5-cdc88803d4ab.png)

#### (2) サーバー上で起動する場合

jarファイルと同じ階層に、「jarファイルの名前.conf」という名前で設定ファイルを作成し、設定内容を記述。
jarファイルの名前がhoge.jarの場合は以下の通り。

```conf:hoge.conf
JAVA_OPTS="-Duser.timezone=Asia/Tokyo";
```

設定が完了したら、再起動して、時間が正しく設定されているか確認しましょう。

### 3. アプリケーションプロパティーファイルのJackson時刻設定の確認
上記1, 2でも想定の結果が得られなかった場合はアプリケーションプロパティーファイルに以下の記述を追加してみましょう。

```yml:application.yml
spring:
  jackson:
    dateFormat: yyyy-MM-dd HH:mm:ss
    time-zone: Asia/Tokyo
```
dateFormatの部分は任意。
表示させたい形式を記述します。

余談ですが、ソースコードで個別に形式変更することも可能！
例えば以下のように記述すると、「yyyy/MM/dd」形式になります。

```java:
@JsonFormat(pattern = "yyyy/MM/dd")
private Date createdAt;
```

## 終わりに
最初何が原因で時間がズレてるのかわからず、とても困惑しました。
順番に確認することで原因までたどりつけました！

他にも時間がズレる要素ありましたら、ぜひ教えてください！


## 参考
### 1. DBのタイムゾーンの設定確認
- [MySQLでタイムゾーンを設定する | Qiita](https://qiita.com/tailak/items/63dce2dd7dfe049b038e)
- [MySQL Now関数(現在時刻、日時を取得) | プログラミング入門サイト ～bituse～](https://bituse.info/mysql/35)

### 2. アプリケーションサーバーのタイムゾーンの設定確認
- [Java 日付型のタイムゾーンがGMT(-9時間）になってしまう不具合の解決方法 - Date, Calendar | ホームページ制作のサカエン](https://www.saka-en.com/java/java-gmt-date-calendar/)
- [【Java・SpringBoot】eclipse（STS）で起動するサーバーのタイムゾーンを変更する方法（JST->UTC）| 地方に引越し予定の30歳男がプログラマーを続けるためのブログ](https://layerprogram.com/javatimezone/)
- [Spring Bootで作ったWebアプリの時刻がイギリス時刻になった時は... | jildin workers](http://jildin.hatenablog.com/entry/2017/03/21/120000)
- [Tomcatのタイムゾーン設定(Eclipse) | ゆるふわエンジニアのブログ](http://j-levia.hatenablog.jp/entry/2018/07/11/141611)

### 3. アプリケーションプロパティーファイルのJackson時刻設定の確認
- [Spring BootのJackson時刻設定まとめ | hogepiyoエンジニアリング](http://hogepiyo.hatenablog.jp/entry/2015/11/11/190252)
- [JavaでDateをISO 8601 拡張形式で出力する | Qiita](https://qiita.com/purini-to/items/873036865d513ac933bf)