2017-06-03

Hard times with Ansible's to_datetime filter

I was a bit stupid. Took me some time to figure out how this is supposed to work, so here it is.

In Ansible 2.2 there is a new "to_datetime" filter (see bottom of that section) which transforms datetime string to datetime object.

Basic usage to convert string to datetime object, not that useful in this form:

$ ansible -c local -m debug -a "var=\"'2017-06-01 20:30:40'|to_datetime\"" localhost

localhost | SUCCESS => {
    "'2017-06-01 20:30:40'|to_datetime": "2017-01-06 20:30:40", 
    "changed": false
}

You can parse datetime string with arbitrary format (see python documentation for formatting options):

$ ansible -c local -m debug -a "var=\"'06/01/2017'|to_datetime('%m/%d/%Y')\"" localhost

localhost | SUCCESS => {
    "'06/01/2017'|to_datetime('%m/%d/%Y')": "2017-06-01 00:00:00", 
    "changed": false
}

In my case I wanted to parse start and end date of some registered task in ansible playbook (so in playbook string to parse would be registered_variable.start). Maybe you do not want datetime object, but UNIX timestamp from that (notice extra parenthesis):

$ ansible -c local -m debug -a "var=\"('2017-06-01 20:30:40.123456'|to_datetime('%Y-%m-%d %H:%M:%S.%f')).strftime('%s')\"" localhost

localhost | SUCCESS => {
    "('2017-06-01 20:30:40.123456'|to_datetime('%Y-%m-%d %H:%M:%S.%f')).strftime('%s')": "1496341840", 
    "changed": false
}

But actually I just wanted to know how much time given task took, so I can simply substract two datetime objects and then use .seconds of the resulting timedelta object:

$ ansible -c local -m debug -a "var=\"( '2017-06-01 20:30:40.123456'|to_datetime('%Y-%m-%d %H:%M:%S.%f') - '2017-06-01 20:29:35.234567'|to_datetime('%Y-%m-%d %H:%M:%S.%f') ).seconds\"" localhost

localhost | SUCCESS => {
    "( '2017-06-01 20:30:40.123456'|to_datetime('%Y-%m-%d %H:%M:%S.%f') - '2017-06-01 20:29:35.234567'|to_datetime('%Y-%m-%d %H:%M:%S.%f') ).seconds": "64", 
    "changed": false
}

In pre 2.2 version, you can use this inefficient call of local date command (you do not have to worry about that ugly '\\\"' escaping when in playbook):

$ ansible -c local -m debug -a "var=\"lookup('pipe', 'date -d \\\"2017-06-01 20:30:40.123456\\\" +%s')\"" localhost

localhost | SUCCESS => {
    "changed": false, 
    "lookup('pipe', 'date -d \"2017-06-01 20:30:40.123456\" +%s')": "1496341840"
}
Good luck!