I don't understand gather_subset

This is not correct (at least for the builtin plugins, and while it would theoretically be possible for other plugins to ignore updates it would break the API expectations and usually be a bad idea.)

The cache affects whether facts that you have not gathered in the current run are available, and (in some configurations) whether play-level gathering happens. Gathered facts are always updated.

- hosts: localhost
  gather_facts: false
  tasks:
    - name: Uses the cached value because facts were not gathered
      debug:
        msg: "{{ ansible_facts.date_time.time }}"

    - gather_facts:

    - name: Has the freshly gathered value
      debug:
        msg: "{{ ansible_facts.date_time.time }}"

    - gather_facts:
        gather_subset: "!all,!date_time"

    - name: Still the fresher value
      debug:
        msg: "{{ ansible_facts.date_time.time }}"

    - gather_facts:
        gather_subset: date_time

    - name: Refreshed again
      debug:
        msg: "{{ ansible_facts.date_time.time }}"
PLAY [localhost] ***************************************************************

TASK [Uses the cached value because facts were not gathered] *******************
ok: [localhost] =>
    msg: '14:51:14'

TASK [gather_facts] ************************************************************
ok: [localhost]

TASK [Has the freshly gathered value] ******************************************
ok: [localhost] =>
    msg: '14:53:41'

TASK [gather_facts] ************************************************************
ok: [localhost]

TASK [Still the fresher value] *************************************************
ok: [localhost] =>
    msg: '14:53:41'

TASK [gather_facts] ************************************************************
ok: [localhost]

TASK [Refreshed again] *********************************************************
ok: [localhost] =>
    msg: '14:53:43'