zaki work log

作業ログやら生活ログやらなんやら

[Ansible] to_datetime フィルタを使って文字列をdatetimeオブジェクトに変換

AnsibleでWed Feb 10 09:17:08 JST 2021という表記の文字列をdatetimeオブジェクトに変換するには、to_datetimeフィルターを使う。
使用例はフィルターのページの「Handling dates and times」に使い方が載っているのでここに書かれている通り。

内部実装はPythonのstrptime()が使用されているので、フォーマットの指定はPythonのドキュメントを見るとよい。

def to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
    return datetime.datetime.strptime(string, format)

datetimeオブジェクトにすれば各メソッドが使用できるため、UNIX Epochにして比較するなど簡単になる。(←C/Perl育ちの秒で管理したい人間の発想)

環境

サンプルコード

    - name: to_datetime
      vars:
        str_sample: "2016-08-14 20:00:12"
        str_year: "2021"
        str_ymdhms: 2021.02.10 09-15-20
        str_jst: Wed Feb 10 09:17:08 JST 2021
        str_offset: Wed Feb 10 09:17:08 +0900 2021
      debug:
        msg:
          - "{{ str_sample | to_datetime }}"
          - "{{ str_year | to_datetime('%Y') }}"
          - "{{ str_ymdhms | to_datetime('%Y.%m.%d %H-%M-%S') }}"
          - "{{ str_jst | to_datetime('%a %b %d %H:%M:%S %Z %Y') }}"
          - "{{ str_offset | to_datetime('%a %b %d %H:%M:%S %z %Y') }}"
          - "{{ (str_jst | to_datetime('%a %b %d %H:%M:%S %Z %Y')).timestamp() }}"  # 型はfloat ('1612916228.0')
          - "{{ lookup('pipe', 'date +%s') }}"

実行結果

ok: [localhost] => 
  msg:
  - '2016-08-14 20:00:12'
  - '2021-01-01 00:00:00'
  - '2021-02-10 09:15:20'
  - '2021-02-10 09:17:08'
  - '2021-02-10 09:17:08+09:00'
  - '1612916228.0'
  - '1613054485'

書式について

デフォルトの書式

ドキュメントの以下コメント、

Default date format is %Y-%m-%d %H:%M:%S but you can pass your own format

および、実装もそうなってる通り、フィルター使用時に書式を何も指定しなければ%Y-%m-%d %H:%M:%Sとなる。
任意のフォーマット文字列を指定することも可能。

タイムゾーン

タイムゾーンについては実行環境のロケールPythonバージョンに依存するので注意。
(書式(抜粋)についても下記記事参照)

zaki-hmkc.hatenablog.com

  • %z

    • サンプルコードのstr_offsetにおける+0900の部分を解釈するが、Python 2系で動くAnsibleでは使用できない。
    • エラー:

      the field 'args' has an invalid value ({u'msg': [u"{{ str_offset | to_datetime('%a %b %d %H:%M:%S %z %Y') }}"]}), and could not be converted to an dict.The error was: 'z' is a bad directive in format '%a %b %d %H:%M:%S %z %Y'

  • %Z

    • サンプルコードのstr_jstにおけるJSTの部分を解釈するが、実行OSのタイムゾーン設定がJSTでないと使用できない。
    • エラー:

      the field 'args' has an invalid value ({u'msg': [u"{{ str_jst | to_datetime('%a %b %d %H:%M:%S %Z %Y') }}"]}), and could not be converted to an dict.The error was: time data 'Wed Feb 10 09:17:08 JST 2021' does not match format '%a %b %d %H:%M:%S %Z %Y'