Value Template Syntax Help

Hello,

Looking to incorporate a date 7/4 to use. So if the
first part is not 7/4 and day of week is 6,7 then time is 22:00
second part is if not 7/4 and day of week is 1,2,3,4,5 time is 21:30
third part is, does not matter what day of week, just it is 7/4 then the time is 23:00

What am I doing wrong?

value_template: >
          {{ (now().isoweekday() in (6,7) and is_state('sensor.time', '22:00') and (now().month != 7 and now().day != 4))) or
          (now().isoweekday() in (1,2,3,4,5) and is_state('sensor.time', '21:30') and (now().month != 7 and now().day != 4))) or
		  (now().month == 7 and now().day == 4) and is_state('sensor.time', '23:00')) }}

One too many parentheses on the first two lines and one misplaced on the last.

Try:

value_template: >
  {{ (now().isoweekday() in (6,7) and is_state('sensor.time', '22:00') and (now().month != 7 and now().day != 4)) or
    (now().isoweekday() in (1,2,3,4,5) and is_state('sensor.time', '21:30') and (now().month != 7 and now().day != 4)) or
    (now().month == 7 and now().day == 4 and is_state('sensor.time', '23:00')) }}

It helps if your config editor has a bracket colour matching plug-in.

Thank you! Just curious, with my code, how could I specify a date in MM-DD type format to simplify it?

Would something like this work?

value_template: >
  {{ (states('sensor.date')[-5:] != '07-04' and now().isoweekday() in (6,7) and is_state('sensor.time', '22:00') ) or
    (states('sensor.date')[-5:] != '07-04' and now().isoweekday() in (1,2,3,4,5) and is_state('sensor.time', '21:30') ) or
    (states('sensor.date')[-5:] == '07-04' and is_state('sensor.time', '23:00')) }}

Should do. Use the template editor in the developer tools to test it.

There’s a lot of repetition in the template that makes it more challenging to comprehend its logic.
For example, it test if today is 6 or 7 and if it isn’t it repeats the test to see if today is 1, 2, 3, 4, or 5.

When the repetitive parts are removed, the template is simplified to this:

        value_template: >
          {% set is_not_date = true if now().month != 7 or now().day != 4 else false %}

          {% if now().isoweekday() in (6,7) %}
             {{ is_state('sensor.time', '22:00') and is_not_date }}
          {% else %}
             {% if is_not_date %}
               {{ is_state('sensor.time', '21:30') }}
             {% else %}
               {{ is_state('sensor.time', '23:00')) }}
             {% endif %}
          {% endif %}

EDIT
Correction. Change logical AND to logical OR in the first line of value_template.

Thank you!

Hello,

I’ve noticed when experimenting with the snippet, I changed the month to 12 and day to 9 for this example. Where the weekday is 6 or 7, I changed the time to the current time for testing. It returned false. If I change the month comparison to ==, it returned true. How can I correct this to account for the month and date?

value_template: >
          {% set is_not_date = true if now().month != 12 and now().day != 9 else false %}

          {% if now().isoweekday() in (6,7) %}
             {{ is_state('sensor.time', '04:00') and is_not_date }}
          {% else %}
             {% if is_not_date %}
               {{ is_state('sensor.time', '21:30') }}
             {% else %}
               {{ is_state('sensor.time', '23:00') }}
             {% endif %}
          {% endif %}

A better example to see this is trying this in the template editor. It is 12/7, and this should be true since it is not 12/9

{% set is_not_date = true if now().month != 12 and now().day != 9 else false %}
{{ is_not_date }}

You’re right; I made a mistake.

Change the logical AND to a logical OR.

{% set is_not_date = true if now().month != 12 or now().day != 9 else false %}

Here are the results:

Thanks,

Another quick question. When I was testing this using today’s date in the set, and the else should be the one that is true when the time is on 12/7, right?

It shows false.

value_template: >
          {% set is_not_date = true if now().month != 12 or now().day != 7 else false %}

          {% if now().isoweekday() in (6,7) %}
             {{ is_state('sensor.time', '17:17') and is_not_date }} #Saturday, Sunday and not 12/7
          {% else %}
             {% if is_not_date %}
               {{ is_state('sensor.time', '17:18') }} #Not Saturday, Sunday and not 12/7
             {% else %}
               {{ is_state('sensor.time', '17:18') }} # Any day of week and 12/7
             {% endif %}
          {% endif %}

I don’t understand your question.

The latest template you posted will:

set is_not_date to false
today is Saturday so the first if will evaluate to true and evaluate this template:
{{ is_state('sensor.time', '17:17') and is_not_date }}
which will report false at any time today because is_not_date is false

If that’s not how you want it to behave then maybe change it to:
{{ is_state('sensor.time', '17:17') and not is_not_date }}
I say ‘maybe’ because I’m not certain how you want it to behave.

I’ll be honest with you and admit it was a helluva job to untangle the logic of your original template … and there’s a strong chance I failed to do it correctly. I also tried to retain the way you designed the date test. However, if I had to create the template from scratch, I would not make a “negative variable”, meaning I would make an is_date as opposed to an is_not_date. So instead of it checking if the month is not 12 and the day is not 7, it would check if the month is 12 and the day is 7.