【Linux】dateコマンドでよく使うフォーマット(前月/翌月のデータ取得は注意)

# よく使うフォーマット

dateコマンドでフォーマット指定する事がありますが、指定方法をよく忘れてしまうので、メモしておきます。
ファイルのリネームやら、スクリプトが終わった時間を書き込む時に使います。


```shell_session:YYYY-MM-DD
[root@localhost tmp]# date '+%F'
2022-09-23
```

```shell_session:YYYY-MM-DD 曜日(省略形)
[root@localhost tmp]# date '+%F %a'
2022-09-23 金
```

```shell_session:YYYY-MM-DD hh:mm:ss
[root@localhost tmp]# date '+%F %T'
2022-09-23 22:10:09
```

```shell_session:YYYYMMDDhhmmss
[root@localhost tmp]# date '+%Y%m%d%H%M%S'
20220923221309
```

```shell_session:前日/翌日の日付取得
#前日

[root@localhost tmp]# date --date='1 days ago'
2022年  9月 22日 木曜日 22:46:54 JST

#翌日

[root@localhost tmp]# date --date='1 days'
2022年  9月 24日 土曜日 22:46:56 JST
```

よく使うオプションは下記に抜粋。
もっとオプション知りたいよという方は、`info date`をコンソールで実行しましょう。または、ググりましょう。

| オプション名 |    効果    |
|     ---     |    ---     |
|     %Y      |   YYYY(年) |
|     %m      |    mm(月)  |
|     %d      |    dd(日)  |
|     %H      |    hh(時)  |
|     %M      |    mm(分)  |
|     %S      |    ss(秒)  |
|     %F      |    %Y-%m-%d と同じ  |
|     %T      |    %H:%M:%S と同じ  |
|     %A      |    曜日 　 |
|     %a      |    曜日(省略形)  |
|     --date    |   フォーマットを指定して、日時を表記する　|


## 前月/翌月のデータを取得したい場合は注意

前月/翌月のデータを取得したい場合で、2/4/6/9/11月のデータを月末等に取得しようとすると想定通りに取得出来ない事がありました。
3/31の1か月前のデータを取得しようとすると、3/3のデータが返ってきます。2/31で取得しようして、この事象が発生しているよう見えます。(カレンダー上に2/31は存在していないので、2/28 + 3日分 のデータを加算して、3/3のデータを返しているのでしょうか？詳しくは不明。)

カレンダー上に存在しない日付だと、上記のような動きになるように見えます。

一応実行結果を載せておきます。
cron等で動かすとなると、注意が必要です。


```shell_session:想定通りいかないパターン
#前月取得

[root@localhost ~]# date --date '2022/03/31 1 month ago'
2022年  3月  3日 木曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/05/31 1 month ago'
2022年  5月  1日 日曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/07/31 1 month ago'
2022年  7月  1日 金曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/10/31 1 month ago'
2022年 10月  1日 土曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/12/31 1 month ago'
2022年 12月  1日 木曜日 00:00:00 JST

#翌月取得

[root@localhost ~]# date --date '2022/01/31 1 month'
2022年  3月  3日 木曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/03/31 1 month'
2022年  5月  1日 日曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/05/31 1 month'
2022年  7月  1日 金曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/08/31 1 month'
2022年 10月  1日 土曜日 00:00:00 JST
[root@localhost ~]# date --date '2022/10/31 1 month'
2022年 12月  1日 木曜日 00:00:00 JST
```


私が前月/翌月を取得したい場合は、以下のコマンドで取得します。
当月/前月 or 翌月に同じ日が存在すれば、前の月/次の月という観点での取得は行えます。
--dateのフォーマットを指定する際に、+%Y%m01で当月1日を指定して、その一か月前の日付を取得しています。
20日のデータが欲しい場合等は、+%Y%m20で指定するとよいです。

```shell_session
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months ago"
```

意図した通りに動くかをテストします。
`date --set`で日付変更していきます。
今回はスナップショット取得しておいて、時刻変更前に戻れるようにしておきました。

2月は想定通り動かないパターンがある事が分かっているので、分かっている範囲で検証を行っていきます。

```shell_session:

[test_01@localhost ~]$ date
2022年  9月 24日 土曜日 11:33:32 JST

#2月分_前月取得

[root@localhost ~]# date --set "2022-03-29"
2022年  3月 29日 火曜日 00:00:00 JST
[root@localhost ~]# date
2022年  3月 29日 火曜日 00:00:01 JST
[root@localhost ~]# date --date "1 months ago"
2022年  3月  1日 火曜日 00:00:03 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months ago"
2022年  2月  1日 火曜日 00:00:00 JST

[root@localhost ~]# date --set "2022-03-30"
2022年  3月 30日 水曜日 00:00:00 JST
[root@localhost ~]# date
2022年  3月 30日 水曜日 00:00:01 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months ago"
2022年  2月  1日 火曜日 00:00:00 JST

[root@localhost ~]# date --set "2022-03-31"
2022年  3月 31日 木曜日 00:00:00 JST
[root@localhost ~]# date
2022年  3月 31日 木曜日 00:00:01 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months ago"
2022年  2月  1日 火曜日 00:00:00 JST

#2月分_翌月取得

[root@localhost ~]# date --set "2022-01-29"
2022年  1月 29日 土曜日 00:00:00 JST
[root@localhost ~]# date
2022年  1月 29日 土曜日 00:00:09 JST
[root@localhost ~]# date --date "1 months"
2022年  3月  1日 火曜日 00:00:12 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months"
2022年  2月  1日 火曜日 00:00:00 JST

[root@localhost ~]# date --set "2022-01-30"
2022年  1月 30日 日曜日 00:00:00 JST
[root@localhost ~]# date
2022年  1月 30日 日曜日 00:00:01 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months"
2022年  2月  1日 火曜日 00:00:00 JST

[root@localhost ~]# date --set "2022-01-31"
2022年  1月 31日 月曜日 00:00:00 JST
[root@localhost ~]# date
2022年  1月 31日 月曜日 00:00:01 JST
[root@localhost ~]# date --date "`date '+%Y%m01'` 1 months"
2022年  2月  1日 火曜日 00:00:00 JST

```

取得出来ています。


## 終わりに(前月のデータ取得しようとして、ハマりました。)

月末分のデータ比較をする事があったのですが、意図した通りにデータが整形出来ていないとドツボにハマってしまいました。(テストで気づいた)

こういう事が起こるかもしれないから、エラー吐く仕組みを考えとく必要があるかな、、
私はデータ整形の都度、想定通りのデータが取得出来ているかを確認するようにif文で書いて対応しました。コードが長くなってしまいましたが、、良い方法がすぐに思いつかなかったです。