The EPIC Time Conversion and Manipulation Thread!

yes, that a nice tool isn’t it :wink:

too bad the same last-triggered for scripts is still not surviving restarts.
Don’t now why, but the bug report got buried probably.

1 Like

You could always set an input_datetime to the time the switch was triggered. Those survive reboots and you could set up another sensor using it if needed to give you “how long has the switch been on?”.

He’s using an automation so it’s a moot point because those survive.

1 Like

I really need to start reading more closely…

fwiw, here’s the link to the issue for last_triggered not being restored as it should be:

Does anyone here knows how to properly use relative_time? I can not find suitable documentation/examples for me, so I created a new topic for help with obtaining the relative_time from an input_datetime sensor.

I may be wrong but I didn’t find any mention of the fromtimestamp method in this thread.

FWIW, it provides a quick way to convert a timestamp to a datetime object such as the timestamp attribute of an input_datetime. Obviously you can use strptime to convert an input_datetime’s state to a datetime object. However, here’s another way to compute it.

First we get the input_datetime’s timestamp:

{% set t = state_attr('input_datetime.test', 'timestamp') %}

We can convert it to a datetime object like this:

{% set dt = now().fromtimestamp(t) %}

The resulting datetime object is offset-naive which means it has no understanding of timezone. If we intend to use it in a calculation with an offset-aware datetime object, we will have to change it from “naive” to “aware”.

We can do that by setting its timezone to the same as the result of the now() function (which is an offset-aware datetime object and is your local time).

{% set dt = (now().fromtimestamp(t)).replace(tzinfo=now().tzinfo) %}

Now that we have converted the timestamp into a datetime object, it can be used in date calculations as seen in the last three lines of this screenshot:

Here it is, all in one statement:

{% set dt = (now().fromtimestamp(state_attr('input_datetime.test', 'timestamp'))).replace(tzinfo=now().tzinfo) %}
6 Likes

At some point I just want to add a ton of new methods that do all these things in 1 line of code. I’m busy until mid January though.

1 Like

for the wish list then, since you offer that 1 line of code in mid January :wink:

add a time_zone aware last_seen on the device_trackers, which is still somewhat of a mystery here and there.
check eg the life_360 last_seen, and compare that to the CC Composite last_seen, which allows to do https://github.com/pnbruckner/ha-composite-tracker#time-zone-examples

            {% set n = now() %}
            {{ (n.astimezone(state.attributes.last_seen.tzinfo).utcoffset() -
                n.utcoffset()).total_seconds()/3600 }}

I hope I managed to replace that for my person entities doing this:

          {% set state = states.person.marijn %}
          {{(state.last_updated.astimezone().utcoffset() -
            now().utcoffset()).total_seconds()/3600}}

since it has no last_seen, and last_updated comes closest…? (no way to test though, since I am here now, and not there…)

Hey,

I have been trying for the last two hours to convert a timestamp taken from an entity’s attribute to local time, but everything I tried hasn’t worked so far. I am growing desperate … maybe someone sees what I am not seeing.

This is how the entity looks:

The since attribute is in UTC.

This is how I create the sensor:

kala_last_changed:
      value_template: "{{ as_timestamp(states.binary_sensor.pet_kala.attributes.since) | timestamp_local }}"
      friendly_name: Kala Last Changed

I also tried to cast to a custom timestamp or use “state_attr(…)” but I always get the sensor to display UTC time.

Any idea what I am doing wrong?

Thanks in advance!

{% set hrmn = secs | timestamp_custom('%H:%M', false) %}

Use the false option parameter to cast as local time otherwise it defaults to utc

Thanks, I played around a bit more. This is super weird.

{{ states.binary_sensor.pet_kala.attributes.since }}
{{ as_timestamp(states.binary_sensor.pet_kala.attributes.since) | timestamp_custom('%H:%M', false)}}
{{ as_timestamp(states.binary_sensor.pet_kala.attributes.since) | timestamp_custom('%H:%M', true)}}

gives

2020-11-21 18:12:52
17:12
18:12

However, the entity changed its status at 19:13:53 PM (UTC+1, my local time which is the correct time)

It seems the “since” attribute is in UTC, but the system thinks it is local time or something like that. Is there anyway to manipulate this to get the correct time?

as_timestamp assumes local. So you’re converting UTC to local with as_timestamp which is incorrect.

I see - thanks!

I fixed it using this:

{{ as_timestamp(states.binary_sensor.pet_kala.attributes.since+'+00:00') | timestamp_local}}

Not sure if the most elegant, but it works :smiley:

If that makes it work it’s because the since attribute contains a string value (representing date and time) but is ‘offset-naive’ because it lacks timezone information.

Tip: when concatenating strings, use the tilde character ~ instead of the plus symbol.

Thanks for the tip!

I received a missing timezone error when trying to convert the string to datetime which is why I added the timezone.

Thanks for the help everyone!

checking the config I suddenly realized having quite a few of these sensor.date sensors:

      year:
        friendly_name: Year
        value_template: >
          {{strptime(states('sensor.date'),'%Y-%m-%d').strftime('%Y')}}

given the complexity of these conversions, Id rather write

          {{now().strftime('%Y')}}

and, to post another one:

          {% set month =  now().strftime('%m') %}
          {% if month in ['1','3','5','7','8','10','12'] %} 31
          {% elif month in ['4','6','9','11'] %} 30
          {% else %} {{'29' if states('sensor.year')|int//4 == 0 else '28'}}
          {% endif %}

and was wondering what could be the reason not to do this, other than maybe the more frequent updating happening each minute compared to the daily updating of the more complex conversion template?

You can also use now().month and now().year.

However that returns an integer value, not a string, so you would have to change the list’s items from string to integer.

          {% if now().month in [ 1, 3, 5, 7, 8, 10, 12 ] %} 31
          {% elif now().month in [ 4, 6, 9, 11 ] %} 30
          {% else %} {{'29' if states('sensor.year')|int//4 == 0 else '28'}}
          {% endif %}
1 Like

a yes, did that already in templates like this:

      remaining_days:
        friendly_name: Remaining days
        value_template: >
          {% set this = now() %}
          {% set next = this.month + 1 if this.month + 1 <= 12 else 1 %}
          {% set last = this.replace(month=next, day=1) %}
          {{(last.date() - this.date()).days}}

and will adapt to your suggestion too. 1 line less, and better readability indeed.
thanks.

Not sure how long you plan on running HA but your leap year detection won’t work.
For instance it would have said 2000 was a leap year and it’ll also cock up in 2400

I like to plan ahead
No y2k crap for me
:rofl: