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.

2 Likes

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.

2 Likes

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:

196

10/06/2024 

0

314

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.

I cant get this to works, i want to calculate how many days my HA-server has been running, using system monitor sensor value.
I have set up helper with this.

{{ (strptime(states('sensor.system_monitor_viimeinen_kaynnistys'), '%m/%d/%Y', today_at()) | as_local - today_at()).days }}

It returns 0, tried trimming but didnt work, when I replace states(‘sensor…’) with date like 10/05/2024, it gives me days in negative, i would like to get days in positive, but didnt figure it out.

What is the state of sensor.system_monitor_viimeinen_kaynnistys?

That’s because you are subtracting a later time from an earlier one.

I tried to change that order, but i didnt get any results, it allways reported Unknown.
That sensor gives May 22, 2024 at 20:33
Found other way, it worked. But i have read to not use as_timestamp(now() and it should be replaced by Time&Date, but didnt get that to work either, is my date formating wrong, tried time_date and date_time?

{{ (((as_timestamp(now()) - as_timestamp(states('sensor.system_monitor_viimeinen_kaynnistys')))) | int /60/1440) | round(0) }}

Do you recall where you read that?

Because it sounds like outdated advice.

I believe they are miss understanding the advice. The advice is most likely referencing datetime objects over the use of as_timestamp, which is suggested because datetime objects handle timezones better than as_timestamp.

{{ (now() - states('sensor.system_monitor_viimeinen_kaynnistys') | as_datetime).days }}

With the format in that sensor, you need something like:

strptime(states('sensor.system_monitor_viimeinen_kaynnistys'), "%B %d, %Y at %H:%M")

to get a datetime object out of it, then you’d need to assign a timezone.

Both of these return something, but don’t take timezones into consideration:

{{ time_since(strptime("May 22, 2024 at 20:33", "%B %d, %Y at %H:%M")) }}
{{ now()|as_timestamp - strptime("May 22, 2024 at 20:33", "%B %d, %Y at %H:%M")|as_timestamp }}

He’s claiming that as_timestamp is working unless I miss read something. Both as_timestamp and as_datetime use the same underlying code to determine the date from an iso (or some non-iso) formats.

If his format is truly May 22, 2024 at 20:33, then he will need to use strptime like you say.

{{ now() - strptime("May 22, 2024 at 20:33", "%B %d, %Y at %H:%M")|as_local}}

in his case

{{ (now() - strptime(states('sensor.system_monitor_viimeinen_kaynnistys'), "%B %d, %Y at %H:%M")|as_local).days }}
1 Like

I had the impression that the advice was about using Time&Date sensors instead of now() which would have been applicable a long, long time ago when now() didn’t serve to periodically update a template.

Anyways, we’ve yet to hear from JabeBRD.

1 Like

I completely forgot about those, been so long