mktime() output not the same as the date utility

Mark B. mkbucc at gmail.com
Tue Oct 14 10:10:49 PDT 2008


Hi,

I can't figure out from the man pages why
mktime() is giving a different result than date -f.
Both strptime and mktime are supposed to use the
local timezone, as does date.

The output of date is correct; mktime() is an hour later.

What am I missing here?

Thanks,

m

$ uname -s; uname -r
FreeBSD
6.0-RELEASE-p9


$ gcc test.c
$ ./a.out
date -j -f "%Y-%m-%d %H:%M:%S" "2008-10-14 08:06: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


$ date -j -r 1223985981
Tue Oct 14 08:06:21 EDT 2008
$ date -j -r 1223989581
Tue Oct 14 09:06:21 EDT 2008


$ cat test.c
#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 *fmt    = "%Y-%m-%d %H:%M:%S";

/* Return seconds since epoch computed from date utility. */
time_t
expected()
{
        char             cmd[500] = {0};
        char             outbuf[4096];
        unsigned long    exp, act;
        int              rc;
        FILE            *pfp;

        /* date -j -f "%Y-%m-%d %H:%M:%S" "2008-10-14 08:06:21" +%s */
        (void) snprintf(cmd, sizeof(cmd),
            "date -j -f \"%s\" \"%s\" +%%s", fmt, time_s);

        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;

}


More information about the freebsd-questions mailing list