Probably because now() reports local time and as_timestamp does not.
Try them in the template tool and see what you get.
That’s what I did.
Maybe it will work if I put it in an actual template sensor.
EDIT: IT does not. Still off by 1 hour.
Anyone know?
try this instead:
{% set time_diff = (as_timestamp(utcnow()) - as_timestamp(states.input_datetime.example.last_changed)) | timestamp_custom('%H:%M') %}
{{ time_diff.split(':')[0]}} Hours {{ time_diff.split(':')[1] }} Minutes
That won’t work if the time is greater than 24 hours.
Here’s a calculation that works with any time difference.
For just hours and minutes, it would be:
{%- set word_for_and = 'and' %}
{%- set up_time = as_timestamp(utcnow())-as_timestamp(states.input_datetime.example.last_changed) %}
{%- macro phrase(name, plural_name, divisor, mod=None) %}
{%- set value = ((up_time // divisor) % (mod if mod else divisor)) | int %}
{%- set name = plural_name if value > 1 else name %}
{{- '{} {}'.format(value, name) if value | int > 0 else '' }}
{%- endmacro %}
{%- set values = [
phrase('hour', 'hours', 60*60),
phrase('minute', 'minutes', 60),
] | select('!=','') | list %}
{{ values[:-1] | join(', ') ~ ' ' ~ word_for_and ~ ' ' ~ values[-1] if values | length > 1 else values | first }}
true.
But I just answered the question of “hours & minutes”. Not “days, hours & minutes”.
Just trying to keep it simple until the requirements change.
Well, yeah that’s what the template I posted does. Just hours and minutes. But the hours aren’t capped at 24.
true, again.
the difference is in the simplicity.
yours is way more complicated. especially if there is no need for more than 24 hours.
Well there were no need for dates beyond 1999 so limiting to 24 hours should be fine
That still outputs 1 hour ahead of the actual time (it’s now 7 hours ago and your code outputs 8 hours)
This one works perfectly, thanks!
I know you said that you are using petro’s solution here is another template in my format that (I hope…) should be correct:
{% set time_diff = (as_timestamp(utcnow()) - as_timestamp(states.input_datetime.example.last_changed)) | timestamp_custom('%H:%M', false) %}
{{ time_diff.split(':')[0]}} Hours {{ time_diff.split(':')[1] }} Minutes
If you don’t mind could you test it for me to see if you get the correct results, please?
if it does work, TBH, I’m really not sure what’s going on with the first two attempts as to why they didn’t work. And I can’t explain what the reason is for why adding “false” to the custom timestamp formatting fixes the problem.
From my understanding and the testing I did in the template editor I am getting some strange results so I can’t explain it at all.
These shouldn’t matter. you can use as_timestamp(now()) or as_timestamp(utcnow()) and they both should return the same value. datetime objects have timezones associated with them and as_timestamp converts it into an integer that is based on UTC.
The issues lie in timestamp_custom('%H:%M', false)
. This assumes the input is a timestamp. When you subtract 2 timestamps, they are no longer timestamps. It’s now an int but it just so happens to work with timestamp_custom. But the problem with timestamp_custom is that it assumes Local so without the false it offsets the delta it by the timezone because timestamp_custom isn’t meant for time differences. It’s meant for moments in time, i.e. a timestamp int.
It wasn’t offsetting the time by just the timezone difference.
it was 19 hours off for me in my tests which I assume is because my TZ is +5. So, 24 - 5 = 19.
So it was doing some strange 24 hour time shift then offset the timezone.
It just surprised me since I’ve just never run into that before.
Take a look at the full date instead of just the hour and minute and you’ll see what’s happening.
I already had all of that displayed while testing this out and I’m still not seeing it:
Of course, I’m not doubting you I just can’t see it.
here is another one updated:
I’m talking about the difference, not the inputs. After you convert each an separate it into a timestamp, take the value and give it a full format:
{{ 123 | timestamp_custom('%Y-%m-%d %H:%M:%S %z') }}
1969-12-31 19:02:03 -0500
My TZ is -5, so I get back 5 hours before 1970.
That should just be 2 minutes and 3 seconds, but as you see… with my timezone, there’s a lot more crap going on.
but… with utc
{{ 123 | timestamp_custom('%Y-%m-%d %H:%M:%S %z', false) }}
1970-01-01 00:02:03 +0000
Ok, so the “funky 24 hour time shift” is because the timestamp_custom assumes local time until you convert it to UTC using “false”. Or you convert it to UTC some other way.
Kind of like you said above.
I get it now.
Thanks, again (and again, and again…just building up some additional thanks for the next inevitable time I ask for your help )
whispers…(but my way still works if you convert it to UTC…)…
Is it possible to use the state
instead of last_changed
?
I ask because, if I manually edit the value of the input_datetime sensor, to say a time that is 4 hours ago, the last_changed
will be right now and not 4 hours ago.
Is that possible?