timeesp32real-time-clock

ESP32 S2 - reading wrong time after manual set up


The issue: I have made a WEB app for setting. It has 2 options for RTC - SNTP and manual set up. SNTP works well. But manual not...

It received GET request like - rtc_datetime=2022-12-06T07%3A02

               if(httpd_query_key_value(qry, "rtc_datetime", temp, MAX_GET_QRY_VAL_LEN) == ESP_OK) {
                // decoding %3A to : etc
                decode(temp,value);
                //strcpy(value,temp);
                ESP_LOGI(TAG, "Time is: %s", value);

                if(value[0]=='\0') {
                    char resp[] = "Set manual time mode";
                    httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
                    return ESP_OK;
                }

                //tm.tm_year = (value[0] - '0')*1000 + (value[1] - '0')*100 + (value[2] - '0')*10 + (value[3] - '0') - 1900;//year
                tm.tm_year = string2int(value,4) - 1900;
                ESP_LOGI(TAG, "year is: %d", tm.tm_year);
                //tm.tm_mon = (value[5] - '0')*10 + (value[6] - '0'); //month
                tm.tm_mon = string2int(value+5,2) - 1;
                ESP_LOGI(TAG, "mon is: %d", tm.tm_mon);
                //tm.tm_mday = (value[8] - '0')*10 + (value[9] - '0');; // day
                tm.tm_mday = string2int(value+8,2);
                ESP_LOGI(TAG, "day is: %d", tm.tm_mday);
                //tm.tm_hour = (value[11] - '0')*10 + (value[12] - '0'); // hour
                tm.tm_hour = string2int(value+11,2);
                ESP_LOGI(TAG, "hour is: %d", tm.tm_hour);
                //tm.tm_min = (value[14] - '0')*10 + (value[15] - '0'); // minute
                tm.tm_min = string2int(value+14,2);
                ESP_LOGI(TAG, "min is: %d", tm.tm_min);
                tm.tm_sec = 0;

                time_t t = mktime(&tm);
                ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));

                struct timeval new;
                new.tv_usec = 0;
                new.tv_sec = t;

                settimeofday(&new, NULL);
                //localtime(&t);

                struct tm timeinfo2;
                timeinfo2.tm_sec = 0;
                timeinfo2.tm_min = 0;
                time_t now2;// = time(NULL);
                time(&now2);
                localtime_r(&now2, &timeinfo2);

                ESP_LOGI(TAG, "curr time - %4d-%2d-%2d %2d:%2d", timeinfo2.tm_year+1900, timeinfo2.tm_mon+1, timeinfo2.tm_mday, timeinfo2.tm_hour, timeinfo2.tm_min);
                ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));

                char resp[] = "Time is set";
                httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);

asctime(&tm) shows correct time from URL. But time in timeinfo2 has difference 17 minutes and 53 seconds...

Line by line log:

I (16452) web server: GET request: form=rtc_form&rtc_datetime=2022-12-06T19%3A21&rtc_tz=458
I (16452) web server: r0_form
I (16452) web server: r1_form
I (16452) web server: rtc_form
I (16462) system config: sntp: 0
I (16462) system config: rtc_tz: 458
I (16462) system config: Save /spiffs/rtc.json
I (16492) system config: Set: {"rtc_sntp":0,"rtc_tz":458}
I (16492) web server: Time is: 2022-12-06T19:21
I (16492) web server: year is: 122
I (16492) web server: mon is: 11
I (16502) web server: day is: 6
I (16502) web server: hour is: 19
I (16512) web server: min is: 21
I (16512) web server: The local date and time is: Tue Dec  6 19:21:00 2022

I (16522) web server: curr time - 2022-12- 6 19:38
I (16522) web server: The local date and time is: Tue Dec  6 19:38:53 2022

I have no idea what I do wrong....

                tm.tm_year = 2022 - 1900;
                tm.tm_mon = 0;
                tm.tm_mday = 0;
                tm.tm_hour = 0;
                tm.tm_min = 0;
                tm.tm_sec = 0;

                time_t t = mktime(&tm);

                ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));

                struct timeval new;
                new.tv_usec = 0;
                new.tv_sec = t;

                settimeofday(&new, NULL);

                struct tm timeinfo2;
                timeinfo2.tm_sec = 0;
                timeinfo2.tm_min = 0;
                time_t now2;
                time(&now2);
                localtime_r(&now2, &timeinfo2);

                ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));

So, this is the code without any data from GET request. Hm... What is a correct initialization for tm struct? I thing true is near... mktime() "makes" this issue or tm struct is wrong initialized. The same problem:

I (22892) web server: The local date and time is: Fri Dec 31 00:00:00 2021
I (22902) web server: The local date and time is: Fri Dec 31 00:17:53 2021

I add ctime() log for checking mktime() output, so it showes correct

time_t t = mktime(&tm);
ESP_LOGI(TAG, "Time from epoch t: %s", ctime(&t));
ESP_LOGI(TAG, "Time from tm: %s", asctime(&tm));

Console log:

I (18012) web server: Time from epoch t: Thu Dec  8 09:13:00 2022

I (18022) web server: Time from tm: Thu Dec  8 09:13:00 2022

Solution

  • I've found the same problem in espressif GitHub issues. It looks like the issue is in the settimeofday() function. So, I implemented the same workaround:

    settimeofday(&new, NULL);
    struct timeval get_set_time;
    gettimeofday(&get_set_time,NULL);
    int time_diff = get_set_time.tv_sec - new.tv_sec;
    ESP_LOGI(TAG, "Difference in time: %d", time_diff);
    new.tv_sec -= time_diff;
    settimeofday(&new, NULL);
    

    Log:

    I (15322) web server: Difference in time: 1073
    

    Moreover, the project was migrated to IDF 5.0 version — the bug is no longer there in the settimeofday(). So, the problem was solved.