Shine
Shine

Reputation: 3818

ESP32 setenv() and localtime() from UTC time string

please consider following code, it compiles and run on ESP32 board:

    unsetenv("TZ");
    String payload = http.getString();
    payload.replace("\"", "");
    Serial.print("Payload: ");
    Serial.println(payload);
    const char* format = "%Y-%m-%dT%H:%M:%S";
    strptime(payload.c_str(), format,& _time);

    //debug only
    Serial.print("Chamber time(UTC): ");
    char chDate[11] = "";
    char chTime[9] = "";
    strftime(chDate, 11, "%m/%d/%Y", &_time);
    strftime(chTime, 9, "%H:%M:%S", &_time);
    Serial.print(chDate);
    Serial.print(" ");
    Serial.println(chTime);

    int epoch_time = mktime(&_time);
    timeval epoch = { epoch_time, 0 };
    const timeval* tv = &epoch;
    settimeofday(tv, NULL);



    int rcode = setenv("TZ", "EST+5", 1);
    tzset();
    Serial.print("SetEnv reply");
    Serial.println(rcode);
    //VERIFICA
    struct tm now;
    getLocalTime(&now, 0);
    Serial.println(&now, " %B %d %Y %H:%M:%S (%A)");

producing the following output:

Payload: 2020-04-08T21:59:10.736+0000
Chamber time(UTC): 04/08/2020 21:59:10
SetEnv reply0
April 08 2020 21:59:10 (Wednesday)

I expected the last date to be a local time according to "EST+5" timezone, in this example. Infact, I followed this readme, as I am using a ESP32 board, that says:

To set local timezone, use setenv and tzset POSIX functions. First, call setenv to set TZ environment variable to the correct value depending on device location. Format of the time string is described in libc documentation. Next, call tzset to update C library runtime data for the new time zone. Once these steps are done, localtime function will return correct local time, taking time zone offset and daylight saving time into account

What am I missing/doing wrong, apart from my rusty C++? Perfect solution would be to use : format like ":Europe/Rome" Thanks

Upvotes: 0

Views: 9902

Answers (4)

Nugget
Nugget

Reputation: 63

In your original code...Replace:

int rcode = setenv("TZ", "EST+5", 1);

with:

int rcode = setenv("TZ", "EST5EDT", 1);

or:

int rcode = setenv("TZ", "EST5EDT,M3.2.0,M11.1.0", 1);

Upvotes: 0

lmurdock12
lmurdock12

Reputation: 1021

Here is the solution that worked for me...after a bunch of pain finding solutions when I tested on my local linux machine, but did not work on the esp32

My esp32 TZ variable was initially set to a CST timezone, I wanted to read in a UTC timestamp and convert it to a PDT timezone. Here is what I did:


# Set timezone to UTC
setenv("TZ", "GMT0",1);
tzset();

# Read in timezone of format 2023-03-14T00:00:00.000Z
struct tm tm;
sscanf(utc_time.c_str(), "%4d-%2d-%2dT%2d:%2d:%2d",
    &tm.tm_year,
    &tm.tm_mon,
    &tm.tm_mday,
    &tm.tm_hour,
    &tm.tm_min,
    &tm.tm_sec
);

# mktime is expecting tm_year & tm_mon based off year since 1900 and months since January
tm.tm_year -= 1900;
tm.tm_mon--;

time_t epoch = mktime(&tm);

# Set to the new timezone we want & convert it
setenv("TZ","PST8PDT",1);
tzset();

struct tm* out_tm;
out_tm = localtime(&epoch);

# Print it out
char out_str[15];
strftime(out_str,sizeof(out_str),""%A, %B %d %Y %I:%M:%S"",out_tm);
Serial.printf("Converted time is: %s\n",out_str);

Result:

Before time is: 2023-03-14T00:00:00.000Z
Converted time is: Monday, March 13 2023 05:00:00

Upvotes: 1

un-CharlieH
un-CharlieH

Reputation: 127

The TZ string "EST+5" might be unknown to the OS, supported by the fact your output showed UTC time. EST and EDT have been used for US Eastern or America/New York. Assuming this is a Linux-like OS, take a look in the /usr/share/zoneinfo/ path for the zones available, or try the tzselect command to see if you can find the correct TZ string.

Upvotes: 2

un-CharlieH
un-CharlieH

Reputation: 127

Try this sequence of C functions:

   time_t tnow;
   time(&tnow);
   struct tm when;
   errno_t ret = localtime_s(&when, &tnow);
   // struct tm *when = localtime(&tnow); // deprecated for some compilers

The getLocalTime() function is not standard C and may not honor tzset().

Upvotes: 0

Related Questions