Time format help

Hello,
i have an esp32 that works as the house’s alarm system.

When a sensor triggers, I would like to publish in mqtt data and time that the sensor triggered.

Currently, the function is like this:

time:
  - platform: sntp
    timezone: America/Sao_Paulo
    servers: a.st1.ntp.br
    id: sntp_time
text_sensor:
  - platform: template
    name: "Notify Alarme"
    internal: false
    id: notifica
    on_value:
      then:
        - lambda: |-
            if (x != "") {
              char str[25];
              time_t currTime = id(sntp_time).now().timestamp;
              strftime(str, sizeof(str), " %Y-%m-%d %H:%M:%S", localtime(&currTime));
              id(mqtt_client).publish("esp32alarme/select/estado_alarme/command", "triggered"); 
              id(mqtt_client).publish("esp_telegram/notifica_alarme", x + str );
            }

But the received time is wrong, the received time is 6 hours later.

I would like to know what I should do to adjust this time, since I’ve already tested changing the defined timezone, but it didn’t change the time at all.

This is an intriguing issue!
I think your code is correct, but it looks like the problem is caused by a bug, probably in the ESPHome Time integration?
I had a brief look at the ESPHome Time integration code on GitHub, and as I understand it, the code uses a Python package that contains the IANA tzdata zoneinfo, which is the complete list of TZ zones data.
To test it I created a simple ESPHome setup based on your code:

time:
  - platform: sntp
    timezone: America/Sao_Paulo
    servers: a.st1.ntp.br
    id: sntp_time
    on_time:
      # Every 1 minute
      - seconds: 0
        minutes: /1
        then:
          - lambda: |-
              char str[25];
              time_t currTime = id(sntp_time).now().timestamp;
              strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", localtime(&currTime));
              id(mqtt_client).publish("esp/notify_time", str );

This publishes the determined date time to MQTT every minute.
With this code I tested a lot of different timezone entries, and this was the result:

As can be seen, most of the South American TZ entries give wrong results, and most of the North American and European TZ entries return correct results. But this is not consistent.
When the result is incorrect the sign is almost always inverted, so for instance -3 becomes +3, resulting in a time off-set of +6 (like in your case for America/Sao_Paulo).
However, I still do not understand in which cases it is going wrong.
In most cases where it goes wrong the correct TZ difference is minus to UTC, but not always.
So often the timezone entry is not correctly translated to the applicable time difference.
It seems to be arbitrary? Or is someone seeing a logic behind this?

The good news however is that in your case you could solve it for now by using the generic time zone BRT+3 to get the correct time for Sao Paulo (Brasilia Time). See: Time in Brazil on Wikipedia and Specifying the Time Zone with TZ.

1 Like

I’m curious: Does the system receiving the alert know what time it is? Accurately and reliably?
Does the ESP really need to know what time it is, or just deliver the alert successfully?

If so, I have a design suggestion that may save you some effort:
Rather than burden the ESP with doing timestamping and possibly risking it having an error, just let the sensor … do the sensing which is its primary purpose, and let the receiving system do the timestamping.

2 Likes

A good point, but has to be answered by the OP.

Independent of this, we still have the TZ issue, so in the mean time I did some more digging, and I am now more convinced that this issue is caused by a bug in the current ESPHome Time integration.
It appeared that the by the ESPHome Time integration determined TZ zone data is shown in the compile logs, for instance like this for the “America/Sao_Paulo” time zone:

ESPHome_Time_sntp_20211117-1055

This shows that in the case of the “America/Sao_Paulo” time zone the determined TZ data gives:

Timezone: ‘<-03>3’

So I again run most of the tests, and registered the TZ data that ESPHome determined. See this table with the added ESPHome TZ data column:

This clearly shows that for almost all time zones with an erroneous outcome the TZ data contains “<” and “>” characters. This appears to be a valid format for TZ data, as can be read in “Theory and pragmatics of the tz code and data”.
But apparently this is not handled correctly by the ESPHome Time integration: the determined time offset has the sign inverted.
So next step is trying to find out where in the ESPHome source code this is going wrong. Wordt vervolgd…

By the way: the latest ESPHome release version 2021-11-0 includes an update of the Time integration dealing with TZ, but unfortunately this does not solve the discussed TZ problem.

It appears that this problem has already been reported on the ESPHome GitHub site:
Wrong timezone offset when sync time with home assistant”.
There it is explained that the problem is caused by the external newlib library that is used by the ESPHome Time integration, and it is not expected that this issue will get fixed anytime soon.
The solution as given there is to use a timezone format like XXXX-n in the cases that a “<>" format is seen in the TZ data by ESPHome.
Here XXXX is the timezone abbreviation and n is the offset with an inverted sign.
So for instance in Sao Paulo with an offset of -3 to UTC the timezone should be: BRT+3.
However, I think that the disadvantage of this “solution” is that it does not take DST into account, so this has to be set manually when applicable. For instance in Easter Island with an offset of -6 the timezone should probably be: EAST+6 for standard time but EASST+5 for DST.