RASBR
(Rami)
May 4, 2022, 12:46pm
212
Hi,
I am not very familiar with Jinja templates, mostly get syntax from all awesome guys posting in this community. however I couldn’t find what I am searching for.
I need to show the last changed time as follows:
If less than 24hrs to show ‘15 hours ago’ or ‘Today at 16:25’
If more between 24-48hrs to show ‘Yesterday at 16:25’
If more than 48hrs to show ‘Tuesday at 16:25’
I really appreciate any advice
Thanks in advance
RS
Rami, this may be taking your brief too literally, but try the following:
{% set last_changed = states.sensor.XXXX.last_changed %}
{%- set delta = (now() - last_changed | as_local).total_seconds() / 3600 %}
{%- set weekday = last_changed.strftime("%A") %}
{%- set time = last_changed.strftime("%H:%M") %}
{%- if delta < 24 %} {{ [ "Today at "~time, delta|round(0)~" hours ago" ] | random }}
{%- elif 24 < delta < 48 %} Yesterday at {{ time }}
{%- else %} {{ weekday~" at "~time}} {%- endif %}
RASBR
(Rami)
May 4, 2022, 3:49pm
214
Didgeridrew:
{% set last_changed = states.sensor.XXXX.last_changed %}
{%- set delta = (now() - last_changed | as_local).total_seconds() / 3600 %}
{%- set weekday = last_changed.strftime("%A") %}
{%- set time = last_changed.strftime("%H:%M") %}
{%- if delta < 24 %} {{ [ "Today at "~time, delta|round(0)~" hours ago" ] | random }}
{%- elif 24 < delta < 48 %} Yesterday at {{ time }}
{%- else %} {{ weekday~" at "~time}} {%- endif %}
Thank you very much Drew, This is perfect… I tried it. below my observation:
Current time 18:52 (GMT+3)
At first it displays ‘Today at 14:52’ then about 30 seconds later it displays ‘1 hours ago’
I think it has something to do with when the code/entity refreshes!
I will give it more time and see how it goes.
Much appreciate it though on the logic/code a lot to be learnt from for other stuff as well
That’s what I meant by “taking your brief too literally”…
You wrote:
The following clause causes it to randomly shuffle between the two formats every time the template refreshes:
{{ [ "Today at "~time, delta|round(0)~" hours ago" ] | random }}
You can switch it out for either {{ "Today at "~time }}
or {{ delta|round(0)~" hours ago" }}
finity
May 4, 2022, 4:15pm
216
this should get you what you want.
You will need to put your data in for the ‘time’ variable.
{% set time = states('input_datetime.both_date_and_time') %}
{% if as_timestamp(time) | timestamp_custom('%Y-%m-%d') == as_timestamp(now()) | timestamp_custom('%Y-%m-%d') %}
Today at {{ as_timestamp(time) | timestamp_custom('%H:%M') }} ({{ ((as_timestamp(now()) - as_timestamp(time)) / 3600 ) | int}} hours ago)
{% elif as_timestamp(time) | timestamp_custom('%Y-%m-%d') == (as_timestamp(now().replace(hour=0, minute=0, second=0)) - 3600) | timestamp_custom('%Y-%m-%d') %}
Yesterday at {{ as_timestamp(time) | timestamp_custom('%H:%M') }}
{% elif as_timestamp(time) < as_timestamp(now().replace(hour=0, minute=0, second=0)) - (3600 * 1) and as_timestamp(now()) - 84600 * 7 < as_timestamp(time) %}
{{ as_timestamp(time) | timestamp_custom('%A at %H:%M') }}
{% else %}
More than a week ago
{% endif %}
there may be a more elegant way to do it but this works in my testing.
see what you think.
2 Likes
RASBR
(Rami)
May 4, 2022, 4:16pm
217
LOL, indeed that was ‘literally’ but the ‘Today…’ format displays the GMT time not the local time
Ok, I understand now… Move the as_local
filter so that it is applied to the variable last_changed
the first two lines should be:
{% set last_changed = states.sensor.XXXX.last_changed | as_local %}
{%- set delta = (now() - last_changed).total_seconds() / 3600 %}
1 Like
RASBR
(Rami)
May 4, 2022, 5:03pm
219
Thank you @finity & @Didgeridrew for your help… Both solutions work flawlessly…
petro
(Petro)
May 4, 2022, 10:30pm
220
FYI, you guys can utilize today_at to make the template really easy to read without any fancy math.
{% set last_changed = states.binary_sensor.main_door.last_changed %}
{% if last_changed < today_at() - timedelta(days=1) %}
{{ last_changed.strftime('%A at %H:%M') }}
{% elif last_changed < today_at() %}
{{ last_changed.strftime('Yesterday at %H:%M') }}
{% else %}
{{ last_changed.strftime('Today at %H:%M') }}
{% endif %}
2 Likes
RASBR
(Rami)
May 4, 2022, 11:11pm
221
Wow… and I just finished modifying @finity 's to be:
{% set time = states('input_datetime.test_datetime_3') %}
{% set hrs = ((as_timestamp(now()) - as_timestamp(time)) / 3600 ) | int %}
{% set mins = ((as_timestamp(now()) - as_timestamp(time)) ) | timestamp_custom('%M') |int %}
{% if as_timestamp(time) | timestamp_custom('%Y-%m-%d') ==
as_timestamp(now()) | timestamp_custom('%Y-%m-%d') %}
Today at {{ as_timestamp(time) | timestamp_custom('%H:%M') }}
{% if hrs == 0 %}
({{ mins | int}} minute(s) ago)
{% elif hrs == 1 %}
({{ hrs | int}} hour ago)
{% else %}
({{ hrs | int}} hours ago)
{% endif %}
{% elif as_timestamp(time) | timestamp_custom('%Y-%m-%d') ==
(as_timestamp(now().replace(hour=0, minute=0, second=0)) - 3600)
| timestamp_custom('%Y-%m-%d') %}
Yesterday at {{ as_timestamp(time) | timestamp_custom('%H:%M') }}
{% elif as_timestamp(time) < as_timestamp(now().replace(hour=0, minute=0, second=0)) - (3600 * 1)
and as_timestamp(now()) - 84600 * 7 < as_timestamp(time) %}
{{ as_timestamp(time) | timestamp_custom('%A at %H:%M') }}
{% else %}
More than a week ago
{% endif %}
adding the following lines:
{% set hrs = ((as_timestamp(now()) - as_timestamp(time)) / 3600 ) | int %}
{% set mins = ((as_timestamp(now()) - as_timestamp(time)) ) | timestamp_custom('%M') |int %}
{% if hrs == 0 %}
({{ mins | int}} minute(s) ago)
{% elif hrs == 1 %}
({{ hrs | int}} hour ago)
{% else %}
({{ hrs | int}} hours ago)
{% endif %}
I will try your code @petro right away
RASBR
(Rami)
May 4, 2022, 11:39pm
223
Thanks Petro, this is great. Which Jinja reference would you recommend for learning and/or referencing such functions i.e. today_at()
The two links in the developer tools are always a good starting point.
https://jinja.palletsprojects.com/en/3.1.x/templates/
RASBR
(Rami)
May 5, 2022, 9:39am
225
I checked the ones at the HA Templates page… will re-check again though.
Much appreciate your advice. Thanks
Rami
petro
(Petro)
May 5, 2022, 10:50am
226
I think this is what you’re looking for:
{% set last_changed = states.binary_sensor.main_door.last_changed %}
{% if last_changed < today_at() - timedelta(days=6) %}
More than a week ago
{% elif last_changed < today_at() - timedelta(days=1) %}
{{ last_changed.strftime('%A at %H:%M') }}
{% elif last_changed < today_at() %}
{{ last_changed.strftime('Yesterday at %H:%M') }}
{% else %}
{{ last_changed.strftime('Today at %H:%M') }} ({{ relative_time(last_changed) }} ago)
{% endif %}
RASBR
(Rami)
May 5, 2022, 1:30pm
227
Hi Petro,
May I trouble you with one last thing… I’ve trying to get it to work with no luck after several trial, I guess I need to do some intensive reading about States and Attributes.
What if instead of last changed attribute (which changes after each restart, I want to use an input_datetime helper to make it persistant over re-start… how can I insert this in your code.
It keeps giving me error either no attribute or can’t use < between strings and datetime.
Sorry for the inconvenience
States are always strings, so you will need to convert the state of the Input datetime helper to a offset-aware datetime object by replacing the first line of the template:
{% set last_changed = states('input_datetime.XXXX') | as_datetime | as_local %}
2 Likes
RASBR
(Rami)
May 5, 2022, 1:57pm
229
Thank you big time. I can now see what I did wrong… I had the as_local filter before the | as_datetime… makes perfect sense now and works flawlessly.
Much appreciated
RS
I’m trying to format elapsed time into something like ##d ##h ##m or ##: ##: ##
Here’s what I’ve got so far:
{{ (as_timestamp(now()) - as_timestamp(states('sensor.uptime'))) | timestamp_custom('%dd %hh %mm') }
}
Which gives me 31d Dech 12m off an epoch of ~9000 which should be more like 0d 2h 30m. What’s the proper syntax to depict elapsed time from 0 instead of the start of the epoch?
petro
(Petro)
May 20, 2022, 2:40pm
231
This will be formatted ddd hh:mm:ss
{{ now() - states('sensor.uptime') | as_datetime | as_local }}
If you want a custom format, you have to do the math.
Here’s the math laid out…
@KameDomotics ,
@AcidSleeper
12 d, 5 h, 35 m format.
{%- set up_time = as_timestamp(now())-as_timestamp(states('sensor.hassio_drifttid_dagar')) %}
{%- macro phrase(name, divisor, mod=None) %}
{%- set value = ((up_time // divisor) % (mod if mod else divisor)) | int %}
{{- '{} {}'.format(value, name) if value | int > 0 else '' }}
{%- endmacro %}
{%- set values = [
phrase('w', 60*60*24*7),
…
With all that Python/Jinja2 is capable of…is that really the most compact way to convert/format seconds into another timeframe?