Last active
December 20, 2021 23:22
-
-
Save jhgorse/63b147cbe54f6cb92347739eb558e92d to your computer and use it in GitHub Desktop.
make time locale work on windows wsl, macOS, and linux
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment