ESP32 set time offset

I want to load the time from my own server and set the ESP32 clock to the received time.
The time from my server is a php script that returns this:

<?PHP
	echo strtotime(date('Y-m-d H:i:s'));
?>

The EPS32 receives the time and sets the internal clock like this:

struct timeval tv;
tv.tv_sec = atol(receivedTime);
settimeofday(&tv, NULL);

I don’t want to set a timezone because every device can be placed around the world where there are different timezones so i want my php script to take care of that (in the future).

The only problem is that the EPS has 1 hour and 43 minutes time difference than the current time.
PHP shows the right time but the EPS converts it “wrong” to display the correct time.

To show the time, i use this code:

struct tm timeinfo;
if(!getLocalTime(&timeinfo)){
  Serial.println("Failed to obtain time");
  return;
}
Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");

If i add 6130 seconds to the php time, i get the correct time in the ESP32

What am i doing wrong here?

“atol” takes an integer, you are supplying a string with a formatted date and time. You need to extract the date and time values as individual tokens (strtok function) and use those to fill the “timeval” struct before setting the time.

Also, you might need to specify a time zone on the ESP in order to maintain a correct time.

I don’t want to set a timezone because every device can be placed around the world where there are different timezones so i want my php script to take care of that (in the future).

struct timeval tv;
tv.tv_sec = atol(receivedTime);
settimeofday(&tv, NULL);

Isn’t this code to set the time according to the elapsed seconds? tv_sec receives an integer if i am correct

if “receivedTime” is equal to the output from the PHP-script, “atol” will not work. Otherwise please look at this.

I am not sure if it has something to do with te atol, if i put this value hardcoded in the tv.tv_sec, it still gives the wrong time:

tv.tv_sec = 1620133061;

If i use this site to check the value since the epoch, it does give me the current correct time:
Epoch Converter - Unix Timestamp Converter

What is the value of “receivedTime” when passing it to “atol”?

The same, the received value now from the php script (after i atol it) is 1620133653
If i paste this value directly in my code i get the same wrong time.

How can the time be wrong for 1 hour and 43 minutes, i understand that i can be wrong 1 or 2 hours because of the timezone, but not some minutes

Hello,

I think it’s giving incorrect time because you don’t set the timezone environment variable, so maybe it uses garbage values because it’s not initialized or something…

Try add

setenv("TZ", "UTC", 1);
tzset();

This still doesn’t work and gives me the wrong time again.

    setenv("TZ", "UTC", 1);
    tzset();
    struct timeval tv;
    tv.tv_sec = _receivedTime;
    settimeofday(&tv, NULL);

I saw another example online and i tried it and this seems to work:

    timeval epoch = {_receivedTime, 0};
    const timeval *tv = &epoch;
    timezone utc = {0,0};
    const timezone *tz = &utc;
    settimeofday(tv, tz);

Now my time is correct apart from 2 hours (timezone) and a few seconds??, so i will figure out how to pass the timezone to recalculate it as well

So you are passing a value like “2021-05-04 10:20:30” to “atol” and expecting an integer with seconds since epoch to pop out? Good luck with that!

I am not doing that, strtotime converts the time to seconds which gives me the correct time in seconds since the epoch

Why are you not using the time() function in PHP instead of formatting and de-formatting?

I also tried and it gives me the exact same result. I used the strtotime function because i can add multiple hours to set the timezone, but i can do that with time() as well

Try to debug with something like:

Serial.println(receivedTime);
struct timeval tv;
tv.tv_sec = atol(receivedTime);
Serial.println(tv.tv_sec);
settimeofday(&tv);
tv.tv_sec = 0;
gettimeofday(&tv);
Serial.println(tv.tv_sec);
getLocalTime(..) or localtime(..);
Serial.println(the values from getLocalTime);

Otherwise you might want to consider using SNTP to set the time which is easy on the ESP32.

Your code gives me this:

1620138339
160
1233
Failed to obtain time
Failed to obtain time
Failed to obtain time
Failed to obtain time
Failed to obtain time
1620138370
[ New request ] - 1620138370
1620138370
-2146627463
2007878295
Wednesday, August 17 2033 07:58:15

Where [ New request ] loads the result from time() in php

I cannot see the declarations of the used data types, nor can I see how the data is received, so that’s tough to help.