The EPIC Time Conversion and Manipulation Thread!

What does this report on your system?

{{ (utcnow() - as_datetime(state_attr("sensor.my_sensor_name","LastUpdated"))).seconds }}

Same result or different?

Is there? GMT = UTC, but Iā€™d be surprised if a source defines it as UTC+1

Yes, the stackoverflow thread that ā€˜confirms itā€™s zulu timeā€™ has recent posts from 2 separate wikipedia pages. 1 for normal time computing which lists it as zulu time, and 1 page on nautical time that references zulu as gmt and z meaning zero. Youā€™re welcome to google it yourself ā€œz at the end of timestampā€, just donā€™t accept the ā€˜most upvotedā€™ answer and read all the solutions. Youā€™ll find that people donā€™t agree on the subject.

From what it looks like, the ā€˜solutionā€™ post is old, and has more upvotes. However the link to the nautical page is less than a few months old with a climbing upvote.

This site indicates Zulu time is zero hours after GMT. Scroll past the calculator and the description states:

GMT representations, usage and related time zones

W3C/ISO-8601: International standard covering representation and exchange of dates and time-related data

Z - is the zone designator for the zero UTC/GMT offset, also known as ā€˜Zuluā€™ time
+00 - basic short
+0000 - basic
+00:00 - extended

Email/RFC-2822: Internet Message Format Date Standard, typically used for timestamps in email headers

+0000 - sign character (+) followed by a four digit time providing hours (00) and minutes (00) of the offset. Indicates zero hour and zero minutes time differences of the zero meridian.

Military/NATO: Used by the U.S. military, Chinese military and others

Zulu - Military abbreviation for GMT
Z - short form of ā€˜Zuluā€™

Output for

{{ (utcnow() - as_datetime(state_attr("sensor.my_sensor_name","LastUpdated"))).seconds }}

is

82838

How does it compare to the value (currently) computed using your original template?

Now as timestamp:       {{ as_timestamp(now()) }}
Attribute as timestamp: {{ as_timestamp(state_attr("sensor.my_sensor_name","LastUpdated")) }}
123-Test:               {{ (utcnow() - as_datetime(state_attr("sensor.my_sensor_name","LastUpdated"))).seconds }}
Attribute - now:        {{ (as_timestamp(state_attr("sensor.my_sensor_name","LastUpdated")))- as_timestamp(now())}}

displays as:

Now as timestamp:       1628169363.302744
Attribute as timestamp: 1628172942.0
123-Test:               82821
Attribute - now:        3578.697114944458

I donā€™t reach the same stackoverflow page as yours, apparently.

But the ISO 8601 except available defines the ā€œZā€ as ā€œthe UTC designator, added to the end of a time representation to indicate that a time of day is represented as UTC of dayā€ (https://www.iso.org/obp/ui/fr/#iso:std:iso:8601:-1:ed-1:v1:en), which leaves little place to interpretation :wink:

which is GMT or UTC1 :wink: , the debate is weather it means ā€œZULUā€ or not.

Lol. The ā€œz=zuluā€, you mean? Well, not really important, is it :wink:
Not sure what you mean by UTC1, though. Is it a synonym for UTC, or is it UTC+1?

Itā€™s just what the wikipedia page said. I assume it means utc seeing that GMT is UTC. Using GMT as a reference should have clued you in.

Could you link me to where ā€œUTC1ā€ is used?
Never saw that notation, and if it does indeed exists, quite confusingā€¦

I had interpreted LastUpdated to represent a datetime in the past, but the timestamp values shown above indicate it is greater than now, so itā€™s in the future. If thatā€™s true then the order of the subtraction in my template should be reversed.

{{ (as_datetime(state_attr("sensor.my_sensor_name","LastUpdated")) - utcnow()).seconds }}

itā€™s probably a typo on the page and should be UT1, which is universal time aka UTC aka GMT

1 Like
Now as timestamp:       {{ as_timestamp(now()) }}
Attribute as timestamp: {{ as_timestamp(state_attr("sensor.my_sensor_name","LastUpdated")) }}
123-Test:               {{ (as_datetime(state_attr("sensor.my_sensor_name","LastUpdated")) - utcnow()).seconds }}
Attribute - now:        {{ (as_timestamp(state_attr("sensor.my_sensor_name","LastUpdated")))- as_timestamp(now())}}

displays:

Now as timestamp:       1628171580.01422
Attribute as timestamp: 1628175169.0
123-Test:               3588
Attribute - now:        3588.9856350421906

It doesnā€™t make sense that ā€œLastUpdatedā€ is in the future.
The trick is probably to remove the ā€œZā€, as that datetime is actually in local time, not UTC

{{state_attr("sensor.my_sensor_name","LastUpdated").split('Z')[0]}}
1 Like

That looks to be working for me:

{{ (as_timestamp(now()) - as_timestamp(state_attr("sensor.my_sensor_name","LastUpdated").split('Z')[0]))}}

displays

19.010035037994385

Perfect; the two techniques should produce the same result.

Itā€™s not wrong. Your local time is definitely offset by one hour from UTC whereas the attributeā€™s time is in UTC. If the offset is due to DST, and the attribute never employs DST, then you will have to normalize the values (add/subtract DST when appropriate).

If this doesnā€™t report -1 then DST is in effect (and can be employed as a test for normalizing the datetime value):

{{ now().timetuple().tm_isdst }}

Thanks - guess Iā€™ll have to wait until October 31st to find out! :grinning:

Do you know for certain that the attributeā€™s value, despite indicating Zulu time, always represents your local time regardless of DST? Can the developer supply that information ā€¦ or will you truly have to wait until the next DST change to find out?

BTW, if the goal is to slice off the last character then it can be done neatly like this (instead of using split('Z')[0]):

state_attr("sensor.my_sensor_name","LastUpdated")[:-1]