Condition: time with templates for after: and before:

In this script I want to find a given entry in the schedule that applies when the script is run. (The trigger is not based on time.)

sequence:
  - variables:
      index: 0
      schedule:
        - name: Morning
          after: "6:30"
          before: "10:00"
        - name: Midday
          after: "10:00"
          before: "15:00"
        - name: Evening
          after: "15:00"
          before: "21:30"
  - repeat:
      for_each: "{{ schedule }}"
      sequence:
        - condition: time
          after: '15:45'
          before: '2:30'
        - action: notify.persistent_notification
          metadata: {}
          data:
            message: "{{ repeat.item.name }}"

What I’d like to do, of course is:

        - condition: time
          after: '{{ repeat.item.after }}'
          before: '{{ repeat.item.before }}'
        - action: notify.persistent_notification
        ...

But, it does not seem like after: and before: accept a template.

I found a few posts about this, such as this one. (Although I don’t understand the need to convert to a timestamp vs. comparing datetime objects.)

Nice thing about the the time condition is you can be a bit sloppy on the time format (no leading zero, no seconds) AND it figures out if it crosses a midnight boundary.

Best I can think of is somthing like a template condition like:

{% set cur_day = now().strftime("%Y-%m-%d ") -%}
{% set cur_day = '2023-02-28 ' -%}



{% set fmat = "%Y-%m-%d %H:%M" -%}
{% set start_dt = strptime( cur_day ~ '15:00', fmat ) -%}
{% set end_dt = strptime( cur_day ~ '2:30', fmat ) -%}

{{ start_dt }} < {{ end_dt }} == {{ start_dt < end_dt }}

{% if start_dt > end_dt -%}
{% set end_dt = end_dt + timedelta(days=1) -%}
{% endif -%}
{{ start_dt }} < {{ end_dt }} == {{ start_dt < end_dt }}

Resulting in:

2023-02-28 15:00:00 < 2023-02-28 02:30:00 == False

2023-02-28 15:00:00 < 2023-03-01 02:30:00 == True

(I’m not worried about DST changes.)

The time condition configuration accepts a string time, so curious if there’s a way to use a variable for the string. Or do I need to go the template route?

Thanks,

Update: I’ll try the template solution by @Didgeridrew

That is a very old post from before we got improved datetime templating functions. You can definitely do this with datetime objectes instead of timestamps now.

e.g.

    {% set t_now = now() %}
    {% set t_on = today_at(states('input_datetime.mstr_bed_sunrise_sim_time')) %}
    {% set t_off = today_at(states('input_datetime.mstr_bed_sunrise_sim_time')) + timedelta(minutes=30)  %}
    {{ t_on <= t_now <= t_off }}

What does that mean? Can you clarify what your actual goal is?

Sure. In this case the script will return some values based on the time of day. Specifically, this is for a thermostat that changes the temp during the day. I don’t trigger on times because there’s other input such as a door or window being open or home.zone goes to zero.

But, to be clear, I’m not only trying to solve a specific issue, but (maybe more) to learn HA and templating.

In this case, the after: and before: seem like they could take a template with a string time of day. As I mentioned, the condition: time does have that nice feature of allowing spans across midnight (i.e. where the condition knows that after: 20:00 is before: 02:00).

Update: as for learning HA, I was looked for a way to use a more concise config (an array of times) to define the times and loop over them. My first write of this was a long list of conditions where each after: and before: were hard-coded in the script.

Is there a reason you specifically want to use a script?

Have you considered using either the TOD sensor integration or a template sensor?

Templated time of day sensor Example
template:
  - sensor:
      - name: Time of Day
        state: >
          {% set a = today_at("05:00")%}
          {% set b = today_at("07:00")%}
          {% set c = today_at("12:00")%}
          {% set d = today_at("18:00") %}
          {% set e = today_at("20:00")%}
          {% set f = today_at("01:00")%}
          {% set map = {
          a < now() <= b: 'Early Morning',
          b < now() <= c: 'Morning',
          c < now() <= d : 'Afternoon',
          d < now() <= e: 'Evening',
          e < now() < f + timedelta(days=1): 'Night',
          today_at() < now() <= f: 'Night',
          f < now() <= a: 'Late Night'
          } %}
          {{ map.get(True) }}

I use a template sensor to render an indentifier, then that ID sets which helpers to use to get the desired temperature values for the current situation.

No, because I was unaware of it! [1]

And it handles DST, although I’d need another map from “Morning” to what temps to set, which is probably fine.

I was assuming I’d do something like this to have all the configuration in one place:

      schedule:
        - name: Morning
          after: "6:30"
          before: "10:00"
          heat_temp: 67
          cool_temp: 78
        - name: Midday
          after: "10:00"
          before: "15:00"
          heat_temp: 60
          cool_temp: 80

I do like your template approach, and I could return heat/cool temps as well as the name. Plus, it catches that time after midnight that I missed in my first attempt.

Any reason to be concerned with having the template code run every minute vs a script that runs only when called? In my case that’s every 10 minutes or when there’s an event like a door left open or we leave the house.

BTW, I think you need less than or equal here to catch midnight.

today_at() <= now() <= f: 'Night',

Is there a reason why it is not possible to template like this for before: and after:? Or is it simply because it hasn’t been implemented?

        - condition: time
          after: '{{ repeat.item.after }}'
          before: '{{ repeat.item.before }}'
        - action: notify.persistent_notification
        ...

Thanks,

[1] I was just mentioning to a friend yesterday new to HA that “whatever it is you want to do in Home Assistant someone probably has already done it!”

That really depends on your equipment and needs, but, unless you’re running HA on a potato, the difference is likely negligible.

If you are concerned about it, you can use a trigger-based template sensor. That way you could have the sensor update as required or based on a Time Pattern trigger if you just want a longer interval.

Generally the answer to that type of question is “Because no one has bothered to develop it and submit a PR”. I’m not a developer, so I have no idea as to the feasibility of the idea, but sometimes PRs aren’t added because what they do can already be done other ways and adding them would add undue complication.