You alluded to this fact, but it's important to note that the offset between UTC and the time in a time zone is not necessarily constant. If the time zone performs daylight saving (summer) time adjustments, the offset will vary depending on the time of year.
One way to find the offset is to take the time you're interested in, hand it to the localtime()
function, then look at the tm_gmtoff
field. Do this with the TZ
environment variable set to the zone name you're interested in. Here's an example that does so for the current time:
#include <time.h>
#include <stdio.h>
int main()
{
setenv("TZ", "America/Los_Angeles", 1);
time_t t = time(NULL);
struct tm *tmp = localtime(&t);
printf("%ld\n", tmp->tm_gmtoff);
}
At the moment this prints -25200, indicating that Los Angeles is 25200 seconds, or 420 minutes, or 7 hours west of Greenwich. But next week (actually tomorrow) the U.S goes off of DST, at which point this code will start printing -28800.
This isn't guaranteed to work, since the tm_gmtoff
field is not portable. But I believe all versions of Linux will have it. (You might have to compile with -D_BSD_SOURCE
or something, or refer to the field as __tm_gmtoff
. But in my experience it tends to work by default, as plain tm_gmtoff
.)
The other way is to go back and forth with gmtime
and mktime
, as described in Sam Varshavchik's answer.
Addendum: You asked about not using environment variables. There is a way, but unfortunately it's even less standard. There are BSD functions tzalloc
and localtime_rz
which do the job, but they do not exist on Linux. Here's how the code looks:
timezone_t tz = tzalloc("America/Los_Angeles");
if(tz == NULL) return 1;
time_t t = time(NULL);
struct tm tm, *tmp = localtime_rz(tz, &t, &tm);
printf("%ld\n", tmp->tm_gmtoff);
For me this prints -28800 (because PDT fell back to PST just a few minutes ago).
If you had it, you could also use localtime_rz
along with mktime
in Sam Varshavchik's answer. And of course Howard Hinnant's library is pretty obviously thread-safe, not requiring mucking with TZ
at all.
EDIT (OP): The code for localtime_rz
and tzalloc
can be downloaded from https://www.iana.org/time-zones and works on Ubuntu 14.04.