getting utc timestamp using strftime()

Petr picture Petr · May 23, 2012 · Viewed 7.6k times · Source

I am trying to encode current utc time into string using the strftimefunction:

time_t now;
struct tm nowLocal;
struct tm nowUtc;

now = time(NULL);
localtime_r(&now, &nowLocal);
gmtime_r(&now, &nowUtc);

So far so good: nowLocal contains current time in my timezone (CET), nowUtc contains utc time, the difference is exactly according to the tm_gmtoff value:

nowLocal: {tm_sec = 28, tm_min = 27, tm_hour = 13, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x8127a38 "CEST"}

nowUtc: {tm_sec = 28, tm_min = 27, tm_hour = 11, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 0, tm_gmtoff = 0, tm_zone = 0x3e9907 "GMT"}

Then I call strftime() with "%s" format to get the seconds since epoch:

char tsFromLocal[32];
char tsFromUtc[32];

strftime(tsFromLocal, sizeof(tsFromLocal), "%s", &nowLocal);
strftime(tsFromUtc, sizeof(tsFromUtc), "%s", &nowUtc);

The result seems strange to me. I expected to get exactly the same string from both strftime() calls as %s format is described as:

The number of seconds since the epoch, i.e., since 1970-01-01 00:00:00 UTC. Leap seconds are not counted unless leap second support is available.

But I got two different values:

tsFromLocal:"1337772448"

tsFromUtc: "1337768848"

and moreover the difference is not 7200 (tm_gmtoff) but 3600. Can anyone explain such behavior? Or is it a bug?

The reason why I am doing this is that I need to transfer the time value over the network and compare it to the current time on the target machine that can be in different time zone. On target machine I wanted to:

struct tm restoredUtc;
time_t restored;

strptime(tsFromUtc, "%s", &restoredUtc);
restored = timegm(&restoredUtc);

But I got:

restoredUtc:{tm_sec = 28, tm_min = 27, tm_hour = 12, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x8127a38 "CEST"}

So strptime() sets the tm_zone according to the current time zone anyway. But even if I would use timelocal() instead of timegm() I will not get correct value as it should be 11:27:28 CEST and not 12:27:28 CEST. Is this error related to different results of strftime()?

Any comments to this later part?

Answer

Tom Parker-Shemilt picture Tom Parker-Shemilt · Oct 16, 2012

You're probably best off just using GMT throughout given there's gmtime_r that'll always give you the same answer everywhere. If an individual machine wants to display in local time, that can be done later, but sticking to one timezone for storage and network transfer is a good idea, and GMT values are easy to get to.