The EPIC Time Conversion and Manipulation Thread!

reserved for later

1 Like

This is an awesome thread and I’m going to steal it!

Just one curious thing…

My ISP usage reports time like this:

2019-03-29 14:27:02

Which is an utter PITA as I am reading it in via either MQTT or directly using a web hook to write to the sensor.

From my research, I believed that if I added a T in the middle like this:
2019-03-29T14:27:02 that this would be read as a LOCAL time and in fact that is exactly what happens… in Home Assistant… It was right. I set the device_class to a timestamp and then I could use the nifty format: datetime to display it in a friendly way on a card (This was when I was reading it into a sensor, not an attribute)

Anyway, after I did that, I looked on my iPad… and bugger me… it was ADDING the timezone to the date so it was saying ‘in 10 hours time’

Turned out I had to append the time zone to the end as well for my iPad to recognise it as a local date/time.

2019-03-29 14:27:02+11:00

Just a nice trap for iOS…

So I’m pretty sure the middle one is wrong. With the -5 on the end it means it’s in local time and the Timezone is -5 hrs to get GMT/UTC

Ie the ISO format of this time is 2018-12-14T14:57:27-05:00 which is local and in GMT it would be 2018-12-14T19:57:27Z (Z for Zulu or +00:00) At least that is what I have seen…

I’m glad you find it useful. That’s what it’s here for. :slightly_smiling_face:

I don’t think so but I’m open to being convinced.

GMT is five hours ahead of my timezone right now.

So to represent my timezone in UTC I have to subtract 5 hours from GMT to get to my local time. So GMT - 5 hours = my local time.

Looking quickly in wikipedia (ISO 8601 - Wikipedia ), if you want to represent your local time in UTC format you need to put in the timezone offset (-05:00 in my case). If no offset is specified then the time is considered to be in local time. If local time is GMT then the Z is added to make sure it is unambiguous that the local time is also GMT.

At least I think that’s what I’m getting from reading it.

And looking at your post again we may be saying the same thing but in a different way? But I wouldn’t say my statement there is “wrong”.

If it’s got a Timezone that isn’t 00:00 or z for Zulu it’s local time not GMT. The offset there says how it’s modified gmt. As I said when I read a local time in my iOS devices assumed they were gmt. Specifying the correct iso format with local time and +11 like we are now and everything works. Home Assistant was fine with no zone - it assumes local (which is the convention) iOS nor so much without the offset.

You are representing your local time in UTC format by putting in the timezone offset (-05:00 in my case).

I know. I said that. that’s why you need to have the timezone offset to define your local time in UTC format in terms of GMT. If there is no offset then it’s assumed to be local time. In the case that local time = GMT time then to make it clear that local time is also GMT when no offset is given then it’s customary per the ISO8601 standard to include at least the “Z” to signify that local time = GMT => it tells you unambiguously that local time (represented in UTC format) = GMT (represented in UTC format).

This all boils down to being a representation of local time in two different frames of reference. One is in relation to GMT (and needs to include the offset) and the other is assumed to be local time since it doesn’t include the offset.

Just wanted to say thanks for this thread, @finity. I find myself referring to it frequently. Maybe you should consider creating a version of it to put somewhere in the HA docs.

1 Like

Thanks for the kind words.

If I get the time maybe I’ll give your suggestion a try.

1 Like

sorry, need some guidance please.
Im in the UK (So UTC+1 at the moment) and i have an attribute in my sensor thats showing as UTC.
So it shows as being 00:05 when it was actually 01:05

{{ states.vacuum.rover.attributes.clean_start }}
value = 2019-07-27 00:00:05

how do i change this value to add 60mintues to it, or is there more of a global setting that would automatically pass the correct value into the source data?

You need the sensor to include the time zone in the string then it will display correctly. Anything without an explicit time zone definition is treated as being in local time so the best solution is to ensure the sensor includes the TZ.

Hi, I’m trying to build an if-then test to get something done only when now() is not inside a specific time interval of the day. This is my most recent, but still failed attempt:

