Here’s the sensor I use to calculate the “last given weekday in a given month in a given year”. It’s been adapted to find the “last Wednesday in the current month in the current year”.
last_wednesday:
value_template: >
{% set isoweekday = 3 %}
{% set month = now().month %}
{% set year = now().year %}
{% if month == 12 %} {% set month = 1 %} {% set year = year + 1 %}
{% else %} {% set month = month + 1 %}
{% endif %}
{% set lastday = now().date().replace(year=year).replace(month=month).replace(day=1) - timedelta(days=1) %}
{% set ns = namespace(lastday = lastday) %}
{% for i in range(1, 8) if ns.lastday.isoweekday() != isoweekday %}
{% set ns.lastday = ns.lastday - timedelta(days=1) %}
{% endfor %}
{{ ns.lastday }}
It’s easily adapted for any day, month, and year. For example, to find the last Friday of July in 2022, simply set:
{% set isoweekday = 5 %}
{% set month = 7 %}
{% set year = 2022 %}
Another popular need is to find the nth weekday of a month (4th Wednesday of the current month) in the current year.
fourth_wednesday:
value_template: >
{% set nth = 4 %}
{% set month = now().month %}
{% set isoweekday = 3 %}
{% set d = now().date().replace(month=month).replace(day=1) %}
{% set adj = (isoweekday - d.isoweekday()) % 7 %}
{{ d + timedelta(days=adj) + timedelta(weeks=nth-1) }}
FWIW, it can be reduced to:
fourth_wednesday:
value_template: >
{{ now().date().replace(month=now().month).replace(day=1) +
timedelta(days=(3 - d.isoweekday()) % 7) + timedelta(weeks=4-1) }}
FWIW, the techniques used are based on common python examples. I had a need to to do this in python_script and it was straightforward to convert them to Jinja2.
EDIT
Last chosen weekday of the month (Wednesday in this example).
{% set wd = 3 %} {# Wednesday is ISO weekday 3 #}
{% set (m, y) = (now().month, now().year) %}
{% set (m, y) = (1,y+1) if m==12 else (m+1,y) %}
{% set dt = now().date().replace(year=y, month=m, day=1) %}
{% set dt = dt + timedelta(days=wd - dt.isoweekday()) %}
{% set dt = dt - timedelta(days=7) %}
{{ dt }}