Time difference - based on an datetime helper and template

Hi,
Is it possible to determine the time difference between the two in a template?

the first:
{{ as_datetime(states('input_datetime.test')).strftime('%d %B %y - %H:%M') }}

the second:
{{ now().strftime('%d %B %y - %H:%M') }}

so the first is based on a start time of an automation, when the automation stops the second comes into play. What I’m after is the time difference between them, so for instance an output like: 36 minutes
or 1h and 12 minutes.

Or is it easier to create a second helper that stores the date/time?

All you ever wanted to know about time manipulation in templates (and more):

1 Like
{{ time_since(as_datetime(states('input_datetime.test'))) }}
1 Like

input_datetimes do not store a timezone. So if your datetime is local, you need convert it to local time.

{{ as_local(as_datetime(states('input_datetime.test'))).strftime('%d %B %y - %H:%M') }}

1 Like

hm I’ve tested your example @Troon but I get an output like:
3 hours
the test input datetime sensor is set on: 2024-06-10 13:00:00
so I would expect an output like 2.5 hours?
Is it rounding the output?

@koying I saw the page and I’m still testing.
When I create another helper (datetime) for the end time, I get the output I expected but don’t ask me why:
{{states('input_datetime.test_end')|as_datetime - states('input_datetime.test')|as_datetime}}

output:
2:30:00

So I need to minus the end of the automation with the start to get the time the total automation ran?

You seem to be allergic to reading the documentation that I linked. Here’s the link again, and a screenshot of the relevant information that clearly explains to you how to do what you want:

image

It’s a bit annoying that I’ve had to explain all this when you had exactly the same answer from me recently:

yes you’re totally right, it’s a maze at times with all kinds of templates that do all kinds of things (on my side) to find the right one for this situation. but thanks for the reminder anyway.

If you need a difference between two times, it is easiest to convert them into epoch timestamps (number of seconds since 1970). For a helper, it is easy state_attr('input_datetime.xyz', 'timestamp')

That timestamp can get you into all sorts of trouble because the input_datetime is not datetime aware and the value could be UTC or your local timezone. That’s why it’s generally accepted to not use those attributes.

1 Like

Well… timestamps do have certain specifics, but can be very realiable when observing those (I am a programmer, might be biased :grinning:).

I have found out that input_datetime is not TZ aware, but the timestamp attribute it has “is always UTC”. As opposed to doing input_datetime | as_timestamp on TZ unaware value. That lead to incorrect timestamp.

So I found out to be most conveniet to use now() | as_timestamp for “in-memory” datetimes and state_attr(input_datetime, timestamp) for retrieving stored datetimes. And it makes sense and works :slightly_smiling_face:.

Yes, but as a programmer you should understand that datetime aware objects are better than timestamps. I.e. using {{ states(input_datetime) | as_datetime | as_local }} provides exactly that and can be directly used with timedelta objects making it so you can completely avoid unit conversions.

It takes your complex process to add a day:

state_attr('input_datetime.xyz', 'timestamp') + 24*60*60

into something explicit that tells you right in your function what it’s doing:

states('input_datetime.xyz') | as_datetime | as_local + timedelta(days=1)

Secondly, HA exclusively uses datetimes as inputs across the entire software. So your timestamp sensor will need to be converted to a datetime object if you want to use it as a trigger, or display it as relative time in the UI without needing templates everywhere.

1 Like

I consider {{ states(input_datetime) | as_datetime | as_local }} to be very brittle and prone to hard to debug issues. All it takes is to forget to filter it as_local and you will spend “hours” trying to debug your code logic instead of just fixing the time conversion. Especially for me in UTC+1, it is very subtle and can manifest into an issue in quite a long time.

I am not sure about the last paragraph you wrote. I am not using a timestamp sensor. I am just extracting the timestamp attribute from the input_datetime in places where it suits me instead of trying to filter it to a correct timezone :slightly_smiling_face:.

Anyway… I don’t really care how other do this. Everyone can have their prefered method. I am just adding my two cents :slightly_smiling_face:.

I’m sorry, but this just tells me you’ve never used it. If you forget as_local there’s an immediate error in your logs if you try to use it to do anything with input_datetime because it will create a non-timezone aware datetime object. There’s no debugging because you’ll see an error on screen in the template editor as well as in your logs. That is of course if you use it with any other datetime object. If you simply are trying to add 10 minutes to it, it will be a non datetime aware object that has an addtional 10 minutes. I.e. No error, no problem and it can be used to output to any message with ease (just like a tz aware datetime object).

And if you use it anywhere else, where a timezone is applied, you do not need to add as_local because the object will be datetime aware in utc and the math will work regardless.

The reason I’m replying like this, we don’t want to go back to the old days where every other forum post was questions about converting time. Your suggestion is exactly that, it’s pushing people towards the old ways. There’s a reason that epic time conversion thread has been dead for almost a year now, it’s because it’s much easier now. So while your perspective is fine, it’s just something that shouldn’t be shared in a thread that is over a year old with a working modern solution.

1 Like