Astimezone() output differs from server local time zone

Hi Folks,

I’d greatly appreciate your insights on time zones. I haven’t found an answer on my own and I’m just banging my head against the wall at this point.

tl;dr: I have a remote deployment on GMT-3, while my local time is GMT-5. When executing HA templates, some pick up my server time zone, while others pick up my local time zone… it is a mess.

Setup
Proxmox 6.8.12-5-pve VM running HAOS 14.2, core 2025.2.4.

root@pve00:~# date
Wed Feb 19 02:22:38 AM -03 2025

Proper HA time zone configured via

  1. Profile → Time Zone (Use Server Time Zone)
  2. Settings → System- > General (GMT-3)

HA terminal add-on output matches server local time after setting up NTP server for DHCP on my remote router using the right NTP pools/servers.

➜  ~date
Wed Feb 19 02:23:19 -03 2025

Challenges
Some templates work great… others drive me crazy. In particular when trying to display an hourly weather forecast.

Working great:

{{ now() }}
2025-02-19 02:23:47.809414-03:00

Working awfully

{{ now().now() }}
2025-02-19 00:23:47.809432

{{ now().astimezone() }}
2025-02-19 00:23:47.809438-05:00

astimezone() is currently using the same time as the naive approach, which is actually my local time zone - two hours behind the server time zone.

Furthermore:

{{ utcnow().tzinfo }}
UTC

{{ now().tzinfo }}
America/Santiago

{{ now().astimezone().tzinfo }}
EST

If I try to get the weather forecast for the next hour, I get it on my local time zone, instead of the server time zone… needless to say, this is absolutely useless to me.

{% set forecast_time = (state_attr('sensor.forecast', 'forecast') | map(attribute='datetime') | list)[0] %}
{% set dt = strptime(forecast_time, '%Y-%m-%dT%H:%M:%S%z') %}
{{ dt.astimezone().strftime('%-I%p %z').strip() }}
1AM -0500

The expected output above should’ve been 3AM -0300.

What I’ve tried

  • Configuring Chrony to set up the system clock. Chrony log shows:
[02:05:12] INFO: Starting chronyd...
2025-02-19T05:05:12Z chronyd version 4.6.1 starting (+CMDMON +NTP +REFCLOCK +RTC +PRIVDROP +SCFILTER +SIGND +ASYNCDNS +NTS +SECHASH +IPV6 -DEBUG)
s6-rc: info: service legacy-services successfully started
2025-02-19T05:05:12Z Initial frequency -205.829 ppm
2025-02-19T05:05:16Z System's initial offset : 0.045135 seconds slow of true (slew)
2025-02-19T05:05:23Z Selected source 64.176.3.116 (cl.pool.ntp.org)
  • Setting up DHCP NTP server on remote router
  • reconfiguring and resetting everything through the GUI.

Yet, I still get astimezone() modifying server time zone by -5 instead of -3.

Request
All the posts I’ve found with a similar problem seemed to have been solved by the steps above - or at least these were the proposed solutions… If you can point me to any other solution, I’d greatly appreciate it.

Thank you very much in advance.

Just use the |as_local filter.

1 Like

That was absolute next level. Thank you so much!

Even knowing what to look for, I still didn’t see that many posts with it…

I was so not solving this by myself!

Edit: For anyone looking, this is how you would use it:

{% set forecast_time = (state_attr('sensor.forecast', 'forecast') | map(attribute='datetime') | list)[0] %}
{% set dt = strptime(forecast_time, '%Y-%m-%dT%H:%M:%S%z') | as_local %}
{{ dt.strftime('%-I%p %z').strip() }}
7PM -0300

Which is the correct output.

1 Like