The standard C run-time (CRT) time() function for windows is documented thus
“The time function returns the number of seconds elapsed since midnight (00:00:00), January 1, 1970, coordinated universal time, according to the system clock. The return value is stored in the location given by timer. This parameter may be NULL, in which case the return value is not stored.”
So you would think that UTC is immune from local timezone information.
In windows its not.
time_t ltime;
t = time(<ime);
t = 1163025749
The time in Reykjavik,ICELAND is (10:42pm) Wednesday
Change timezone
t = time(<ime);
t = 1163007749
The time in Reykjavik,ICELAND is (5:42pm) Wednesday
To be immune from timezone changes during execution of your application you need to call _tzset() before you call time()
While trolling through the documentation I found this foreboding Y2Kish gem.
“In Visual C++ 2005, time is a wrapper for _time64 and time_t is, by default, equivalent to __time64_t. If you need to force the compiler to interpret time_t as the old 32-bit time_t, you can define _USE_32BIT_TIME_T. This is not recommended because your application may fail after January 18, 2038; the use of this macro is not allowed on 64-bit platforms.”
I had similar problems with daylight savings when i was dealing with dates and times. I wanted my internal representations to be completely timezone free.
I would rather that the user always sets the time using the current timezone, or simply adds the timezone offset at the end of any calculation. Having the system assume things about timezones is just asking for trouble when you move an application from one machine to another. When i construct a Time object as 12 midnight, i dont want to find out that the system has added an hour for dalylight savings, thats just evil.
My primary concern in the solution below was with dst, but i think localtime() calls tzset() as well so you get the added bonus of not being affected by timezone changes.
http://www.opengroup.org/onlinepubs/009695399/functions/localtime_r.html
bool Time::Construct()
{
// We wan’t to create a localised time, including timezone offset as this should
// report the current time as seen on the system. No where else do these time
// routines deal with localised time. This is so that assigning a specific value
// to time doesn’t result in it being reported differently or coverted in any way.
// Times are often converted or taken from other sources and should be left alone
// unless we specifically want localised time like now.
timeb time;
ftime(&time);
struct tm * pointer = localtime((time_t*)&time.time);
struct tm local = *pointer;
local.tm_isdst=0;
time_t seconds = mktime(&local);
Construct(seconds);
return true;
}