Convert seconds to days, hours, minutes

I was using the original code but i wanted to shorten the ouput so i modified the code to output 00d 00h 00m. Much better IMO than the elongated 00 days, 00 hours, 00 minutes.

Heres the code:

value_template: >-
{% set time = (value | int) | int %}
{% set minutes = ((time % 360000) / 6000) | int %}
{% set hours = ((time % 8640000) / 360000) | int %}
{% set days = (time / 8640000) | int %}

{%- if time < 6000 -%}
  Less than a minute
{%- else -%}
  {%- if days > 0 -%}
    {{ days }}d
  {%- endif -%}
  {%- if hours > 0 -%}
    {%- if days > 0 -%}
      {{ ' ' }}
    {%- endif -%}
    {{ hours }}h
  {%- endif -%}
  {%- if minutes > 0 -%}
    {%- if days > 0 or hours > 0 -%}
      {{ ' ' }}
    {%- endif -%}
    {{ minutes }}m
  {%- endif -%}
{%- endif -%}
2 Likes

To contribute my version: it abuses Jinja’s whitespace control. Easily extendable to Months, Quarters,Years, etc.

edit //
It was breaking on exactly 60 minutes, 1 day, etc. Should be more robust now!

  # NOTE:
  # - define durations for the various UNITs of time
  #   * modulus helps to reduce "extras" of the larger time units
  # 
  # - now build the string
  #
  # for each UNIT of time that's greater than 1:
  #     if it's not the first loop iteration:
  #         append ", " to the string
  #     else:
  #         1. convert the DURATION to STR
  #         2. split DURATION on "."
  #         3. append the left part (the whole number) to the string
  #         4. append the UNIT to the string
  #
  # ...but if that's no UNITs, then we just started so
  # set the string to "just now"
  #
  - platform: template
    sensors:
      hass_uptime:
        value_template: >-
          {%- set uptime  = states.sensor.hass_uptime_minutes.state | round -%}
          {%- set sep     = ', ' -%}
          {%- set TIME_MAP = {
              'week': (uptime / 10080) % 10080,
               'day': (uptime / 1440) % 7,
              'hour': (uptime / 60) % 24,
            'minute': (uptime % 60)
          }
          -%}

          {%- for unit, duration in TIME_MAP.items() if duration >= 1 -%}
            {%- if not loop.first -%}
              {{ sep }}
            {%- endif -%}
              
            {{ (duration | string).split('.')[0] }} {{ unit }}

            {%- if duration >= 2 -%}
              s
            {%- endif -%}
          {%- endfor -%}

          {%- if uptime < 1 -%}
            just now
          {%- endif -%}
9 Likes

much better than the hacky version I was using which didnt display properly. Thanks for sharing :hugs:

Hi
i want ask will this code work with NUT ?

i want make the Runtime in minute or hour will work ?
i never use template before

thank you

Yes, I am using essentially the same code for mine.

- platform: template
  sensors:  
    nut_ups_runtime_friendly:
    friendly_name: 'Time Remaining'
    value_template: >- 
      {% set time = (states.sensor.nut_ups_battery_runtime.state | int) | int %}
      {% set minutes = ((time % 3600) / 60) | int %}
      {% set hours = ((time % 86400) / 3600) | int %}
      {% set days = (time / 86400) | int %}
    
      {%- if time < 60 -%}
        Less than a minute
        {%- else -%}
        {%- if days > 0 -%}
          {{ days }}d
        {%- endif -%}
        {%- if hours > 0 -%}
          {%- if days > 0 -%}
            {{ ' ' }}
          {%- endif -%}
          {{ hours }}h
        {%- endif -%}
        {%- if minutes > 0 -%}
          {%- if days > 0 or hours > 0 -%}
            {{ ' ' }}
          {%- endif -%}
          {{ minutes }}m
        {%- endif -%}
      {%- endif -%}
2 Likes

thanks for reply
it don’t work for me don’t know why ?
do i need to change the code or not ?

thank you

Yes, you will need to change sensor.nut_ups_battery_runtime to match whatever your sensor is but that should be all that’s needed

hello

sorry take my long time to try this i was busy i try change the sensor.nut_ups_battery_runtime but still not working my name same as you sensor.nut_ups_battery_runtime it give this error ?

thank you

If you’re using the exact same configuration as shown in @LJM9000’s post above: The indentation is wrong; all lines from friendly_name onwards must be indented by 2 more spaces.

1 Like

OK i try like you say the now give Configuration valid! but the time still in second

And have you changed your user interface configuration? That code does not change the way the original sensor stores and represents its data, it’s creating a new sensor.
In the entities card that currently displays all data about your UPS you will have to change the entity ID from sensor.nut_ups_battery_runtime to sensor.nut_ups_runtime_friendly.

1 Like

thank you exxamalte now is working
and thank you all

:smile::smile:

1 Like

why 10080 ?
Isn’t 1 week = 60sec * 60 min * 24h * 7day = 604800 ?

The uptime in that template sensor is given in minutes, not seconds.

This feels like a more accurate version :

          {%- set TIME_MAP = {
                        'w': (uptime / 604800) % 604800,
                        'd': (uptime / 86400) % 7,
                        'h': (uptime / 3600) % 24,
                        'm': (uptime / 60) % 60,
                        's': (uptime % 60)
                    }
          -%}
2 Likes

Certainly more accurate, but unnecessary for my needs. I believe the sensor will only update every 15 seconds anyway?

Mostly, the way I think of it is … “when will I ever care about the exact second my HASS instance started?” It’s mostly a for-fun sensor anyway. :slight_smile:

i fully agree, the sensors i’m converting into human-readable are updating once per hour, seconds, even minutes are of little importance.
The thing is, that your formulas for hours days & weeks are wrong.

@Tommmii I would encourage you to run some tests. uptime in minutes divided by the number of minutes in [hour, day, week] modulo the number of minutes in [hour, day, week] should yield the correct output. If you can demonstrate it does not, I’m happy to change the coding to fix!

from : Technicolor TG-789vac V2 DSL Stats

{%- set TIME_MAP = {
                    'week': (uptime / 604800) % 10080,
                    'day': (uptime / 86400) % 7,
                    'hour': (uptime / 3600) % 24,
                  'minute': (uptime % 60)
                }
                -%}

Also, one of the uptimes i’m tracking is at 1064848 seconds right now.
That converts to 1 w, 5 d, 7 h, 47 m, 28 s according to my calculation.
Confirmed by https://www.tools4noobs.com/online_tools/seconds_to_hh_mm_ss/

I’m sorry, I’m confused as to what the problem is. I receive a similar result of “1 week, 5 days, 7 hours, 47 minutes” with the code in my snippet. The smallest denomination in my snippet is minutes, so you would need to first divide 1,064,848 by 60.