Consider the following code:
time_t t;
t = time( NULL );
elog << "timezone: " << getenv( "TZ" )
<< ", current local time: " << asctime( localtime( &t ));
If I build this code using MSVC, and run it under the windows DOS shell, I get the correct local time:
timezone: , current local time: Wed Jul 25 13:05:08 2012
But if I run the same program under a cygwin shell like bash, this code returns GMT!
timezone: America/New_York, current local time: Wed Jul 25 18:05:08 2012
If I run this program in Linux or OsX, it also returns the correct local time.
Why?
@Update: It is now a year later and I found that the answer I gave below does not always work.
It seems that for some programs unsetting TZ does not always work. I don't know why. But there is a cumbersome workaround. Basically, right after you unset TZ, you have to check that local time is indeed no longer returning GMT, but only if you aren't actually in the GMT time zone, and compute a manual adjustment to time_t's when you call localtime() or maketime()
u64 localTimeOffset = 0;
static void unsetTz()
{
static bool unsetTZ = false;
if ( !unsetTZ )
{
putenv( "TZ=" );
unsetTZ = true;
// unsetting TZ does not always work. So we have to check if it worked
// and make a manual adjustment if it does not. For long running programs
// that may span DST changes, this may cause the DST change to not take
// effect.
s32 tzOffset = getTzOffset();
if ( tzOffset )
{
static char timeBuf[48];
char* s = &(timeBuf[0]);
struct tm* timeInfoGMT;
struct tm* timeInfoLocal;
time_t zero = 86400;
timeInfoGMT = gmtime( &zero );
u32 GMTHour = timeInfoGMT->tm_hour;
timeInfoLocal = localtime( &zero );
u32 localHour = timeInfoLocal->tm_hour;
if ( localHour == GMTHour )
{
// unsetting tz failed. So we have to make a manual adjustment
localTimeOffset = tzOffset * 60 * 60;
}
}
}
}
s32 getTzOffset()
{
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation( &tzInfo );
s32 tz = ( tzInfo.Bias / 60 );
return tz;
}
A call to local time:
time_t t = getAtTimeFromSomewhere();
t -= localTimeOffset;
timeInfo = localtime( &t );
A call to maketime:
struct tm timestr;
makeATMFromAStringForExample( time, timestr );
time_t timet = mktime( ×tr );
timet += localTimeOffset;
Good times.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…