【Ansible】 Lookup プラグインで日付計算がしたい

### はじめに
 
- バージョン
  - ansible 2.9.7

　Ansibleの記事で、lookupプラグインのpipeを用いて今日の日付を取得するのはよく見かけるのですが、  
〇日後/〇日前といった日付計算をしている記事があまりなかったので、実際にPlaybookを書いてみます。

### 1. Playbook紹介

　Playbookを書きながら思ったのですが、Playbookの書き方よりもdateコマンドの使い方が重要です。
Playbookの最後の``date2 - date1(day)``の部分は、それぞれの日付を秒に変換し、差を
``60 * 60 * 24``で割ることで、date1とdate2の日数の差を計算しています。

```yaml
---
- name: "Date calculate test"
  hosts: localhost
  gather_facts: false
  vars:
    date1: "2022/05/20"
    date2: "2022/06/04"
  tasks:
    - name: "to datetime"
      set_fact:
        date1_datetime: "{{ date1 | to_datetime('%Y/%m/%d') }}"
        date2_datetime: "{{ date2 | to_datetime('%Y/%m/%d') }}"
        date1_second: "{{ (date1 | to_datetime('%Y/%m/%d')).timestamp() }}"
        date2_second: "{{ (date2 | to_datetime('%Y/%m/%d')).timestamp() }}"

    - name: "debug datetime"
      debug:
        msg:
          - "date1_datetime: {{ date1_datetime }}"
          - "date2_datetime: {{ date2_datetime }}"
          - "date1_second: {{ date1_second }}"
          - "date2_second: {{ date2_second }}"

    - name: "Date calculate"
      debug:
        msg:
          - >-
            date1_datetime:
              {{ date1_datetime }}
          - >-
            date1_datetime - 1 hour:
              {{ lookup('pipe','date -d "{{ date1_datetime }} 1 hour ago" "+%Y/%m/%d %H:%M:%S"') }}
          - >-
            date1_datetime + 1 hour:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 1 hour" "+%Y/%m/%d %H:%M:%S"') }}
          - >-
            date1_datetime - 10 day:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 10 day ago" "+%Y/%m/%d"') }}
          - >-
            date1_datetime + 15 day:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 15 day" "+%Y/%m/%d"') }}
          - >-
            date1_datetime + 2 week:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 2 week" "+%Y/%m/%d"') }}
          - >-
            date1_datetime + 1 month:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 1 month" "+%Y/%m/%d"') }}
          - >-
            date1_datetime + 1 year:
              {{ lookup('pipe', 'date -d "{{ date1_datetime }} 1 year" "+%Y/%m/%d"') }}
          - >-
            date2 - date1(day):
              {{ ((date2_second | int) - (date1_second | int)) / (60 * 60 * 24) }}
```

**ポイント**

1. to_datetimeフィルタ

   - to_datetimeフィルタを使って文字列をdatetimeオブジェクトに変換することが出来ます
 
     ```text
     {{ 変換する文字列 | to_datetime('変換する文字列のフォーマット')
     ```

2. dateコマンド

   - 以下のフォーマットで日付計算が行えます
 
     ```text
     date -d "計算元のdatetimeオブジェクト 計算用文字列" "出力フォーマット(+%Y/%m/%dなど)"
     ```

   - 計算用文字列では、秒(seconds)/分(minites)/時(hour)/日(day)/週(week)/月(month)/年(year)  
   などが使えます。記載例は以下です。**時間を戻す場合は最後にagoを付けます。**
     - 時間を進める場合

     ```text
     10 day
     ```

     - 時間を戻す場合

     ```text
     10 day ago
     ```

### 2. 実行結果

　以下の実行結果より、想定通り計算できていることがわかります。

```text
PLAY [Date calculate test] *****************************************************

TASK [to datetime] *************************************************************
ok: [localhost]

TASK [debug datetime] **********************************************************
ok: [localhost] => 
  msg:
  - 'date1_datetime: 2022-05-20 00:00:00'
  - 'date2_datetime: 2022-06-04 00:00:00'
  - 'date1_second: 1653004800.0'
  - 'date2_second: 1654300800.0'

TASK [Date calculate] **********************************************************
ok: [localhost] => 
  msg:
  - |-
    date1_datetime:
      2022-05-20 00:00:00
  - |-
    date1_datetime - 1 hour:
      2022/05/19 23:00:00
  - |-
    date1_datetime + 1 hour:
      2022/05/20 01:00:00
  - |-
    date1_datetime - 10 day:
      2022/05/10
  - |-
    date1_datetime + 15 day:
      2022/06/04
  - |-
    date1_datetime + 2 week:
      2022/06/03
  - |-
    date1_datetime + 1 month:
      2022/06/20
  - |-
    date1_datetime + 1 year:
      2023/05/20
  - |-
    date2 - date1(day):
      15.0

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```



### 参考記事

[Lookup プラグイン(pipe) - Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/plugins/lookup/pipe.html)
[Examples of date (GNU Coreutils 9.1)](https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html)