Page 1 of 1

sentenv() not resulting in the expected behaviour

Posted: Mon Jan 04, 2021 7:14 pm
by wreyford
##Board:
ESP32-Wroom32E-Devkit4

##Environment:
VSCode, using Espressif ESP-IDF Extension

##Problem:
I'm trying to set the TimeZone correctly for South Africa after obtaining time from NTP.
The Time Zone according to different databases is:
UTC+2
Africa/Johannesburg
SAST (South African Standard Time)
ZA
We do not have daylight saving.

The code below gives the correct time, when zone set to SAST-2, and that is incorrect as SAST should be the correct time, not minus 2hours. SAST also gives the correct time.
It also gives the correct time when UCT-2 is selected, and we are definitely UTC+2
Strangely adding 2 hours to UTC, actually gives a time 4 hours behind our correct time.

Code: Select all

char strftime_buf[80];

    // Set TZ to Africa/Johannesburg, UTC+2
    // See link to the timezone variables: https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
    // See another link for tz-variables: https://remotemonitoringsystems.ca/time-zone-abbreviations.php
    // See http://www.cplusplus.com/reference/ctime/strftime/ for all the format parameters.
    
    setenv("TZ", "SAST-2", 1);     //"Africa/Johannesburg" The 1 indicates it should overwrite the current variable
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);

    setenv("TZ", "SAST", 1);     //South African Standard Time //"Africa/Johannesburg" The 1 indicates it should overwrite the current variable
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);

    // Set timezone to Africa/Johannesburg / GMT+2 Time
    setenv("TZ", "GMT+2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);

    // Set timezone to Africa/Johannesburg / GMT-2 Time
    setenv("TZ", "GMT-2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);

    // Set timezone to Africa/Johannesburg / UTC+2 Time
    setenv("TZ", "UTC+2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);

    // Set timezone to Africa/Johannesburg / UTC-2 Time
    setenv("TZ", "UTC-2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%A, %d %B %Y %H:%M:%S %Z", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in South Africa is: %s", strftime_buf);
  
The output is as follows:
Image

The current local time in South Africa is 20:35:19
SAST-2, UTC-2, GMT-2 gives correct time as 20:35:19, but should not give the correct time
UTC+2, GMT+2 gives incorrect time as 16:35:19, but should be giving the correct time
SAST gives correct time as 20:35:19, and should give the correct time.

Also the documentation can be upgraded to explain the setenv() parameters better.
The last integer i.e. sentenv("TZ","Zone",int) is not explained in your documentation, and after much searching appears to be 1 = overwrite.

Please help me to understand your implementation of the Time Zones, and against what database do you match them, as I don't understand how UTC-2 can give the correct time whereas we are definitely in UTC+2

Please add to the documentation a reference list of used Time Zones that you identify against.

Re: sentenv() not resulting in the expected behaviour

Posted: Tue Jan 05, 2021 3:50 pm
by ESP_Minatel
Hi,

The problem is on the definition of the TZ. Please consider the POSIX format.

POSIX Format

After the three letters abbreviation, you specify the amount of hours behind the UTC.

For "UTC-2" you should use "UTC2" and for "UTC+2" use "UTC-2".

Change your code as the following.

Code: Select all

    setenv("TZ", "GMT2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in GMT-2 is: %s", strftime_buf);

    setenv("TZ", "GMT-2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in GMT+2 is: %s", strftime_buf);

    setenv("TZ", "UTC2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in UTC-2 is: %s", strftime_buf);

    setenv("TZ", "UTC-2", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in UTC+2 is: %s", strftime_buf);
Output:
timezone.png
timezone.png (23.53 KiB) Viewed 3641 times

Hope this can help you!

Re: sentenv() not resulting in the expected behaviour

Posted: Wed Jan 06, 2021 5:29 am
by wreyford
ESP_Minatel - For "UTC-2" you should use "UTC2" and for "UTC+2" use "UTC-2".
Thx, that was my conclusion from the results, but I did not understand why.
Now at least UTC-2 correctly defining actual TZ of UTC+2 makes more sense.