Template sensor... timing issue

I have this template sensor:-

- sensor:
    - name: "Central Heating Calculated Setpoint"
      unique_id: central_heating_calculated_setpoint
      state: >
        {% set normal = states('input_number.central_heating_normal_set_point') | float(0) %}
        {% set morning = states('input_number.central_heating_morning_temperature_adjust') | float(0) %}
        {% set evening = states('input_number.central_heating_evening_temperature_adjust') | float(0) %}
        {% set morning_until = today_at(states('input_datetime.central_heating_morning_is_until')) %}
        {% set evening_starts = today_at(states('input_datetime.central_heating_evening_starts_at')) %}
        {% set adj = states('sensor.central_heating_weather_setpoint_adjust') | float(0) if is_state('input_boolean.central_heating_external_temperature_adjust','on') else 0 %}
        {% if now() < (morning_until-timedelta(seconds=1)) %}
          {{ normal + morning + adj }}
        {% elif now() >= (evening_starts-timedelta(seconds=1)) %}
          {{ normal + evening + adj }}
        {% else %}
          {{ normal + adj }}
        {% endif %}

I have an automation that fires at exactly the defined morning_until and also evening_starts times to read the value from the sensor.

My original time evaluations of now() in the if statement did not include the timedeltas that you can see in the current implementation, because for some reason, the template returned incorrect values when my automation requests the value on EXACTLY the morning_ends or evening_starts time. (If called manually just a second later, the template rendered the correct values)

Is there a more elegant way of dealing with this edge case ?

You’ve created a sensor to supply the correct temperature based on the current time, so why not just trigger on that sensor’s state change instead of a strict time trigger?

If your automation doesn’t already, you may also want to include a trigger for when HA restarts to cover the edge case of HA being off during the time when the sensor would change.

When you say you get incorrect values, you mean that the value isn’t what you were expecting?
Example - it’s exactly morning_until (let’s say, 6am), and when your automation runs, now() returns 6am - but likely a few microseconds after, so your first if fails because now() is larger. Your elif fails because now() is probably less than evening_starts (lets assume 8pm), so you end up with the result from your else.

If that’s the case, then it’s just because of now()'s precision. If you want it to be less exact, you’d want to reduce the precision. You could do that with now().replace(second=0, microsecond=0) which would give you to the minute (zeroing the seconds and microseconds).

Such an obvious answer that I was totally snow blind to.