Time range condition template

I realise I am not able to do this to check if the current time is within either one of two ranges set by input_datetime values:

  - condition: or
    conditions:
      - condition: time
        after: {{ input_datetime.lounge_ac_am_on_time }}
        before: {{ input_datetime.lounge_ac_am_off_time }}
      - condition: time
        after: {{ input_datetime.lounge_ac_pm_on_time }}
        before: {{ input_datetime.lounge_ac_pm_off_time }}

and that I’m going to have to use a condition: template but I have no idea how. Anyone got any pointers on how to accomplish this?

what is the exact logic that you’re trying to achieve which doesn’t work with the above?
the way you currently wrote it, if the time is within one of the ranges, then the condition would return true as at least 1 condition is true (set with OR)

I assumed {{ input_datetime.lounge_ac_am_on_time }} would have to be in a condition: template rather than condition: time to actually evaluate. Though I haven’t tested it yet.

I tested it. It did not work.

Hmm. Not like this either:

  - condition: or
    conditions:
      - condition: template 
        value_template: {{ (states('sensor.time') >= states.input_datetime.lounge_ac_am_on_time.state) and (states('sensor.time') < states.input_datetime.lounge_ac_am_off_time.state) }}
      - condition: time
      - condition: template 
        value_template: {{ (states('sensor.time') >= states.input_datetime.lounge_ac_pm_on_time.state) and (states('sensor.time') < states.input_datetime.lounge_ac_pm_off_time.state) }}

Error loading /config/configuration.yaml: invalid key: "OrderedDict([("(states('sensor.time') &gt;= states.input_datetime.lounge_ac_am_on_time.state) and (states('sensor.time') &lt; states.input_datetime.lounge_ac_am_off_time.state)", None)])" in "/config/automations.yaml", line 569, column 0

Found another way not that does not pass validation:

  - condition: or
    conditions:
      - condition: template 
        value_template: "{{ (states('sensor.time') >= states.input_datetime.lounge_ac_am_on_time.state[0:5]) and (states('sensor.time') < states.input_datetime.lounge_ac_am_off_time.state[0:5]) }}"
      - condition: time
      - condition: template 
        value_template: "{{ (states('sensor.time') >= states.input_datetime.lounge_ac_pm_on_time.state[0:5]) and (states('sensor.time') < states.input_datetime.lounge_ac_pm_off_time.state[0:5]) }}"

You need to add todays date to your input_datetimes and you can use now() to check against. Also, you can just do the check in seconds:

condition:
  - condition: template
    value_template: >
      {% set current_date_string = now().strftime("%Y-%m-%d ") %}
      {% set current_time = now().timestamp() %}
      {% set lounge_am_start = strptime(date+state('input_datetime.lounge_ac_am_on_time'), '%Y-%m-%d %H:%M').timestamp() %}
      {% set lounge_am_end = strptime(date+state('input_datetime.lounge_ac_am_off_time'), '%Y-%m-%d %H:%M').timestamp() %}
      {% set lounge_pm_start = strptime(date+state('input_datetime.lounge_ac_pm_on_time'), '%Y-%m-%d %H:%M').timestamp() %}
      {% set lounge_pm_end = strptime(date+state('input_datetime.lounge_ac_pm_off_time'), '%Y-%m-%d %H:%M').timestamp() %}
      {{ lounge_am_start <= current_time <= lounge_am_end or lounge_pm_start <= current_time <= lounge_pm_end }}

ok, so are you trying to ensure that current time (e.g. now()) is between these timestamps?
If so that’s what you need:

  - condition: or
    conditions:
    - condition: template
      value_template: '{{ (as_timestamp(now()) -(states.input_datetime.lounge_ac_am_on_time.attributes.timestamp | default(0)) | int > 0) and ((states.input_datetime.lounge_ac_am_off_time.attributes.timestamp  - as_timestamp(now()) | default(0)) | int > 0)}}'
    - condition: template
      value_template: '{{ (as_timestamp(now()) -(states.input_datetime.lounge_ac_pm_on_time.attributes.timestamp | default(0)) | int > 0) and ((states.input_datetime.lounge_ac_pm_off_time.attributes.timestamp  - as_timestamp(now()) | default(0)) | int > 0)}}'

@tom_l I’ve never used input_datetimes, so if they have timestamps then it’s even easier. Assuming the timestamp has today’s date.

Also, you don’t need default(0) when using this method because strings converted to int’s default to zero when it can’t convert (if the string returns any character that’s not a number).

condition:
  - condition: template
    value_template: >
      {% set current_time = now().timestamp() %}
      {% set am_start = states('input_datetime.lounge_ac_am_on_time', 'timestamp') | int %}
      {% set am_end = states('input_datetime.lounge_ac_am_on_time', 'timestamp') | int %}
      {% set pm_start = states('input_datetime.lounge_ac_am_on_time', 'timestamp') | int %}
      {% set pm_end = states('input_datetime.lounge_ac_am_on_time', 'timestamp') | int %}
      {{ am_start <= current_time <= am_end or pm_start <= current_time <= pm_end }}
1 Like

The datetimes I am using have time only. And this trigger has worked for me before:

trigger:
  platform: template
  value_template: "{{ states('sensor.time') == (states.input_datetime.lounge_ac_pm_on_time.state[0:5]) }}"

So I was attempting to adapt it for a condition for a range of times.

However I have just discovered an errant “)” in a completely unrelated automation miles away from where I was working that wasn’t there when I validated the config yesterday. This was causing errors unrelated to this current effort. Ugh.

It is unlikely that my time ranges will ever cross a date boundary but I like the the idea of accounting for it just in case.

Thank you both for your ideas. I’ll have a bit of an experiment and let you know how I go.

1 Like

Success. This passes the validation check but the off times must be > the on times (i.e. not cross a date boundary).

  - condition: or
    conditions:
      - condition: template
        value_template: "{{ (states('sensor.time') >= states.input_datetime.lounge_ac_am_on_time.state[0:5]) and (states('sensor.time') < states.input_datetime.lounge_ac_am_off_time.state[0:5]) }}"
      - condition: template
        value_template: "{{ (states('sensor.time') >= states.input_datetime.lounge_ac_pm_on_time.state[0:5]) and (states('sensor.time') < states.input_datetime.lounge_ac_pm_off_time.state[0:5]) }}"

This will do for now. Sleep time.

That’s comparing strings and will not work.

let me clarify, that will pass config check but will not properly give you the correct true/false time checks.

Really?

It has been for the trigger I posted above. And it works in the template editor.

Ah. Never mind. == works for strings!

Ok back to the drawing board. Tomorrow.

you should just be able to copy and paste what @lolouk44 wrote or what I wrote without any issues…

1 Like

and just to show you:

Ha. Good example.

FYI what I wrote above is what I use for my holidays automation so I know it works
however I use a date and time input_date…

Ok I’ll paste it in and see what happens tomorrow morning. Thanks for your help folks.

1 Like

Oh good lord. There’s another problem I’ve just disovered in my action template,

This:

{% if (states.input_select.lounge_ac_mode.state != 'Normal Cool')%}

Needs to account for ‘Silent Cool’ and ‘Powerful Cool’ as well. Is there a way to test for the string ‘Cool’ in states.input_select.lounge_ac_mode.state?