Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::mktime and timezone info

Tags:

c++

I'm trying to convert a time info I reveive as a UTC string to a timestamp using std::mktime in C++. My problem is that in <ctime> / <time.h> there is no function to convert to UTC; mktime will only return the timestamp as local time.

So I need to figure out the timezone offset and take it into account, but I can't find a platform-independent way that doesn't involve porting the whole code to boost::date_time. Is there some easy solution which I have overlooked?

like image 672
VolkA Avatar asked Feb 09 '09 23:02

VolkA


People also ask

What timezone does Mktime use?

mktime() always uses local time zone and converts from UTC If you're working with UTC times, you may be upset to find that mktime() always converts using your local time zone thus wrecking your UTC times.

How do I get current UTC time in C++?

The gmtime() function in C++ converts the given time since epoch to calendar time which is expressed as UTC time rather than local time. The gmtime() is defined in <ctime> header file.

What is Mktime in C?

C library function - mktime() The C library function time_t mktime(struct tm *timeptr) converts the structure pointed to by timeptr into a time_t value according to the local time zone.

What is Tm_gmtoff?

long int tm_gmtoff. This field describes the time zone that was used to compute this broken-down time value, including any adjustment for daylight saving; it is the number of seconds that you must add to UTC to get local time. You can also think of this as the number of seconds east of UTC.


2 Answers

timestamp = mktime(&tm) - _timezone; 

or platform independent way:

 timestamp = mktime(&tm) - timezone; 

If you look in the source of mktime() on line 00117, the time is converted to local time:

seconds += _timezone; 
like image 63
Serg Avatar answered Oct 09 '22 09:10

Serg


mktime() uses tzname for detecting timezone. tzset() initializes the tzname variable from the TZ enviroment variable. If the TZ variable appears in the enviroment but its value is empty or its value cannot be correctly interpreted, UTC is used.

A portable (not threadsafe) version according to the timegm manpage

   #include <time.h>    #include <stdlib.h>     time_t    my_timegm(struct tm *tm)    {        time_t ret;        char *tz;         tz = getenv("TZ");        setenv("TZ", "", 1);        tzset();        ret = mktime(tm);        if (tz)            setenv("TZ", tz, 1);        else            unsetenv("TZ");        tzset();        return ret;    } 

Eric S Raymond has a threadsafe version published in his article Time, Clock, and Calendar Programming In C

time_t my_timegm(register struct tm * t) /* struct tm to seconds since Unix epoch */ {     register long year;     register time_t result; #define MONTHSPERYEAR   12      /* months per calendar year */     static const int cumdays[MONTHSPERYEAR] =         { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };      /*@ +matchanyintegral @*/     year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR;     result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR];     result += (year - 1968) / 4;     result -= (year - 1900) / 100;     result += (year - 1600) / 400;     if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&         (t->tm_mon % MONTHSPERYEAR) < 2)         result--;     result += t->tm_mday - 1;     result *= 24;     result += t->tm_hour;     result *= 60;     result += t->tm_min;     result *= 60;     result += t->tm_sec;     if (t->tm_isdst == 1)         result -= 3600;     /*@ -matchanyintegral @*/     return (result); } 
like image 21
Daniel Näslund Avatar answered Oct 09 '22 07:10

Daniel Näslund