tags:

views:

1885

answers:

4

What's the best way to convert datetimes between local time and UTC in C/C++?

By "datetime", I mean some time representation that contains date and time-of-day. I'll be happy with time_t, struct tm, or any other representation that makes it possible.

My platform is Linux.

Here's the specific problem I'm trying to solve: I get a pair of values containing a julian date and a number of seconds into the day. Those values are in GMT. I need to convert that to a local-timezone "YYYYMMDDHHMMSS" value. I know how to convert the julian date to Y-M-D, and obviously it is easy to convert seconds into HHMMSS. However, the tricky part is the timezone conversion. I'm sure I can figure out a solution, but I'd prefer to find a "standard" or "well-known" way rather than stumbling around.


A possibly related question is Get Daylight Saving Transition Dates For Time Zones in C

A: 

How do you know which timezone the data was in at the time it was recorded? Does it indicate EDT vs EST (etc.)?

Joe
It was in "local" time when recorded. However, I don't necessarily know whether DST was in effect at the time, so the timezone offset may not be the same now that it was then.
Kristopher Johnson
+5  A: 

You're supposed to use combinations of gmtime/localtime and timegm/mktime. That should give you the orthogonal tools to do conversions between struct tm and time_t.

For UTC/GMT:

time_t t;
struct tm tm;
struct tm * tmp;
...
t = timegm(&tm);
...
tmp = gmtime(t);

For localtime:

t = mktime(&tm);
...
tmp = localtime(t);

All tzset() does is set the internal timezone variable from the TZ environment variable. I don't think this is supposed to be called more than once.

If you're trying to convert between timezones, you should modify the struct tm's tm_gmtoff.

Rick C. Petty
Thanks! I knew something like timegm() had to exist, but didn't know the name.
Kristopher Johnson
Glad to help. Time conversion can be a rather tricky area. It's usually a good idea to store everything in UTC whenever possible. Converting between timezones is even trickier!
Rick C. Petty
Yeah, unfortunately the system's designers chose local time as the "standard" timestamp format for the messaging protocol. I hate it when people do that.
Kristopher Johnson
There is no timegm in Windows.
stepancheg
+1  A: 

If you need to worry about converting date/time with timezone rules, you might want to look into ICU.

chrish
+1  A: 

If on Windows, you don't have timegm() available to you:

struct tm *tptr;
time_t secs, local_secs, gmt_secs;
time( &secs );  // Current time in GMT
// Remember that localtime/gmtime overwrite same location
tptr = localtime( &secs );
local_secs = mktime( tptr );
tptr = gmtime( &secs );
gmt_secs = mktime( tptr );
long diff_secs = long(local_secs - gmt_secs);

or something similar...