Need template assistance please

Hi All,

I’m trying to create a template sensor to provide ‘True’ if within one day of a calendar event and ‘False’ if not. I dont know much about templates so am fumbling my way through trying things with the template dev tool. Any help would be greatly appreciated.

I think it would be something like:

{% if as_timestamp(states.calendar.recycling_bin_day.attributes.start_time) - as_timestamp(states.sensor.date.state, "%Y-%m-%d" ) < 0000-00-01 %}True{% else %}False{% endif %}

but obviously not quite as this doesn’t work. I just don’t know the correct syntax

something close to this maybe?

{% if states.sensor.date == as_timestamp(states.calendar.recycling_bin_day.attributes.start_time) - ("%Y-%m-01") %}True{% else %}False{% endif %}

…which doesn’t work

I managed to find some bits and pieces on the forum to get me somewhere closer… I think

{% if as_timestamp(states.calendar.recycling_bin_day.attributes.start_time) - as_timestamp(now()) < 900 %}True{% else %}False{% endif %}

works in that it doesn’t error… However I don’t actually understand how the 900 works in the date / time other than apparently being seconds… I also need this template to give a ‘false’ if the date is ‘today’. Not sure how to move forward with this

I don’t use calendar, so can you tell me, is the start_time attribute a Python datetime? E.g., if you put the following in the Template editor, what do you get?

{{ state_attr('calendar.recycling_bin_day', 'start_time').hour }}

Assuming it is a datetime, then this might work for you:

sensor:
  - platform: template
    sensors:
      within_one_day:
        entity_id:
          - calendar.recycling_bin_day
          - sensor.time
        value_template: >
          {{ states.calendar.recycling_bin_day.attributes.start_time.strftime('%j')|int -
             now().strftime('%j')|int == 1 }}

strftime(’%j’) returns the day of the year of a datetime as a string. So I use the int filter to convert that to a number. Then it tests if the event’s day of the year is one more than today’s day of the year. If it is, then the event happens tomorrow. Since the template sensor uses now(), to get it to update as time changes I use entity_id, listing calendar.recycling_bin_day, as well as sensor.time (which updates every minute and, hence, causes the template to sensor update as well.) Instead of using entity_id, you could instead use an automation that updates this template sensor each midnight.

returns nothing at all in the template dev tool.

this is what shows in the states list:

Ok, then try this:

sensor:
  - platform: template
    sensors:
      within_one_day:
        entity_id:
          - calendar.recycling_bin_day
          - sensor.time
        value_template: >
          {% set e = strptime(
               states.calendar.recycling_bin_day.attributes.start_time,
               '%Y-%m-%d %H:%M:%S') %}
          {{ e.strftime('%j')|int - now().strftime('%j')|int == 1 }}

I should probably explain that I’m trying to create what would have been a calendar offset of -840 minutes since the Google calendar component doesn’t allow offsets of more than 2 digits, -840 doesn’t work.

I need to have a sensor which becomes true in the afternoon before the bin day, but false as of midnight going to the bin day. I then use the calendar entry itself to determine that today is a bin day. I need these separate for my GUI representation

Ok, then:

sensor:
  - platform: template
    sensors:
      within_one_day:
        entity_id:
          - calendar.recycling_bin_day
          - sensor.time
        value_template: >
          {% set e = strptime(
               states.calendar.recycling_bin_day.attributes.start_time,
               '%Y-%m-%d %H:%M:%S') %}
          {{ e.strftime('%j')|int - now().strftime('%j')|int == 1 and now().hour >= 12 }}
1 Like

that seems to work in the dev tool so I’ll have to change the calendar date and give it a few test runs. Thank you so much, you are seriously the template guru!

I just used your code with a test event and all seems good. Would you mind explaining how this works for me? I’m confused by the %j for a start!

I thought I did. :wink:

First it takes the start_time attribute, which is a string representation of a date & time, and uses strptime to convert that to a Python datetime object. now(), BTW, also returns a datetime object. Then it takes the datetime objects and uses their strftime methods to convert them to a string that contains a number that represents the day of the year (e.g., 1/31 is 31, 2/1 is 32, 2/2 is 33, etc.) Then those strings are converted to ints and subtracted. If the result is 1, then the event happens tomorrow. Lastly, since you only wanted the sensor to be True in the afternoon, I added the last part that returns True only if it’s in the afternoon.

Now that I think about it, this will not work if the event happens on 1/1 and today is 12/31. So the value_template should probably be:

        value_template: >
          {% set e = strptime(
               states.calendar.recycling_bin_day.attributes.start_time,
               '%Y-%m-%d %H:%M:%S') %}
          {% set n = now() %}
          {{ (e.strftime('%j')|int - n.strftime('%j')|int == 1 or
              e.month == 1 and e.day == 1 and n.month == 12 and n.day == 31) and
             n.hour >= 12 }}

So my guess is that the %j is referring to the 10th place in the string? which is the one that we are doing the calculation on? ie: 2018-11-23 becomes 1234-67-9j ?

strptime takes the string containing the date and time and converts it to a Python datetime object. Then the strftime method of the datetime object converts it to a string containing a number which represents the day of the year, starting with “001” for Jan. 1, “002” for Jan. 2, etc. The ‘%j’ is the format string which tells it what to convert the datetime object to. In this case, ‘%j’ means output the day of the year number. Does that help?

yes, thanks. I’ll have to do some more research on all this so I get a better understanding but this definitely helps. I’m guessing there are other format options (%j) that can be used to grab the month or the hour etc.

Just wanted to let you know that this also works for me Phil! Thanks again.
Made a sensor (with your template) of a google calendar (a webcal calendar from my local goverment about the trash) and made a notification on my phone and my girlfriends phone with node red.
Works like a charm!

1 Like

Hmm maybe i cheered a bit too soon. I used this exact code from Phil. I only changed the 12 o’clock to 20 o’clock and i changed name of the sensor and the name of the google calendar.
I all seem to work fine when i test it. But when i wait untill the next ‘bin-day’ the sensor entity is not changing from false to true at 20 o’clock.
When i restart home asssitant (today did this around 20:10 hours) the entity is changed directly to true. Then it will change automatically to false again at 24:00 hours (as intended). Do you guys have any idea what i am doing wrong?

Edit: this is the exact YAML code in my configuration.yaml

  - platform: template
    sensors:
      morgen_afval:
        entity_id:
          - calendar.afvalwijzer
          - sensor.time
        value_template: >
          {% set e = strptime(
               states.calendar.afvalwijzer.attributes.start_time,
               '%Y-%m-%d %H:%M:%S') %}
          {{ e.strftime('%j')|int - now().strftime('%j')|int == 1 and now().hour >= 20 }}

Please post your exact code. LOL!

1 Like

Have you added sensor.time to your configuration?

Hi Phil, do you mean that i have to add a seperate sensor time? No :relaxed:
Do you mean something like described here? :

If so, i guess only time enough…? So somethin like this:

sensor:
  - platform: time_date
    display_options:
      - 'time'

Yes. You listed sensor.time as one of the entities that should update your template sensor. If sensor.time is not defined in your system it can’t cause your template entity to update.