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) %}
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.
for the wish list then, since you offer that 1 line of code in mid January
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
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 %}
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
donāt know if thatās true but this would get around that
{% set start = now().replace(day=1) %}
{% set month = start.month + 1 if start.month < 12 else 1 %}
{% set year = start.year + 1 if start.month == 12 else start.year %}
{% set end = start.replace(year=year, month=month) %}
{{ (end-start).days }}
they both are leap yearsā¦? but yes, youāre right, I should have added the //400 in case of a centurialā¦
@petro @mariusthvdb
My apologies, I misremembered the rules
From Wikipedia : -
āEvery year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400. For example, the years 1700, 1800, and 1900 are not leap years, but the years 1600 and 2000 are.[5].ā
I think some Petro magic may be required as this is different to previous
the template here doesnāt care about any of that
True, I just re-read it.
Itās a sledgehammer to crack a nut though
Weāll test it when 2100 comes round