I have been tearing my hair out trying to debug a time template within an automation, and have finally figured out what is going on.
I am in the UK so the time zone we are on is currently BST (GMT + 1).
All dates on the UI show BST correctly.
The Traces for the Automation show BST Correctly.
In the Template tool:
{{ Now() }} shows BST correctly
But:-
({{ state_attr(‘automation.my automation’, ‘last_triggered’) }} shows GMT! i.e it is an hour earlier.
A bit of further research shows that (weirdly) HA uses a mixture of the time that the OS uses and the time that is set within HA.
My Settings/Systems/General there seems to be a “bug” (?) in so far as the London time zone is shown as GMT + 0, But setting the HA to a GMT +1 setting has had no affect on the times i.e i am still getting a mixture of GMT and BST times.
It is possible that the date on the Pi that I am running HA on is incorrect, but I have no idea how to check this on a Pi running HAOS.
Can anyone provide any insight as to how to get the dates to match?
All times in the recorder database are stored in UTC regardless of any timezone settings. You don’t need to do anything to get times to “align”. HA (and the underlying python code) has no issue handling datetime objects with different timezones. Most everything should be UTC in the backend, and if you have a sensor with a timestamp class it will be displayed by your frontend in whatever timezone is chosen in your settings, regardless of what timezone is used in the sensor itself.
I think you are trying to solve a problem that does not exist.
To clarify, this is UTC, not GMT, and it is not an hour earlier. It is the same time but shown in UTC. In other words, 2024-04-25 12:00 UTC is the exact same moment in time as 2024-04-25 13:00 BST. The nice thing about UTC is you avoid any gaps in datetimes and any duplicate datetimes because DST isn’t a concept that applies to UTC.
I think that when trying to compare two times, last_triggered and now() and those times, have , at any given time, a one hour difference, then by most rational observers that is a “problem”.
If an HA expert knows the reason and believes that it is logical and that “everyone knows you should convert to timestamp” then fair enough. But to an inexpert user it still presents as a “problem”.
It might be easier to describe / show what you’re trying to do?
If you’re looking at the output of {{ state_attr('automation.my_automation', 'last_triggered') }} in the Developer Tools then you’ll see the value in UTC, but if you add the automation to a dashboard card, compare that date to now(), work out the difference from now(), etc. then HA will handle it for you and the results should look correct to you.
The Use Case is that I wanted a template to ensure that an Automation (a good Morning announcement) only ran once day. There are a number of ways of doing this, indeed I used to have a pretty complex condition template to do so. But for various reasons I wanted it to be as simple as possible.
This is what I came up with:
Can’t get much easier than that. There is one obvious issue with this approach but it does not affect my Use Case
It worked, until when working late, the automation was firing continually between midnight and one. Debugging and comments here indicate that it was cause by attributes using UTC and the now() sensor using time zone.
Some suggestiions were made here, but I came to the conclusion that the following was the easiest solution.
When you use state_attr('automation.good_morning_kitchen', 'last_triggered') in the action block, you will get the time of the trigger event which just happened. The time of the previous trigger event is available through the self-reference variable this.
I think the moral of the story is if you are comparing dates or time, you don’t ever have to worry about timezones as long as you stay with datetime objects. If you extract a piece of information from the datetime object (for example by using the .day property) then you do have to worry about what time zone that object was using.
Drew’s example is good because it’s comparing two datetime objects to each other so the time zone that each one uses is completely irrelevant.
Also you are correct that an automation has to pass all conditions in the main condition block in order to update the last_triggered attribute.