Hi, [Posting here because I think there is a potential manual improvement in this puzzle, which I will be happy to write up once I figure it out.]
I'm trying to figure out how to convert a string to seconds since epoch in the local timezone. When I use strptime() and mktime(), I get a result that is one hour off. My best guess is that mktime() expects tm_isdst but strptime() doesn't load it. But I don't know how to work around this. Or am I missing something else? Below is a short program that demonstrates the behavior and it's output. Thanks for any help, m $ ./a.out date -j 200810140806.21 +%s returns 1223985981 a.out: tm.tm_sec = 21 a.out: tm.tm_min = 6 a.out: tm.tm_hour = 8 a.out: tm.tm_mday = 14 a.out: tm.tm_mon = 9 a.out: tm.tm_year = 108 a.out: tm.tm_wday = 0 a.out: tm.tm_yday = 0 a.out: tm.tm_isdst = 0 a.out: tm.tm_zone = (null) a.out: tm.tm_gmtoff = 0 exp 1223985981, got 1223989581: delta = -3600 $ #include <sys/types.h> #include <sys/wait.h> #include <limits.h> #include <err.h> #include <float.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #define EXITOK(rc) (WIFEXITED(rc) && WEXITSTATUS(rc) == 0) static char *time_s = "2008-10-14 08:06:21"; static char *time_s_v2 = "200810140806.21"; static char *fmt = "%Y-%m-%d %H:%M:%S"; /* Return seconds since epoch computed using the date utility. */ time_t expected() { char cmd[500] = {0}; char outbuf[4096]; unsigned long exp, act; int rc; FILE *pfp; /* date -j 200810140806.21 +%s */ (void) snprintf(cmd, sizeof(cmd), "date -j %s +%%s", time_s_v2); if ((pfp = popen(cmd, "r")) == NULL) errx(1, "popen failed."); while (fgets(outbuf, sizeof(outbuf), pfp) != NULL) printf("%s returns %s", cmd, outbuf); if((rc = pclose(pfp)) == -1) errx(1, "pclose returns -1"); if (!EXITOK(rc)) errx(1, "%s didn't terminate normally", cmd); return (time_t) strtoul(outbuf, 0, 10); } /* Returns seconds since epoch using strptime() and mktime() */ time_t actual() { struct tm tm; time_t rval; rval = (time_t) 0; memset(&tm, 0, sizeof(tm)); if (strptime(time_s, fmt, &tm) == NULL) errx(1, "fmt '%s' didn't match '%s'", fmt, time_s); warnx("tm.tm_sec = %d", tm.tm_sec); warnx("tm.tm_min = %d", tm.tm_min); warnx("tm.tm_hour = %d", tm.tm_hour); warnx("tm.tm_mday = %d", tm.tm_mday); warnx("tm.tm_mon = %d", tm.tm_mon); warnx("tm.tm_year = %d", tm.tm_year); warnx("tm.tm_wday = %d", tm.tm_wday); warnx("tm.tm_yday = %d", tm.tm_yday); warnx("tm.tm_isdst = %d", tm.tm_isdst); warnx("tm.tm_zone = %s", tm.tm_zone); warnx("tm.tm_gmtoff = %lu", tm.tm_gmtoff); return mktime(&tm); } int main(void) { time_t act, exp; double delta; exp = expected(); act = actual(); delta = difftime(exp, act); if (fabs(delta) > DBL_EPSILON) { printf("exp %llu, got %llu: delta = %.0f\n", (long long int) exp, (long long int) act, delta); return 1; } else return 0; }