Both utc and today are strings (a.k.a. "AnsibleUnsafeText"), so you can't subtract one from the other. If they were both Python datetime objects, then you could get a difference like that (or something similar).
I'm evidently not communicating clearly, but please know that I have a lot of sympathy for the frustration you're encountering with data manipulation in Ansible. Been there; got some scorched t-shirts out of it. I see what you're trying to do, and, while you're not wrong, and you can make Ansible do it that way, it involves a lot more "code" than is necessary to solve your problem.
I say that because you don't need "today" or "age". Nor do you need to manipulate any of the kerberos password "__datetime__" values, or convert anything to datetime objects or take their differences. The only new piece of data you need is a string representing the date that was 180 days ago.
Here's another shot at demonstrating what I'm suggesting.
---
- name: KrbPasswordExpiration date/time demo II
hosts: localhost
vars:
user_show:
json:
result:
result:
krbpasswordexpiration: [
{ "__datetime__": "20210107191401Z", "id": "user1" },
{ "__datetime__": "20210213123102Z", "id": "user2" },
{ "__datetime__": "20210327062203Z", "id": "user3" },
{ "__datetime__": "20210411130904Z", "id": "user4" },
{ "__datetime__": "20210519124605Z", "id": "user5" },
{ "__datetime__": "20210604225106Z", "id": "user6" },
{ "__datetime__": "20210711531407Z", "id": "user7" },
{ "__datetime__": "20210818191408Z", "id": "user8" },
]
tasks:
- name: Save "now - 180 days" in krbpasswordexpiration format
set_fact:
krbpassworddeadline: '{{ lookup(''pipe'',
''date -u --date="now - 180 days" +%Y%m%d000000Z'') }}'
- name: Disable accounts of users with old passwords.
debug:
msg: |
Cutoff KRB date: {{ krbpassworddeadline }}
{% for item in user_show.json.result.result.krbpasswordexpiration %}
{% if krbpassworddeadline > item["__datetime__"] %}
!!! Disable account for "{{ item['id'] }}" (pw exp: {{ item["__datetime__"] }}).
{% else %}
--- Retain account for "{{ item['id'] }}" (pw exp: {{ item["__datetime__"] }}).
{% endif %}
{% endfor %}
That produces the following output (given that this was run on 2021-11-17):
TASK [Save "now - 180 days" in krbpasswordexpiration format] *******************
ok: [localhost] => changed=false
ansible_facts:
krbpassworddeadline: 20210522000000Z
TASK [Disable accounts of users with old passwords.] ***************************
ok: [localhost] =>
msg: |-
Cutoff KRB date: 20210522000000Z
!!! Disable account for "user1" (pw exp: 20210107191401Z).
!!! Disable account for "user2" (pw exp: 20210213123102Z).
!!! Disable account for "user3" (pw exp: 20210327062203Z).
!!! Disable account for "user4" (pw exp: 20210411130904Z).
!!! Disable account for "user5" (pw exp: 20210519124605Z).
--- Retain account for "user6" (pw exp: 20210604225106Z).
--- Retain account for "user7" (pw exp: 20210711531407Z).
--- Retain account for "user8" (pw exp: 20210818191408Z).