{%- set t1 = as_timestamp(now())| timestamp_custom('%H:%M') %}
{% if strptime(t1, '%H:%M') < strptime('09:30', '%H:%M') and
      strptime(t1, '%H:%M') > strptime('12:30', '%H:%M') %}
  Do_Something
{%- endif %}

Can you help me out?

I think it’s not the time manipulation that isn’t working. It’s the logic.

you will never have a time now that is both before 09:30 and after 12:30 at the same time.

I think for how you describe the desired result that you will need to change the “and” to an “or”.

That way if now is before 09:30 it will be true or if now is after 12:30 it will be true but not in between.

You are of course absolutely right. Funny how I got stuck in my own mind-loop. I should have thought of that. Anyway, I solved it by using if not :wink:
But still, it puzzles me that I had to use a temporary varible (t1) in order to get HA to tolerate the syntax.

Yeah, I’m no expert at any of this. I spent the better part of 3 or 4 days working on the content of the first posts here to try to understand it. TBH, I still have to go back to my notes when working with the more complex stuff.

but technically I don’t think have to use a variable. You could just substitute the stuff after the “set t1 =” part into everywhere you have t1 in the rest of the template. but that would get really messy. it’s cleaner to use that variable.

and also to make it a bit simpler you didn’t have to convert now to a timestamp. You could have gone straight to a string then when you use strptime it would convert the string to a time object for the comparison:

{%- set t1 = now().strftime('%H:%M') %}
{% if strptime(t1, '%H:%M') < strptime('09:30', '%H:%M') or
      strptime(t1, '%H:%M') > strptime('12:30', '%H:%M') %}
  Do_Something
{%- endif %}

Interesting. But I tried to substitute everything after the “set t1=” directly into the if statement, but HA complained about token irregularities and what not.
I must say that I do find these things overly complex. And finding documentation without presumption that your are already a python or java programmer with 10 years experience, makes it even harder. Take for instance the strftime and strptime operators (I don’t even know if calling them operators is correct?), I assume that someone “made” up these two words with something logical in mind. So probably str means string, and time is of course obvious, but the letter ‘f’ and ‘p’ stuck in between there? What do those mean? It would have been nice to know. it makes it easier to remember if you know what meaning or words these letters represent… just a sigh :roll_eyes:
Anyway, thanks for your suggestion. I’ll try it later.For now, at least, it works as-is.

You definitely have to make sure the sysntax is right with no missing (), {} or quotes.

here it is without the t1 and it is working in the template editor:

as far as the p & f I really don’t know where they came from but it helps me remember which is which using strftime = “string from time” and strptime = not string from time :slightly_smiling_face: so it’s “time from string”.

That’s a good one :slightly_smiling_face:
Thank you so much for your assistance. However, sometimes I do not understand the do’s and dont’s of the template editor. It fails on this one:

{% as_timestamp(now())| timestamp_custom('%H:%M') %}

saying that as_timestamp is invalid, although we know it is valid. I was expecting the above to yield the current time as output.

It fails because you aren’t giving it a directive. the {% …%} requires you tell it to do something. Like set, if-else, etc.

this will not give an error but it won’t output anything to the screen:

{% set t = as_timestamp(now())| timestamp_custom(’%H:%M’) %}

it is just internally setting the variable t to the value of (as_timestamp(now())| timestamp_custom(’%H:%M’) )

if you just want to show an output of what’s happening inside the brackets you use the {{…}} notation.

so if you change the above to this:

{{ as_timestamp(now())| timestamp_custom('%H:%M') }}

it should work

Thank you so much. You’ve yet again solved one of the great syntax mysteries.
( I wonder what pleasure the creator had in making things so complex and completely unlogical) :shushing_face:

Who ? you mean balloob ? :rofl:

finity: could you have a look at “Chicken Eggs!” ??? - I think it needs your time wizzardry skills and I think I’m going to have to read this thread twice a day and practice for a month to get my head round this.
I don’t think it needs Phil’s “Sun Enhancement” just subtract one time from another, subtract a few more hours and then output as minutes.