I have the following code to parse a datetime string
received from GPS satellites into the struct tm
, and then use mktime()
to get the epoch
from it, the result is correct on my Debian machine, but wrong on my ESP32 with ESP-IDF
, do you have any suggestion on why this is happening, is something wrong with DST or timezone stuff?
#include "rs_time.h"
time_t time_from_gnss_info_time(const char * datetime_str){
time_t epoch;
struct tm tm;
sscanf(
datetime_str,
"M-----",
&tm.tm_year,
&tm.tm_mon,
&tm.tm_mday,
&tm.tm_hour,
&tm.tm_min,
&tm.tm_sec
);
epoch = mktime(&tm); // result is '1462765068' or Mon May 9 03:37:48 2016
printf("the date and time is: %s %ld ",ctime(&epoch), time(NULL));
return epoch;
}
the value for epoch
after using mktime()
when the datetime_str
is '20210913221332'
is: 1462765068
, also the ctime()
representation is : Mon May 9 03:37:48 2016
CodePudding user response:
.tm_year
is years since 1900..tm_mon
is months since January.mktime()
uses all members ofstruct tm
(except for.tm_wday, .tm_yday
) to form the return value. OP's code did not initialize/set.tm_isdst
or others -struct tm
may have more than usual 9 members. Initialize them all.mktime()
forms atime_t
assumingstruct tm
is a local time, not universal time which is usually what GPS provides. TZ adjustment may be needed - not yet shown.time_t
does not certainly match along
. Cast to a wide type. (time_t
may even be floating point.) and match specifiers.Add error checking.
time_t time_from_gnss_info_time(const char *datetime_str) {
// Code is likely scanning per the current daylight time setting.
// Use .tm_isdst = -1 to let mktime to determine it.
// Or use 0 for standard time or any value for daylight time.
// All other members are zeroed
// struct tm tm; // Not this
struct tm tm = {.tm_isdst = -1};
if (sscanf(datetime_str, "M-----", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
return -1;
}
// Adjust some members.
tm.tm_year -= 1900;
tm.tm_mon--;
time_t epoch = mktime(&tm);
printf("The date and time is: %s%lld\n", ctime(&epoch),
(long long) time(NULL));
return epoch;
}
int main(void) {
time_t t = time_from_gnss_info_time("20210913221332");
printf("%lld\n", (long long) t);
}
Output
The date and time is: Mon Sep 13 22:13:32 2021
1664290016
1631589212
Additional error checking possible: extra txt, spaces, signs, extreme values, ...