localtime возвращает время по Гринвичу для программ Windows, работающих в оболочках cygwin

Рассмотрим следующий код:

time_t t;
t = time( NULL );
elog << "timezone: " << getenv( "TZ" ) 
     << ", current local time: " << asctime( localtime( &t ));

Если я соберу этот код с помощью MSVC и запущу его в оболочке Windows DOS, я получу правильное местное время :

timezone:, current local time: Wed Jul 25 13:05:08 2012

. Но если я запускаю ту же программу под оболочкой cygwin, например bash, этот код возвращает GMT!

timezone: America/New_York, current local time: Wed Jul 25 18:05:08 2012

Если я запускаю эту программу в Linux или OSX, она также возвращает правильное местное время.

Почему?

@Update :Прошел год, и я обнаружил, что ответ, который я дал ниже, не всегда работает.

Кажется, что для некоторых программ сброс TZ не всегда работает. Я не знаю почему. Но есть громоздкий обходной путь. По сути, сразу после того, как вы отключите TZ, вы должны убедиться, что местное время действительно больше не возвращает GMT, но только если вы на самом деле не находитесь в часовом поясе GMT,и вычислить ручную корректировку времени _t при вызове localtime ()или 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;
}

Звонок по местному времени:

  time_t t = getAtTimeFromSomewhere();
  t -= localTimeOffset;
  timeInfo = localtime( &t );

Вызов maketime:

 struct tm timestr;
 makeATMFromAStringForExample( time, timestr );
 time_t timet = mktime( &timestr );
 timet += localTimeOffset;

Хорошие времена.

7
задан Rafael Baptista 1 May 2013 в 00:47
поделиться