// 2021 JHG // BSD 2 clause. Go nuts. #include <stdio.h> #include <string.h> #include <time.h> #include <assert.h> #if defined(_WIN32) || defined(WIN32) #include <windows.h> #include <winsock.h> #elif defined(__unix__) #include <sys/time.h> #endif #if _WIN32 # define timegm _mkgmtime #endif time_t local_utc_offset_from_seconds(time_t t) { if (t < 0) t = 0; struct tm* locg = localtime(&t); struct tm locl; memcpy(&locl, locg, sizeof(struct tm)); return (timegm(locg) - mktime(&locl)); } int local_utc_offset_seconds() { return (int)(local_utc_offset_from_seconds(0)); } int local_utc_offset_minutes() { return (int)(local_utc_offset_seconds()) / 60; } time_t read_ts(char buf[]) { //const time_t offset = 18000; struct tm epoch = {}; epoch.tm_mday = 2; // to workaround new handling in VC, add a day epoch.tm_year = 70; time_t offset = mktime(&epoch) - 60 * 60 * 24; // and subtract it again //printf("%10ld offset rts\n", offset); // 18000 -> 5 hours struct tm tm, *ptm; time_t ts; timeval tval; if (sscanf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &tval.tv_usec) != EOF) { //tm.tm_isdst = -1; // doesn't work tm.tm_isdst = 0; // does work printf("%04d-%02d-%02d %02d:%02d:%02d.%03ld read back\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tval.tv_usec); tm.tm_year -= 1900; tm.tm_mon -= 1; tval.tv_sec = mktime(&tm); // the issues start here printf("%ld local_utc_offset_from_seconds(tval.tv_sec)\n", local_utc_offset_from_seconds(tval.tv_sec)); ptm = localtime(&tval.tv_sec); printf("%d ptm->tm_isdst\n ", ptm->tm_isdst); printf("%ld tval.tv_sec = mktime(&tm) rts\n", tval.tv_sec); // ///////////////////////////// JHG TODO: here make it go assert(tval.tv_sec == 1630607588); // Thu Sep 02 2021 18:33:08 GMT+0000 tm.tm_isdst = 0 //assert(tval.tv_sec == 1630603988); // Thu Sep 02 2021 17:33:08 GMT+0000 tm.tm_isdst = 1 // Thu Sep 02 2021 17:33:08 GMT+0000 // Thu Sep 02 2021 13:33:08 GMT-0400 //printf("%ld (tval.tv_sec - offset) rts\n", (tval.tv_sec - offset)); //ts = (tval.tv_sec) * 1000 + tval.tv_usec; // tval.tv_usec is actually millis at the moment ts = (tval.tv_sec - offset) * 1000 + tval.tv_usec; // 1,630,585,988 * 1000 // Thu Sep 02 2021 12:33:08 GMT+0000 //ts = (mktime(&tm))*1000 + tval.tv_usec; printf("%ld ts rts\n", ts); return ts; } return -1; } int main() { char buf[] = "2021-09-02 13:33:08.994"; // verify here: https://www.unixtimestamp.com/index.php https://www.epochconverter.com/ const time_t tsm0 = 1630589588994; // Thu Sep 02 2021 13:33:08 GMT+0000 const time_t tsm1 = 1630585988994; // Thu Sep 02 2021 12:33:08 GMT+0000 const time_t ts0 = 1630589588; // Thu Sep 02 2021 13:33:08 GMT+0000 assert(read_ts(buf) == tsm0); //assert(read_ts(buf) == tsm1); const time_t epoch_plus_11h = 60 * 60 * 11; const int local_time = localtime(&epoch_plus_11h)->tm_hour; const int gm_time = gmtime(&epoch_plus_11h)->tm_hour; const int tz_diff = local_time - gm_time; printf("%d tz_diff\n", tz_diff); const time_t local_time0 = mktime(localtime(&epoch_plus_11h)); const time_t gm_time0 = mktime(gmtime(&epoch_plus_11h)); printf("local_time0 %ld mktime gmt %ld, local - gmt = %ld\n", local_time0, gm_time0, local_time0 - gm_time0); // !!! THIS CORRECTS FOR DST !!! //time_t rawtime = time(NULL); 1630603988 time_t rawtime = 1630603988; struct tm* ptm = gmtime(&rawtime); time_t gmt = mktime(ptm); ptm = localtime(&rawtime); time_t offset = rawtime - gmt + (ptm->tm_isdst ? 3600 : 0); printf("%i sec => %i hr %d isdst\n", (int)offset, (int)offset / 60 / 60, ptm->tm_isdst); printf("local_utc_offset_minutes() %d\n", local_utc_offset_minutes()); return 0; }