Days until template sensor

I have a date that is a string in the format 10/06/2023.

I need to have a sensor that shows the number of days to go until that date.

Where do I start with this?

I’m thinking that the string first needs to be converted into a date and then converted into number of days.

I’ll then need to compare that with today’s date.

I’d rather not have a finished solution, just some pointers as to where to start.

This will explain the how. So you can also set a date helper for this or another entity.


Copy-paste the following template into the Template Editor and confirm it reports the desired result.

{{ (strptime('10/06/2023', '%m/%d/%Y', today_at()) | as_local - today_at()).days }}

Replace '10/06/2023' with states('sensor.your_sensor') or whatever is needed to get the date string.

1 Like

Thank you! That works brilliantly.

I’m using {{ states('sensor.my_date')[-11:] }} to get the 10/06/23 and it returns the string correctly.

Substituting it into your template thus…

{{ (strptime(states('sensor.my_date')[-11:], '%m/%d/%Y', today_at()) | as_local - today_at()).days }}

… it just returns 0 as the result.

Am I expecting too much of it?
Does it need to be done in two steps?

The original string takes the form "196 hrs or 10/06/2024"

This is what I’m pasting into the Template Editor:

{{ states('sensor.my_date')[:3] }}

{{ states('sensor.my_date')[-11:] }}

{{ (strptime(states('sensor.my_date')[-11:], '%m/%d/%Y', today_at()) | as_local - today_at()).days }}

{{ (strptime('10/06/2023', '%m/%d/%Y', today_at()) | as_local - today_at()).days }}

And that returns this:





Which highlights another issue.

When the 196 hrs changes to 99 hrs the {{ states('sensor.my_date')[:3] }} it will return "99 ", as there are only two digits. Same problem when it reaches 9.

Is there a way to extract the number up to the first “space”?

Change [-11:] to [-10:] because the date string is ten characters long.

[-11:] will include a leading space which doesn’t match strptime’s pattern. As a consequence, strptime reports its default value which is today_at().

I looked at that, but changing it to -10 loses the 1, resulting in a date of 0/06/2024.

In principle though, should it work? If so then an erroneous character may well be the problem, as you suggest.

That behavior implies there’s a trailing space character in the original string.

Try this:

states('sensor.my_date')[-11:] | trim

Revised example:

{{ (strptime(states('sensor.my_date')[-11:] | trim, '%m/%d/%Y', today_at()) | as_local - today_at()).days }}
1 Like

Excellent. Thank you.

So, ‘trim’ removes just trailing spaces?

Is there something similar to deal with the varying lengths, as per my 196 to 99 hours problem above?
I don’t think there are leading spaces there but just extracting up to the first space would solve the problem.

trim removes leading and trailing white space.

If the string always contains hrs or you can use it as a delimiter in split(). The result will be a list containing two items, 99 and 10/06/2024 , that can be referenced by list index.

Try this in the Template Editor:

{% set x =  states('sensor.my_date').split(' hrs or ') %}
{{ x[0] }}
{{ x[1] | trim }}
1 Like

Thank you.

That works.

In English, for my understanding, it’s taking the string and removing everything on either side of what is in the split().

This then leaves a list, x, with each list item being referenced by [y].

You have taught me so much!

Thank you and have a great weekend.

1 Like

You’re welcome!

Please consider marking my post above with the Solution tag. It will automatically place a check-mark next to the topic’s title signaling to other users that this topic has been resolved. This helps users find answers to similar questions.

For more information about the Solution tag, refer to guideline 21 in the FAQ.