Reputation: 135
I'm trying to get the UTC time from a localtime. Vice versa it works OK. I only have problems when I want to convert a localtime to a UTC one in order to update an RTC clock. This is what I'm doing:
Say that t
is a local timestamp.
char *tz = "GMT-2GMT,M3.5.0/3,M10.5.0/4";
t = 1311444000; // 23/07/11 18:00:00
set_TZ(tz);
gmt_time = gmtime(&t);
mktime(gmt_time);
printf("GMT Time: %s\r\n",asctime (gmt_time));
This gives me 18:00:00, when it should be minus the timezone.
How do I fix this problem?
Upvotes: 2
Views: 5529
Reputation: 213837
The problem here is that time_t
is supposed to represent the number of seconds (simplification, see footnote) since the epoch. This is not affected by time zones. If you add a time zone offset to a time_t
, none of the functions will work as expected. Part of the problem is that it is sometimes impossible to know how to correctly convert such a value to a POSIX timestamp -- when the clocks roll back in the fall, where I live the clocks will read 1:30 AM twice during the same day, and without more information you can't figure out what the UTC time is.
You'll need to convert to local calendar time before you can convert to a POSIX timestamp, at which point you can convert to UTC calendar time.
// NOTE: not reentrant
time_t local_to_posix(time_t t) {
struct tm *tm;
time_t tt;
tm = gmtime(&t); // No timezone compensation
tm->tm_isdst = -1; // Let mktime figure out daylight savings
// NOTE: this WILL be wrong for one hour each year
tt = mktime(tm); // Converts local time to POSIX timestamp
return tt;
}
You can then pass the result to gmtime
, which will give you the UTC calendar time.
Footnote: Strictly speaking, these timestamps are not UTC and do not measure the number of seconds since epoch. They are POSIX timestamps, which count seconds since epoch as if there were no leap seconds. This is probably irrelevant unless your realtime clock is an atomic clock.
Upvotes: 3
Reputation: 135
After further tests the following code this seems to work. Im in UTC+2 and currently in DST. The returned time for UTC is correct. I will to further test without DST and see what is returned.
struct tm tm;
struct tm *local_time;
char *tz = "GMT-2GMT,M3.5.0/3,M10.5.0/4";
time_t t;
tm.tm_hour = 18;
tm.tm_min = 0;
tm.tm_sec = 0;
tm.tm_wday = 0;
tm.tm_yday = 0;
tm.tm_year = (2011) - 1900;
tm.tm_mday = 22;
tm.tm_mon = 7 - 1;
tm.tm_isdst = -1;
set_TZ(tz);
t = mktime(&tm);
local_time = localtime(&t);
printf("Local Time: %s\r\n",asctime (local_time ));
local_time = gmtime(&t);
printf("UTC Time: %s\r\n",asctime (local_time ));
Output:
Local Time: Fri Jul 22 18:00:00 2011
UTC Time: Fri Jul 22 15:00:00 2011
Upvotes: 0