Relative_time including minutes?

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. :wink:

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 :laughing:)

whispers…(but my way still works if you convert it to UTC…)… :stuck_out_tongue_winking_eye:

1 Like

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?

yes it’s possible, but without knowing what input_datetime method you’re using, no one can help you. Post an image of the state or paste the output.

Like this?

Then you’ll have to convert it to a timestamp, which is no easy feat because it does not have a date or a timezone.

Hi,
I have several sensor configured in configuration.yaml template. I don’t want to use the same code for each sensor. I there any way to use function in configuration.yaml with argument datetime, which will return for example 10 seconds, 1 minute, 5 hours, 3 days…?

sensor:
  - platform: template
    sensors:

      xinxang_04_lastupdated:
        value_template: >-
          {% set time_diff =  (now()- states.sensor.viking_0203502038_e7_07_temperature.last_updated).total_seconds() | round(0) %}
          {% if time_diff > 86400 %}
          {{(time_diff / 86400) | int}} days
          {% elif time_diff > 3600 %}
          {{(time_diff / 3600) | int}} hours
          {% elif time_diff > 60 %}
          {{(time_diff / 60) | int}} minutes
          {% else %}
            {{time_diff}} seconds
          {% endif %}

It would be like this

 xinxang_04_lastupdated:
        value_template: >-
          {{ myfunction(states.sensor.viking_0203502038_e7_07_temperature.last_updated) }}

Is it possible that way?

Thanks

see this thread

Hi,

I don’t understand this code. It seems to me, it is a part of sensor template? So I should repeat the same code for each sensor template?

I would like to define a function somewhere (configuration.yaml?) which will do the math and It will be possible to call it from each sensor template. Is it possible? Any example for beginner?

Thanks

you have to copy/paste this code for every sensor. There is no way to define a function for use in multiple spots.

Probably worth a PR though.

There’s no simple way to do this and have it available in all templates. It becomes a chicken/egg scenario based on integration loading order.

1 Like

Actually I meant to suggest a FR (Feature Request) not a PR (Pull Request).

This file seems to contain the HA jinja template functions. https://github.com/home-assistant/core/blob/1210897f83f044e00763637a69e848a189713e24/homeassistant/helpers/template.py

Yes, what you’d need to do is create macro’s that can be accessed in the jinja environment. It’s just that the macros wouldn’t always exist on startup causing a litany of errors.

It’s an old thread, but by modifying the last line into two lines of the template @petro provided (thanks, way above my skills), I managed to limit the result to the biggest two only :

 {% set skip = -1 if (values|length) < 3 else 1-(values|length) %}    
 {{ values[:skip] | join(', ') ~ ' ' ~ word_for_and ~ ' ' ~ values[skip] if values | length > 1 else values | first  | default }}

So it for example results in
3 hours and 13 minutes
Instead of:
3 hours, 13 minutes and 36 seconds

Update: I restructured the code into one macro generating the text (max two levels deep):

{% macro phrase_duration(up_time) %}          
        {%- set word_for_and = 'and' %}
        {% set ns = namespace(values = []) %}
        {% set tags = [['week','weeks', 60*60*24*7, none],['day','days',60*60*24,7],['hour','hours', 60*60, 24],['minute','minutes',60,None],['second','seconds',1,60]] %}
        {% for name,plural_name,divisor,mod in tags %} 
           {%- set value = ((up_time // divisor) % (mod if mod else divisor)) | int %}
           {%- set name = plural_name if value > 1 else name %}
           {%- set text = '{} {}'.format(value, name) if value | int > 0 else ''  %}
           {%- set ns.values = ns.values + [text] %}
        {%  endfor -%}
        {% set values = ns.values | select('!=','') | list %}
        {% set skip = -1 if (values|length) < 3 else 1-(values|length) %}    
        {{ values[:skip] | join(', ') ~ ' ' ~ word_for_and ~ ' ' ~ values[skip] if values | length > 1 else values | first  | default }}
{% endmacro %}

Usage example:

{% from 'tools.jinja' import phrase_duration %}
{{ phrase_duration(as_timestamp(now())-as_timestamp(states.sensor.dryer_state.last_changed)) }}

Result : 5 hours and 32 minutes

I built a whole library that does this for you including your modification.

1 Like

Hi @petro
Thanks for pointing out your great library!
A question though. I can’t figure out which macro does what I made above.
If I understand correctly, your macros require to provide weeks, hours, minutes and / or seconds to select the preferred detail.
But my modification will simply show up to two levels of detail, starting with the biggest available. So depending the timespan the result can be:

  • Weeks [and days]
  • Days [and hours]
  • Hours [and minutes]
  • Minutes [and seconds]

Between the brackets is only given if the value is not zero

{% from 'easy_time.jinja' import custom_time %}
{{ custom_time(states.sensor.dryer_state.last_changed, 'hour,minute') }}

Edit, seems I need coffee. I don’t have this built in, easy add though. I’ll add it in the future.

1 Like