0

I like to calculate the difference of local time (in some timezone) and GMT in terms of number of seconds. I use the following code snippet:

time_t now = time(0); // GMT
time_t gmnow = mktime(gmtime(&now)); // further convert to GMT presuming now in local
time_t diff = gmnow - now;

But, I am getting a wrong difference. What I am doing here is querying the current time as GMT through time(0). Then presuming that is a local time, I call gmtime to add the GMT difference factor and re-convert to local time using mktime. This should have shown the difference of GMT and my timezone, but it is showing a extra difference of 1 hour (daylight savings).

For example, my current time is Thu Mar 13 04:54:45 EDT 2014 When I get current time as GMT, that should be: Thu Mar 13 08:55:34 GMT 2014 Considering this is current time, if I call gmtime, this should further proceed, and re-converting back should give me a difference of 4 hr, but I am getting a difference of 5hr.

Is gmtime usage wrong here? Also, how do I know current time zone as well as time in daylight savings?

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69

2 Answers2

1

Got it!

The following code snippet would solve this:

time_t now = time(0); // UTC
time_t diff;
struct tm *ptmgm = gmtime(&now); // further convert to GMT presuming now in local
time_t gmnow = mktime(ptmgm);
diff = gmnow - now;
if (ptmgm->tm_isdst > 0) {
    diff = diff - 60 * 60;
} 

The trick is to check tm_isdst flag, if applicable and if set, adjust one hour more to diff This works. Thanks to all for your time.

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • This works for most cases. There are a (very small, rare) set of places that observe other than a 1 hour DST change. – Anya Shenanigans Mar 13 '14 at 10:28
  • @Petesh Could this be any problem while running the portion of code, DST becomes effective, just before, just after in between time_t gmnow = mktime(ptmgm) call is made? – Dr. Debasish Jana Mar 15 '16 at 18:28
  • I think there could be an issue in the spring forward case, where there's a whole hour that simply 'doesn't exist' in localtime - you would have to test it yourself to be certain; but for the fall-back case; I think it's covered by the `tm_isdst` flag. Solaris has the variables `altzone` and `timezone` for the [#seconds of UTC offset in both cases](http://docs.oracle.com/cd/E19253-01/816-5168/6mbb3hrfk/index.html). – Anya Shenanigans Mar 15 '16 at 19:29
0

This can handle it in the correct way I think:

time_t t = time (NULL);
tm * srTM = localtime(&t);
setenv("TZ", "GMT0",1); //Change your timezone to GMT
time_t t2 = mktime(srTM);  
diff = difftime(t2,t);
setenv("TZ", "CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00", 1); //Reset your timezone to correct one (here CET)